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/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 7c0655b20..90a10d4da 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,9 +1,9 @@ -Thank you for sending your pull request. But first, have you included + ## Summary -Explain in one sentence the goal of this PR + Solve the issue: #___ @@ -14,4 +14,4 @@ Solve the issue: #___ ## What's new? -*Explain in details what this PR solve or improve. You can include visuals.* + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b8df7ab10..d11285ba4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ ubuntu-18.04, ubuntu-20.04 ] + os: [ ubuntu-18.04, ubuntu-20.04, ubuntu-22.04 ] python-version: ["3.8", "3.9", "3.10"] steps: @@ -70,7 +70,7 @@ jobs: if: matrix.python-version == '3.9' - name: Coveralls - if: (runner.os == 'Linux' && matrix.python-version == '3.8') + if: (runner.os == 'Linux' && matrix.python-version == '3.9') env: # Coveralls token. Not used as secret due to github not providing secrets to forked repositories COVERALLS_REPO_TOKEN: 6D1m0xupS3FgutfuGao8keFf9Hc0FpIXu @@ -100,7 +100,7 @@ jobs: - name: Mypy run: | - mypy freqtrade scripts + mypy freqtrade scripts tests - name: Discord notification uses: rjstone/discord-webhook-notify@v1 @@ -158,16 +158,7 @@ jobs: - name: Tests run: | - pytest --random-order --cov=freqtrade --cov-config=.coveragerc - - - name: Coveralls - if: (runner.os == 'Linux' && matrix.python-version == '3.8') - env: - # Coveralls token. Not used as secret due to github not providing secrets to forked repositories - COVERALLS_REPO_TOKEN: 6D1m0xupS3FgutfuGao8keFf9Hc0FpIXu - run: | - # Allow failure for coveralls - coveralls -v || true + pytest --random-order - name: Backtesting run: | @@ -229,7 +220,7 @@ jobs: - name: Tests run: | - pytest --random-order --cov=freqtrade --cov-config=.coveragerc + pytest --random-order - name: Backtesting run: | @@ -249,7 +240,7 @@ jobs: - name: Mypy run: | - mypy freqtrade scripts + mypy freqtrade scripts tests - name: Discord notification uses: rjstone/discord-webhook-notify@v1 @@ -259,6 +250,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.10" + + - name: pre-commit dependencies + run: | + pip install pyaml + python build_helpers/pre_commit_update.py + docs_check: runs-on: ubuntu-20.04 steps: @@ -271,7 +277,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v3 with: - python-version: 3.8 + python-version: "3.10" - name: Documentation build run: | @@ -288,6 +294,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 @@ -298,8 +307,12 @@ 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 + # Discord notification can't handle schedule events + if: (github.event_name != 'schedule') + permissions: + repository-projects: read steps: - name: Check user permission @@ -319,7 +332,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' @@ -330,7 +343,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v3 with: - python-version: 3.8 + python-version: "3.9" - name: Extract branch name shell: bash @@ -391,7 +404,7 @@ jobs: - name: Discord notification uses: rjstone/discord-webhook-notify@v1 - if: always() && ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false) + if: always() && ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false) && (github.event_name != 'schedule') with: severity: info details: Deploy Succeeded! 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 new file mode 100644 index 000000000..ee909185a --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,46 @@ +# 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" + hooks: + - id: flake8 + # stages: [push] + + - repo: https://github.com/pre-commit/mirrors-mypy + rev: "v0.942" + hooks: + - id: mypy + exclude: build_helpers + additional_dependencies: + - types-cachetools==5.0.1 + - types-filelock==3.2.5 + - types-requests==2.27.25 + - types-tabulate==0.8.9 + - types-python-dateutil==2.8.15 + # stages: [push] + + - 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/Dockerfile b/Dockerfile index 8f5b85698..5f7b52265 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.9.9-slim-bullseye as base +FROM python:3.10.4-slim-bullseye as base # Setup env ENV LANG C.UTF-8 diff --git a/README.md b/README.md index 02eb47e00..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: @@ -129,6 +137,7 @@ Telegram is not mandatory. However, this is a great way to control your bot. Mor - `/status |[table]`: Lists all or specific open trades. - `/profit []`: Lists cumulative profit from all finished trades, over the last n days. - `/forceexit |all`: Instantly exits the given trade (Ignoring `minimum_roi`). +- `/fx |all`: Alias to `/forceexit` - `/performance`: Show performance of each finished trade grouped by pair - `/balance`: Show account balance per currency. - `/daily `: Shows profit or loss per day, over the last n days. 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) diff --git a/config_examples/config_binance.example.json b/config_examples/config_binance.example.json index 8e622eeae..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", - "forcebuy_enable": false, + "force_entry_enable": false, "internals": { "process_throttle_secs": 5 } diff --git a/config_examples/config_bittrex.example.json b/config_examples/config_bittrex.example.json index d40ea6c5a..a0a5071dd 100644 --- a/config_examples/config_bittrex.example.json +++ b/config_examples/config_bittrex.example.json @@ -87,7 +87,7 @@ }, "bot_name": "freqtrade", "initial_state": "running", - "forcebuy_enable": false, + "force_entry_enable": false, "internals": { "process_throttle_secs": 5 } diff --git a/config_examples/config_ftx.example.json b/config_examples/config_ftx.example.json index f86da8ea0..c49898277 100644 --- a/config_examples/config_ftx.example.json +++ b/config_examples/config_ftx.example.json @@ -89,7 +89,7 @@ }, "bot_name": "freqtrade", "initial_state": "running", - "forcebuy_enable": false, + "force_entry_enable": false, "internals": { "process_throttle_secs": 5 } diff --git a/config_examples/config_full.example.json b/config_examples/config_full.example.json index 540e83af6..6382e1baf 100644 --- a/config_examples/config_full.example.json +++ b/config_examples/config_full.example.json @@ -15,10 +15,10 @@ "trailing_stop_positive": 0.005, "trailing_stop_positive_offset": 0.0051, "trailing_only_offset_is_reached": false, - "use_sell_signal": true, - "sell_profit_only": false, - "sell_profit_offset": 0.0, - "ignore_roi_if_buy_signal": false, + "use_exit_signal": true, + "exit_profit_only": false, + "exit_profit_offset": 0.0, + "ignore_roi_if_entry_signal": false, "ignore_buying_expired_candle_after": 300, "trading_mode": "spot", "margin_mode": "", @@ -54,9 +54,9 @@ "order_types": { "entry": "limit", "exit": "limit", - "emergencyexit": "market", - "forceexit": "market", - "forceentry": "market", + "emergency_exit": "market", + "force_exit": "market", + "force_entry": "market", "stoploss": "market", "stoploss_on_exchange": false, "stoploss_on_exchange_interval": 60, @@ -139,21 +139,21 @@ "status": "on", "warning": "on", "startup": "on", - "buy": "on", - "buy_fill": "on", - "sell": { + "entry": "on", + "entry_fill": "on", + "exit": { "roi": "off", - "emergency_sell": "off", - "force_sell": "off", - "sell_signal": "off", + "emergency_exit": "off", + "force_exit": "off", + "exit_signal": "off", "trailing_stop_loss": "off", "stop_loss": "off", "stoploss_on_exchange": "off", - "custom_sell": "off" + "custom_exit": "off" }, - "sell_fill": "on", - "buy_cancel": "on", - "sell_cancel": "on", + "exit_fill": "on", + "entry_cancel": "on", + "exit_cancel": "on", "protection_trigger": "off", "protection_trigger_global": "on" }, @@ -174,7 +174,7 @@ "bot_name": "freqtrade", "db_url": "sqlite:///tradesv3.sqlite", "initial_state": "running", - "forcebuy_enable": false, + "force_entry_enable": false, "internals": { "process_throttle_secs": 5, "heartbeat_interval": 60 @@ -182,6 +182,8 @@ "disable_dataframe_checks": false, "strategy": "SampleStrategy", "strategy_path": "user_data/strategies/", + "recursive_strategy_search": false, + "add_config_files": [], "dataformat_ohlcv": "json", "dataformat_trades": "jsongz" } diff --git a/config_examples/config_kraken.example.json b/config_examples/config_kraken.example.json index 69b00719a..c55dea6ba 100644 --- a/config_examples/config_kraken.example.json +++ b/config_examples/config_kraken.example.json @@ -95,7 +95,7 @@ }, "bot_name": "freqtrade", "initial_state": "running", - "forcebuy_enable": false, + "force_entry_enable": false, "internals": { "process_throttle_secs": 5 }, diff --git a/docker/Dockerfile.armhf b/docker/Dockerfile.armhf index 16f2aebcd..73fc681eb 100644 --- a/docker/Dockerfile.armhf +++ b/docker/Dockerfile.armhf @@ -1,4 +1,4 @@ -FROM python:3.9.9-slim-bullseye as base +FROM python:3.9.12-slim-bullseye as base # Setup env ENV LANG C.UTF-8 diff --git a/docs/advanced-backtesting.md b/docs/advanced-backtesting.md new file mode 100644 index 000000000..2a484da69 --- /dev/null +++ b/docs/advanced-backtesting.md @@ -0,0 +1,73 @@ +# Advanced Backtesting Analysis + +## 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 +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 need to run backtesting with the `--export` option set to `signals` to enable the exporting of +signals **and** trades: + +``` bash +freqtrade backtesting -c --timeframe --strategy --timerange= --export=signals +``` + +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. + +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 +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) +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: + +``` +--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 --enter_reason_list "enter_tag_a,enter_tag_b" --exit_reason_list "roi,custom_exit_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 +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 +timeframe or for informative timeframes) otherwise they will simply be ignored in the script +output. diff --git a/docs/advanced-hyperopt.md b/docs/advanced-hyperopt.md index 9dbb86b2d..7f1bd0fed 100644 --- a/docs/advanced-hyperopt.md +++ b/docs/advanced-hyperopt.md @@ -56,7 +56,7 @@ Currently, the arguments are: * `results`: DataFrame containing the resulting trades. The following columns are available in results (corresponds to the output-file of backtesting when used with `--export trades`): - `pair, profit_ratio, profit_abs, open_date, open_rate, fee_open, close_date, close_rate, fee_close, amount, trade_duration, is_open, sell_reason, stake_amount, min_rate, max_rate, stop_loss_ratio, stop_loss_abs` + `pair, profit_ratio, profit_abs, open_date, open_rate, fee_open, close_date, close_rate, fee_close, amount, trade_duration, is_open, exit_reason, stake_amount, min_rate, max_rate, stop_loss_ratio, stop_loss_abs` * `trade_count`: Amount of trades (identical to `len(results)`) * `min_date`: Start date of the timerange used * `min_date`: End date of the timerange used diff --git a/docs/backtesting.md b/docs/backtesting.md index f42221f8c..02d1a53d1 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} @@ -279,52 +279,59 @@ A backtesting result will look like that: |:-------------------|--------:|------:|-------:|--------:| | trailing_stop_loss | 205 | 150 | 0 | 55 | | stop_loss | 166 | 0 | 0 | 166 | -| sell_signal | 56 | 36 | 0 | 20 | -| force_sell | 2 | 0 | 0 | 2 | +| exit_signal | 56 | 36 | 0 | 20 | +| force_exit | 2 | 0 | 0 | 2 | ====================================================== LEFT OPEN TRADES REPORT ====================================================== | Pair | Buys | Avg Profit % | Cum Profit % | Tot Profit BTC | Tot Profit % | Avg Duration | Win Draw Loss Win% | |:---------|-------:|---------------:|---------------:|-----------------:|---------------:|:---------------|--------------------:| | ADA/BTC | 1 | 0.89 | 0.89 | 0.00004434 | 0.44 | 6:00:00 | 1 0 0 100 | | LTC/BTC | 1 | 0.68 | 0.68 | 0.00003421 | 0.34 | 2:00:00 | 1 0 0 100 | | TOTAL | 2 | 0.78 | 1.57 | 0.00007855 | 0.78 | 4:00:00 | 2 0 0 100 | -================ SUMMARY METRICS =============== -| Metric | Value | -|------------------------+---------------------| -| Backtesting from | 2019-01-01 00:00:00 | -| Backtesting to | 2019-05-01 00:00:00 | -| Max open trades | 3 | -| | | -| Total/Daily Avg Trades | 429 / 3.575 | -| Starting balance | 0.01000000 BTC | -| Final balance | 0.01762792 BTC | -| Absolute profit | 0.00762792 BTC | -| Total profit % | 76.2% | -| Trades per day | 3.575 | -| Avg. stake amount | 0.001 BTC | -| Total trade volume | 0.429 BTC | -| | | -| Best Pair | LSK/BTC 26.26% | -| Worst Pair | ZEC/BTC -10.18% | -| Best Trade | LSK/BTC 4.25% | -| Worst Trade | ZEC/BTC -10.25% | -| Best day | 0.00076 BTC | -| Worst day | -0.00036 BTC | -| Days win/draw/lose | 12 / 82 / 25 | -| Avg. Duration Winners | 4:23:00 | -| Avg. Duration Loser | 6:55:00 | -| Rejected Entry signals | 3089 | -| Entry/Exit Timeouts | 0 / 0 | -| | | -| Min balance | 0.00945123 BTC | -| Max balance | 0.01846651 BTC | -| Drawdown (Account) | 13.33% | -| Drawdown | 0.0015 BTC | -| Drawdown high | 0.0013 BTC | -| Drawdown low | -0.0002 BTC | -| Drawdown Start | 2019-02-15 14:10:00 | -| Drawdown End | 2019-04-11 18:15:00 | -| Market change | -5.88% | -=============================================== +================== SUMMARY METRICS ================== +| Metric | Value | +|-----------------------------+---------------------| +| Backtesting from | 2019-01-01 00:00:00 | +| Backtesting to | 2019-05-01 00:00:00 | +| Max open trades | 3 | +| | | +| Total/Daily Avg Trades | 429 / 3.575 | +| Starting balance | 0.01000000 BTC | +| 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 | +| | | +| Long / Short | 352 / 77 | +| Total profit Long % | 1250.58% | +| Total profit Short % | -15.02% | +| Absolute profit Long | 0.00838792 BTC | +| Absolute profit Short | -0.00076 BTC | +| | | +| Best Pair | LSK/BTC 26.26% | +| Worst Pair | ZEC/BTC -10.18% | +| Best Trade | LSK/BTC 4.25% | +| Worst Trade | ZEC/BTC -10.25% | +| Best day | 0.00076 BTC | +| Worst day | -0.00036 BTC | +| Days win/draw/lose | 12 / 82 / 25 | +| Avg. Duration Winners | 4:23:00 | +| Avg. Duration Loser | 6:55:00 | +| Rejected Entry signals | 3089 | +| Entry/Exit Timeouts | 0 / 0 | +| | | +| Min balance | 0.00945123 BTC | +| Max balance | 0.01846651 BTC | +| Max % of account underwater | 25.19% | +| Absolute Drawdown (Account) | 13.33% | +| Drawdown | 0.0015 BTC | +| Drawdown high | 0.0013 BTC | +| Drawdown low | -0.0002 BTC | +| Drawdown Start | 2019-02-15 14:10:00 | +| Drawdown End | 2019-04-11 18:15:00 | +| Market change | -5.88% | +===================================================== ``` ### Backtesting report table @@ -345,9 +352,9 @@ The column `Avg Profit %` shows the average profit for all trades made while the The column `Tot Profit %` shows instead the total profit % in relation to the starting balance. In the above results, we have a starting balance of 0.01 BTC and an absolute profit of 0.00762792 BTC - so the `Tot Profit %` will be `(0.00762792 / 0.01) * 100 ~= 76.2%`. -Your strategy performance is influenced by your buy strategy, your sell strategy, and also by the `minimal_roi` and `stop_loss` you have set. +Your strategy performance is influenced by your buy strategy, your exit strategy, and also by the `minimal_roi` and `stop_loss` you have set. -For example, if your `minimal_roi` is only `"0": 0.01` you cannot expect the bot to make more profit than 1% (because it will sell every time a trade reaches 1%). +For example, if your `minimal_roi` is only `"0": 0.01` you cannot expect the bot to make more profit than 1% (because it will exit every time a trade reaches 1%). ```json "minimal_roi": { @@ -362,11 +369,11 @@ Hence, keep in mind that your performance is an integral mix of all different el ### Exit reasons table The 2nd table contains a recap of exit reasons. -This table can tell you which area needs some additional work (e.g. all or many of the `sell_signal` trades are losses, so you should work on improving the sell signal, or consider disabling it). +This table can tell you which area needs some additional work (e.g. all or many of the `exit_signal` trades are losses, so you should work on improving the exit signal, or consider disabling it). ### Left open trades table -The 3rd table contains all trades the bot had to `forceexit` at the end of the backtesting period to present you the full picture. +The 3rd table contains all trades the bot had to `force_exit` at the end of the backtesting period to present you the full picture. This is necessary to simulate realistic behavior, since the backtest period has to end at some point, while realistically, you could leave the bot running forever. These trades are also included in the first table, but are also shown separately in this table for clarity. @@ -376,49 +383,51 @@ The last element of the backtest report is the summary metrics table. It contains some useful key metrics about performance of your strategy on backtesting data. ``` -================ SUMMARY METRICS =============== -| Metric | Value | -|------------------------+---------------------| -| Backtesting from | 2019-01-01 00:00:00 | -| Backtesting to | 2019-05-01 00:00:00 | -| Max open trades | 3 | -| | | -| Total/Daily Avg Trades | 429 / 3.575 | -| Starting balance | 0.01000000 BTC | -| Final balance | 0.01762792 BTC | -| Absolute profit | 0.00762792 BTC | -| Total profit % | 76.2% | -| Avg. stake amount | 0.001 BTC | -| Total trade volume | 0.429 BTC | -| | | -| Long / Short | 352 / 77 | -| Total profit Long % | 1250.58% | -| Total profit Short % | -15.02% | -| Absolute profit Long | 0.00838792 BTC | -| Absolute profit Short | -0.00076 BTC | -| | | -| Best Pair | LSK/BTC 26.26% | -| Worst Pair | ZEC/BTC -10.18% | -| Best Trade | LSK/BTC 4.25% | -| Worst Trade | ZEC/BTC -10.25% | -| Best day | 0.00076 BTC | -| Worst day | -0.00036 BTC | -| Days win/draw/lose | 12 / 82 / 25 | -| Avg. Duration Winners | 4:23:00 | -| Avg. Duration Loser | 6:55:00 | -| Rejected Entry signals | 3089 | -| Entry/Exit Timeouts | 0 / 0 | -| | | -| Min balance | 0.00945123 BTC | -| Max balance | 0.01846651 BTC | -| Drawdown (Account) | 13.33% | -| Drawdown | 0.0015 BTC | -| Drawdown high | 0.0013 BTC | -| Drawdown low | -0.0002 BTC | -| Drawdown Start | 2019-02-15 14:10:00 | -| Drawdown End | 2019-04-11 18:15:00 | -| Market change | -5.88% | -================================================ +================== SUMMARY METRICS ================== +| Metric | Value | +|-----------------------------+---------------------| +| Backtesting from | 2019-01-01 00:00:00 | +| Backtesting to | 2019-05-01 00:00:00 | +| Max open trades | 3 | +| | | +| Total/Daily Avg Trades | 429 / 3.575 | +| Starting balance | 0.01000000 BTC | +| 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 | +| | | +| Long / Short | 352 / 77 | +| Total profit Long % | 1250.58% | +| Total profit Short % | -15.02% | +| Absolute profit Long | 0.00838792 BTC | +| Absolute profit Short | -0.00076 BTC | +| | | +| Best Pair | LSK/BTC 26.26% | +| Worst Pair | ZEC/BTC -10.18% | +| Best Trade | LSK/BTC 4.25% | +| Worst Trade | ZEC/BTC -10.25% | +| Best day | 0.00076 BTC | +| Worst day | -0.00036 BTC | +| Days win/draw/lose | 12 / 82 / 25 | +| Avg. Duration Winners | 4:23:00 | +| Avg. Duration Loser | 6:55:00 | +| Rejected Entry signals | 3089 | +| Entry/Exit Timeouts | 0 / 0 | +| | | +| Min balance | 0.00945123 BTC | +| Max balance | 0.01846651 BTC | +| Max % of account underwater | 25.19% | +| Absolute Drawdown (Account) | 13.33% | +| Drawdown | 0.0015 BTC | +| Drawdown high | 0.0013 BTC | +| Drawdown low | -0.0002 BTC | +| Drawdown Start | 2019-02-15 14:10:00 | +| Drawdown End | 2019-04-11 18:15:00 | +| Market change | -5.88% | +===================================================== ``` @@ -439,7 +448,9 @@ It contains some useful key metrics about performance of your strategy on backte - `Rejected Entry signals`: Trade entry signals that could not be acted upon due to `max_open_trades` being reached. - `Entry/Exit Timeouts`: Entry/exit orders which did not fill (only applicable if custom pricing is used). - `Min balance` / `Max balance`: Lowest and Highest Wallet balance during the backtest period. -- `Drawdown (Account)`: Maximum Account Drawdown experienced. Calculated as $(Absolute Drawdown) / (DrawdownHigh + startingBalance)$. +- `Max % of account underwater`: Maximum percentage your account has decreased from the top since the simulation started. +Calculated as the maximum of `(Max Balance - Current Balance) / (Max Balance)`. +- `Absolute Drawdown (Account)`: Maximum Account Drawdown experienced. Calculated as `(Absolute Drawdown) / (DrawdownHigh + startingBalance)`. - `Drawdown`: Maximum, absolute drawdown experienced. Difference between Drawdown High and Subsequent Low point. - `Drawdown high` / `Drawdown low`: Profit at the beginning and end of the largest drawdown period. A negative low value means initial capital lost. - `Drawdown Start` / `Drawdown End`: Start and end datetime for this largest drawdown (can also be visualized via the `plot-dataframe` sub-command). @@ -455,7 +466,7 @@ You can get an overview over daily / weekly or monthly results by using the `--b To visualize daily and weekly breakdowns, you can use the following: ``` bash -freqtrade backtesting --strategy MyAwesomeStrategy --breakdown day month +freqtrade backtesting --strategy MyAwesomeStrategy --breakdown day week ``` ``` output @@ -471,7 +482,7 @@ freqtrade backtesting --strategy MyAwesomeStrategy --breakdown day month ``` -The output will show a table containing the realized absolute Profit (in stake currency) for the given timeperiod, as well as wins, draws and losses that materialized (closed) on this day. +The output will show a table containing the realized absolute Profit (in stake currency) for the given timeperiod, as well as wins, draws and losses that materialized (closed) on this day. Below that there will be a second table for the summarized values of weeks indicated by the date of the closing Sunday. The same would apply to a monthly breakdown indicated by the last day of the month. ### Backtest result caching @@ -492,24 +503,24 @@ Since backtesting lacks some detailed information about what happens within a ca - Buys happen at open-price - All orders are filled at the requested price (no slippage, no unfilled orders) -- Sell-signal sells happen at open-price of the consecutive candle -- Sell-signal is favored over Stoploss, because sell-signals are assumed to trigger on candle's open +- Exit-signal exits happen at open-price of the consecutive candle +- Exit-signal is favored over Stoploss, because exit-signals are assumed to trigger on candle's open - ROI - - sells are compared to high - but the ROI value is used (e.g. ROI = 2%, high=5% - so the sell will be at 2%) - - sells are never "below the candle", so a ROI of 2% may result in a sell at 2.4% if low was at 2.4% profit - - Forcesells caused by `=-1` ROI entries use low as sell value, unless N falls on the candle open (e.g. `120: -1` for 1h candles) -- Stoploss sells happen exactly at stoploss price, even if low was lower, but the loss will be `2 * fees` higher than the stoploss price -- Stoploss is evaluated before ROI within one candle. So you can often see more trades with the `stoploss` sell reason comparing to the results obtained with the same strategy in the Dry Run/Live Trade modes + - exits are compared to high - but the ROI value is used (e.g. ROI = 2%, high=5% - so the exit will be at 2%) + - exits are never "below the candle", so a ROI of 2% may result in a exit at 2.4% if low was at 2.4% profit + - Forceexits caused by `=-1` ROI entries use low as exit value, unless N falls on the candle open (e.g. `120: -1` for 1h candles) +- Stoploss exits happen exactly at stoploss price, even if low was lower, but the loss will be `2 * fees` higher than the stoploss price +- Stoploss is evaluated before ROI within one candle. So you can often see more trades with the `stoploss` exit reason comparing to the results obtained with the same strategy in the Dry Run/Live Trade modes - Low happens before high for stoploss, protecting capital first - Trailing stoploss - Trailing Stoploss is only adjusted if it's below the candle's low (otherwise it would be triggered) - On trade entry candles that trigger trailing stoploss, the "minimum offset" (`stop_positive_offset`) is assumed (instead of high) - and the stop is calculated from this point - High happens first - adjusting stoploss - - Low uses the adjusted stoploss (so sells with large high-low difference are backtested correctly) + - Low uses the adjusted stoploss (so exits with large high-low difference are backtested correctly) - ROI applies before trailing-stop, ensuring profits are "top-capped" at ROI if both ROI and trailing stop applies -- Sell-reason does not explain if a trade was positive or negative, just what triggered the sell (this can look odd if negative ROI values are used) +- Exit-reason does not explain if a trade was positive or negative, just what triggered the exit (this can look odd if negative ROI values are used) - Evaluation sequence (if multiple signals happen on the same candle) - - Sell-signal + - Exit-signal - ROI (if not stoploss) - Stoploss diff --git a/docs/bot-basics.md b/docs/bot-basics.md index e45e3d9ca..1acbca565 100644 --- a/docs/bot-basics.md +++ b/docs/bot-basics.md @@ -34,6 +34,7 @@ By default, loop runs every few seconds (`internals.process_throttle_secs`) and * Check timeouts for open orders. * Calls `check_entry_timeout()` strategy callback for open entry orders. * Calls `check_exit_timeout()` strategy callback for open exit orders. + * Calls `adjust_entry_price()` strategy callback for open entry orders. * Verifies existing positions and eventually places exit orders. * Considers stoploss, ROI and exit-signal, `custom_exit()` and `custom_stoploss()`. * Determine exit-price based on `exit_pricing` configuration setting or by using the `custom_exit_price()` callback. @@ -58,6 +59,7 @@ This loop will be repeated again and again until the bot is stopped. * Calculate entry / exit signals (calls `populate_entry_trend()` and `populate_exit_trend()` once per pair). * Loops per candle simulating entry and exit points. * Check for Order timeouts, either via the `unfilledtimeout` configuration, or via `check_entry_timeout()` / `check_exit_timeout()` strategy callbacks. + * Calls `adjust_entry_price()` strategy callback for open entry orders. * Check for trade entry signals (`enter_long` / `enter_short` columns). * Confirm trade entry / exits (calls `confirm_trade_entry()` and `confirm_trade_exit()` if implemented in the strategy). * Call `custom_entry_price()` (if implemented in the strategy) to determine entry price (Prices are moved to be within the opening candle). diff --git a/docs/configuration.md b/docs/configuration.md index 9ed45fff3..80cd52c5b 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. @@ -53,14 +53,63 @@ FREQTRADE__EXCHANGE__SECRET= Multiple configuration files can be specified and used by the bot or the bot can read its configuration parameters from the process standard input stream. +You can specify additional configuration files in `add_config_files`. Files specified in this parameter will be loaded and merged with the initial config file. The files are resolved relative to the initial configuration file. +This is similar to using multiple `--config` parameters, but simpler in usage as you don't have to specify all files for all commands. + !!! Tip "Use multiple configuration files to keep secrets secret" You can use a 2nd configuration file containing your secrets. That way you can share your "primary" configuration file, while still keeping your API keys for yourself. + ``` json title="user_data/config.json" + "add_config_files": [ + "config-private.json" + ] + ``` + + ``` bash + freqtrade trade --config user_data/config.json <...> + ``` + + The 2nd file should only specify what you intend to override. + If a key is in more than one of the configurations, then the "last specified configuration" wins (in the above example, `config-private.json`). + + For one-off commands, you can also use the below syntax by specifying multiple "--config" parameters. + ``` bash freqtrade trade --config user_data/config.json --config user_data/config-private.json <...> ``` - The 2nd file should only specify what you intend to override. - If a key is in more than one of the configurations, then the "last specified configuration" wins (in the above example, `config-private.json`). + + This is equivalent to the example above - but `config-private.json` is specified as cli argument. + +??? Note "config collision handling" + If the same configuration setting takes place in both `config.json` and `config-import.json`, then the parent configuration wins. + In the below case, `max_open_trades` would be 3 after the merging - as the reusable "import" configuration has this key overwritten. + + ``` json title="user_data/config.json" + { + "max_open_trades": 3, + "stake_currency": "USDT", + "add_config_files": [ + "config-import.json" + ] + } + ``` + + ``` json title="user_data/config-import.json" + { + "max_open_trades": 10, + "stake_amount": "unlimited", + } + ``` + + Resulting combined configuration: + + ``` json title="Result" + { + "max_open_trades": 10, + "stake_currency": "USDT", + "stake_amount": "unlimited" + } + ``` ## Configuration parameters @@ -92,7 +141,7 @@ Mandatory parameters are marked as **Required**, which means that they are requi | `dry_run_wallet` | Define the starting amount in stake currency for the simulated wallet used by the bot running in Dry Run mode.
*Defaults to `1000`.*
**Datatype:** Float | `cancel_open_orders_on_exit` | Cancel open orders when the `/stop` RPC command is issued, `Ctrl+C` is pressed or the bot dies unexpectedly. When set to `true`, this allows you to use `/stop` to cancel unfilled and partially filled orders in the event of a market crash. It does not impact open positions.
*Defaults to `false`.*
**Datatype:** Boolean | `process_only_new_candles` | Enable processing of indicators only when new candles arrive. If false each loop populates the indicators, this will mean the same candle is processed many times creating system load but can be useful of your strategy depends on tick data not only candle. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `false`.*
**Datatype:** Boolean -| `minimal_roi` | **Required.** Set the threshold as ratio the bot will use to sell a trade. [More information below](#understand-minimal_roi). [Strategy Override](#parameters-in-the-strategy).
**Datatype:** Dict +| `minimal_roi` | **Required.** Set the threshold as ratio the bot will use to exit a trade. [More information below](#understand-minimal_roi). [Strategy Override](#parameters-in-the-strategy).
**Datatype:** Dict | `stoploss` | **Required.** Value as ratio of the stoploss used by the bot. More details in the [stoploss documentation](stoploss.md). [Strategy Override](#parameters-in-the-strategy).
**Datatype:** Float (as ratio) | `trailing_stop` | Enables trailing stoploss (based on `stoploss` in either configuration or strategy file). More details in the [stoploss documentation](stoploss.md#trailing-stop-loss). [Strategy Override](#parameters-in-the-strategy).
**Datatype:** Boolean | `trailing_stop_positive` | Changes stoploss once profit has been reached. More details in the [stoploss documentation](stoploss.md#trailing-stop-loss-custom-positive-loss). [Strategy Override](#parameters-in-the-strategy).
**Datatype:** Float @@ -105,7 +154,7 @@ Mandatory parameters are marked as **Required**, which means that they are requi | `unfilledtimeout.entry` | **Required.** How long (in minutes or seconds) the bot will wait for an unfilled entry order to complete, after which the order will be cancelled and repeated at current (new) price, as long as there is a signal. [Strategy Override](#parameters-in-the-strategy).
**Datatype:** Integer | `unfilledtimeout.exit` | **Required.** How long (in minutes or seconds) the bot will wait for an unfilled exit order to complete, after which the order will be cancelled and repeated at current (new) price, as long as there is a signal. [Strategy Override](#parameters-in-the-strategy).
**Datatype:** Integer | `unfilledtimeout.unit` | Unit to use in unfilledtimeout setting. Note: If you set unfilledtimeout.unit to "seconds", "internals.process_throttle_secs" must be inferior or equal to timeout [Strategy Override](#parameters-in-the-strategy).
*Defaults to `minutes`.*
**Datatype:** String -| `unfilledtimeout.exit_timeout_count` | How many times can exit orders time out. Once this number of timeouts is reached, an emergency sell is triggered. 0 to disable and allow unlimited order cancels. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `0`.*
**Datatype:** Integer +| `unfilledtimeout.exit_timeout_count` | How many times can exit orders time out. Once this number of timeouts is reached, an emergency exit is triggered. 0 to disable and allow unlimited order cancels. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `0`.*
**Datatype:** Integer | `entry_pricing.price_side` | Select the side of the spread the bot should look at to get the entry rate. [More information below](#buy-price-side).
*Defaults to `same`.*
**Datatype:** String (either `ask`, `bid`, `same` or `other`). | `entry_pricing.price_last_balance` | **Required.** Interpolate the bidding price. More information [below](#entry-price-without-orderbook-enabled). | `entry_pricing.use_order_book` | Enable entering using the rates in [Order Book Entry](#entry-price-with-orderbook-enabled).
*Defaults to `True`.*
**Datatype:** Boolean @@ -115,15 +164,16 @@ Mandatory parameters are marked as **Required**, which means that they are requi | `exit_pricing.price_side` | Select the side of the spread the bot should look at to get the exit rate. [More information below](#exit-price-side).
*Defaults to `same`.*
**Datatype:** String (either `ask`, `bid`, `same` or `other`). | `exit_pricing.price_last_balance` | Interpolate the exiting price. More information [below](#exit-price-without-orderbook-enabled). | `exit_pricing.use_order_book` | Enable exiting of open trades using [Order Book Exit](#exit-price-with-orderbook-enabled).
*Defaults to `True`.*
**Datatype:** Boolean -| `exit_pricing.order_book_top` | Bot will use the top N rate in Order Book "price_side" to sell. I.e. a value of 2 will allow the bot to pick the 2nd ask rate in [Order Book Exit](#exit-price-with-orderbook-enabled)
*Defaults to `1`.*
**Datatype:** Positive Integer -| `use_sell_signal` | Use sell signals produced by the strategy in addition to the `minimal_roi`. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `true`.*
**Datatype:** Boolean -| `sell_profit_only` | Wait until the bot reaches `sell_profit_offset` before taking a sell decision. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `false`.*
**Datatype:** Boolean -| `sell_profit_offset` | Sell-signal is only active above this value. Only active in combination with `sell_profit_only=True`. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `0.0`.*
**Datatype:** Float (as ratio) -| `ignore_roi_if_buy_signal` | Do not sell if the buy signal is still active. This setting takes preference over `minimal_roi` and `use_sell_signal`. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `false`.*
**Datatype:** Boolean +| `exit_pricing.order_book_top` | Bot will use the top N rate in Order Book "price_side" to exit. I.e. a value of 2 will allow the bot to pick the 2nd ask rate in [Order Book Exit](#exit-price-with-orderbook-enabled)
*Defaults to `1`.*
**Datatype:** Positive Integer +| `use_exit_signal` | Use exit signals produced by the strategy in addition to the `minimal_roi`. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `true`.*
**Datatype:** Boolean +| `exit_profit_only` | Wait until the bot reaches `exit_profit_offset` before taking an exit decision. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `false`.*
**Datatype:** Boolean +| `exit_profit_offset` | Exit-signal is only active above this value. Only active in combination with `exit_profit_only=True`. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `0.0`.*
**Datatype:** Float (as ratio) +| `ignore_roi_if_entry_signal` | Do not exit if the entry signal is still active. This setting takes preference over `minimal_roi` and `use_exit_signal`. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `false`.*
**Datatype:** Boolean | `ignore_buying_expired_candle_after` | Specifies the number of seconds until a buy signal is no longer used.
**Datatype:** Integer | `order_types` | Configure order-types depending on the action (`"entry"`, `"exit"`, `"stoploss"`, `"stoploss_on_exchange"`). [More information below](#understand-order_types). [Strategy Override](#parameters-in-the-strategy).
**Datatype:** Dict | `order_time_in_force` | Configure time in force for entry and exit orders. [More information below](#understand-order_time_in_force). [Strategy Override](#parameters-in-the-strategy).
**Datatype:** Dict | `custom_price_max_distance_ratio` | Configure maximum distance ratio between current and custom entry or exit price.
*Defaults to `0.02` 2%).*
**Datatype:** Positive float +| `recursive_strategy_search` | Set to `true` to recursively search sub-directories inside `user_data/strategies` for a strategy.
**Datatype:** Boolean | `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 @@ -150,10 +200,12 @@ Mandatory parameters are marked as **Required**, which means that they are requi | `telegram.balance_dust_level` | Dust-level (in stake currency) - currencies with a balance below this will not be shown by `/balance`.
**Datatype:** float | `webhook.enabled` | Enable usage of Webhook notifications
**Datatype:** Boolean | `webhook.url` | URL for the webhook. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details.
**Datatype:** String -| `webhook.webhookbuy` | Payload to send on buy. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details.
**Datatype:** String -| `webhook.webhookbuycancel` | Payload to send on buy order cancel. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details.
**Datatype:** String -| `webhook.webhooksell` | Payload to send on sell. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details.
**Datatype:** String -| `webhook.webhooksellcancel` | Payload to send on sell order cancel. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details.
**Datatype:** String +| `webhook.webhookentry` | Payload to send on entry. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details.
**Datatype:** String +| `webhook.webhookentrycancel` | Payload to send on entry order cancel. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details.
**Datatype:** String +| `webhook.webhookentryfill` | Payload to send on entry order filled. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details.
**Datatype:** String +| `webhook.webhookexit` | Payload to send on exit. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details.
**Datatype:** String +| `webhook.webhookexitcancel` | Payload to send on exit order cancel. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details.
**Datatype:** String +| `webhook.webhookexitfill` | Payload to send on exit order filled. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details.
**Datatype:** String | `webhook.webhookstatus` | Payload to send on status calls. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details.
**Datatype:** String | `api_server.enabled` | Enable usage of API Server. See the [API Server documentation](rest-api.md) for more details.
**Datatype:** Boolean | `api_server.listen_ip_address` | Bind IP address. See the [API Server documentation](rest-api.md) for more details.
**Datatype:** IPv4 @@ -164,7 +216,7 @@ Mandatory parameters are marked as **Required**, which means that they are requi | `bot_name` | Name of the bot. Passed via API to a client - can be shown to distinguish / name bots.
*Defaults to `freqtrade`*
**Datatype:** String | `db_url` | Declares database URL to use. NOTE: This defaults to `sqlite:///tradesv3.dryrun.sqlite` if `dry_run` is `true`, and to `sqlite:///tradesv3.sqlite` for production instances.
**Datatype:** String, SQLAlchemy connect string | `initial_state` | Defines the initial application state. If set to stopped, then the bot has to be explicitly started via `/start` RPC command.
*Defaults to `stopped`.*
**Datatype:** Enum, either `stopped` or `running` -| `forcebuy_enable` | Enables the RPC Commands to force a buy. More information below.
**Datatype:** Boolean +| `force_entry_enable` | Enables the RPC Commands to force a Trade entry. More information below.
**Datatype:** Boolean | `disable_dataframe_checks` | Disable checking the OHLCV dataframe returned from the strategy methods for correctness. Only use when intentionally changing the dataframe and understand what you are doing. [Strategy Override](#parameters-in-the-strategy).
*Defaults to `False`*.
**Datatype:** Boolean | `strategy` | **Required** Defines Strategy class to use. Recommended to be set via `--strategy NAME`.
**Datatype:** ClassName | `strategy_path` | Adds an additional strategy lookup path (must be a directory).
**Datatype:** String @@ -173,6 +225,7 @@ Mandatory parameters are marked as **Required**, which means that they are requi | `internals.sd_notify` | Enables use of the sd_notify protocol to tell systemd service manager about changes in the bot state and issue keep-alive pings. See [here](installation.md#7-optional-configure-freqtrade-as-a-systemd-service) for more details.
**Datatype:** Boolean | `logfile` | Specifies logfile name. Uses a rolling strategy for log file rotation for 10 files with the 1MB limit per file.
**Datatype:** String | `user_data_dir` | Directory containing user data.
*Defaults to `./user_data/`*.
**Datatype:** String +| `add_config_files` | Additional config files. These files will be loaded and merged with the current config file. The files are resolved relative to the initial file.
*Defaults to `[]`*.
**Datatype:** List of strings | `dataformat_ohlcv` | Data format to use to store historical candle (OHLCV) data.
*Defaults to `json`*.
**Datatype:** String | `dataformat_trades` | Data format to use to store historical trades data.
*Defaults to `jsongz`*.
**Datatype:** String | `position_adjustment_enable` | Enables the strategy to use position adjustments (additional buys or sells). [More information here](strategy-callbacks.md#adjust-trade-position).
[Strategy Override](#parameters-in-the-strategy).
*Defaults to `false`.*
**Datatype:** Boolean @@ -196,10 +249,10 @@ Values set in the configuration file always overwrite values set in the strategy * `order_time_in_force` * `unfilledtimeout` * `disable_dataframe_checks` -* `use_sell_signal` -* `sell_profit_only` -* `sell_profit_offset` -* `ignore_roi_if_buy_signal` +- `use_exit_signal` +* `exit_profit_only` +- `exit_profit_offset` +- `ignore_roi_if_entry_signal` * `ignore_buying_expired_candle_after` * `position_adjustment_enable` * `max_entry_position_adjustment` @@ -328,10 +381,10 @@ See the example below: ```json "minimal_roi": { - "40": 0.0, # Sell after 40 minutes if the profit is not negative - "30": 0.01, # Sell after 30 minutes if there is at least 1% profit - "20": 0.02, # Sell after 20 minutes if there is at least 2% profit - "0": 0.04 # Sell immediately if there is at least 4% profit + "40": 0.0, # Exit after 40 minutes if the profit is not negative + "30": 0.01, # Exit after 30 minutes if there is at least 1% profit + "20": 0.02, # Exit after 20 minutes if there is at least 2% profit + "0": 0.04 # Exit immediately if there is at least 4% profit }, ``` @@ -340,14 +393,14 @@ This parameter can be set in either Strategy or Configuration file. If you use i `minimal_roi` value from the strategy file. If it is not set in either Strategy or Configuration, a default of 1000% `{"0": 10}` is used, and minimal ROI is disabled unless your trade generates 1000% profit. -!!! Note "Special case to forcesell after a specific time" - A special case presents using `"": -1` as ROI. This forces the bot to sell a trade after N Minutes, no matter if it's positive or negative, so represents a time-limited force-sell. +!!! Note "Special case to forceexit after a specific time" + A special case presents using `"": -1` as ROI. This forces the bot to exit a trade after N Minutes, no matter if it's positive or negative, so represents a time-limited force-exit. -### Understand forcebuy_enable +### Understand force_entry_enable -The `forcebuy_enable` configuration parameter enables the usage of forcebuy commands via Telegram and REST API. +The `force_entry_enable` configuration parameter enables the usage of force-enter (`/forcelong`, `/forceshort`) commands via Telegram and REST API. For security reasons, it's disabled by default, and freqtrade will show a warning message on startup if enabled. -For example, you can send `/forcebuy ETH/BTC` to the bot, which will result in freqtrade buying the pair and holds it until a regular sell-signal (ROI, stoploss, /forcesell) appears. +For example, you can send `/forceenter ETH/BTC` to the bot, which will result in freqtrade buying the pair and holds it until a regular exit-signal (ROI, stoploss, /forceexit) appears. This can be dangerous with some strategies, so use with care. @@ -374,18 +427,17 @@ For example, if your strategy is using a 1h timeframe, and you only want to buy ### Understand order_types -The `order_types` configuration parameter maps actions (`entry`, `exit`, `stoploss`, `emergencyexit`, `forceexit`, `forceentry`) to order-types (`market`, `limit`, ...) as well as configures stoploss to be on the exchange and defines stoploss on exchange update interval in seconds. +The `order_types` configuration parameter maps actions (`entry`, `exit`, `stoploss`, `emergency_exit`, `force_exit`, `force_entry`) to order-types (`market`, `limit`, ...) as well as configures stoploss to be on the exchange and defines stoploss on exchange update interval in seconds. -This allows to buy using limit orders, sell using -limit-orders, and create stoplosses using market orders. It also allows to set the -stoploss "on exchange" which means stoploss order would be placed immediately once -the buy order is fulfilled. +This allows to enter using limit orders, exit using limit-orders, and create stoplosses using market orders. +It also allows to set the +stoploss "on exchange" which means stoploss order would be placed immediately once the buy order is fulfilled. `order_types` set in the configuration file overwrites values set in the strategy as a whole, so you need to configure the whole `order_types` dictionary in one place. If this is configured, the following 4 values (`entry`, `exit`, `stoploss` and `stoploss_on_exchange`) need to be present, otherwise, the bot will fail to start. -For information on (`emergencyexit`,`forceexit`, `forceentry`, `stoploss_on_exchange`,`stoploss_on_exchange_interval`,`stoploss_on_exchange_limit_ratio`) please see stop loss documentation [stop loss on exchange](stoploss.md) +For information on (`emergency_exit`,`force_exit`, `force_entry`, `stoploss_on_exchange`,`stoploss_on_exchange_interval`,`stoploss_on_exchange_limit_ratio`) please see stop loss documentation [stop loss on exchange](stoploss.md) Syntax for Strategy: @@ -393,9 +445,9 @@ Syntax for Strategy: order_types = { "entry": "limit", "exit": "limit", - "emergencyexit": "market", - "forceentry": "market", - "forceexit": "market", + "emergency_exit": "market", + "force_entry": "market", + "force_exit": "market", "stoploss": "market", "stoploss_on_exchange": False, "stoploss_on_exchange_interval": 60, @@ -409,9 +461,9 @@ Configuration: "order_types": { "entry": "limit", "exit": "limit", - "emergencyexit": "market", - "forceentry": "market", - "forceexit": "market", + "emergency_exit": "market", + "force_entry": "market", + "force_exit": "market", "stoploss": "market", "stoploss_on_exchange": false, "stoploss_on_exchange_interval": 60 @@ -434,7 +486,7 @@ Configuration: If `stoploss_on_exchange` is enabled and the stoploss is cancelled manually on the exchange, then the bot will create a new stoploss order. !!! Warning "Warning: stoploss_on_exchange failures" - If stoploss on exchange creation fails for some reason, then an "emergency exit" is initiated. By default, this will sell the asset using a market order. The order-type for the emergency-sell can be changed by setting the `emergencyexit` value in the `order_types` dictionary - however, this is not advised. + If stoploss on exchange creation fails for some reason, then an "emergency exit" is initiated. By default, this will exit the trade using a market order. The order-type for the emergency-exit can be changed by setting the `emergency_exit` value in the `order_types` dictionary - however, this is not advised. ### Understand order_time_in_force 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/data-download.md b/docs/data-download.md index 9bfc1e685..681fb717d 100644 --- a/docs/data-download.md +++ b/docs/data-download.md @@ -30,6 +30,7 @@ usage: freqtrade download-data [-h] [-v] [--logfile FILE] [-V] [-c PATH] [--data-format-ohlcv {json,jsongz,hdf5}] [--data-format-trades {json,jsongz,hdf5}] [--trading-mode {spot,margin,futures}] + [--prepend] optional arguments: -h, --help show this help message and exit @@ -62,6 +63,7 @@ optional arguments: `jsongz`). --trading-mode {spot,margin,futures} Select Trading mode + --prepend Allow data prepending. Common arguments: -v, --verbose Verbose mode (-vv for more, -vvv to get all messages). @@ -157,10 +159,21 @@ freqtrade download-data --exchange binance --pairs .*/USDT - To change the exchange used to download the historical data from, please use a different configuration file (you'll probably need to adjust rate limits etc.) - To use `pairs.json` from some other directory, use `--pairs-file some_other_dir/pairs.json`. - To download historical candle (OHLCV) data for only 10 days, use `--days 10` (defaults to 30 days). -- To download historical candle (OHLCV) data from a fixed starting point, use `--timerange 20200101-` - which will download all data from January 1st, 2020. Eventually set end dates are ignored. +- To download historical candle (OHLCV) data from a fixed starting point, use `--timerange 20200101-` - which will download all data from January 1st, 2020. - Use `--timeframes` to specify what timeframe download the historical candle (OHLCV) data for. Default is `--timeframes 1m 5m` which will download 1-minute and 5-minute data. - To use exchange, timeframe and list of pairs as defined in your configuration file, use the `-c/--config` option. With this, the script uses the whitelist defined in the config as the list of currency pairs to download data for and does not require the pairs.json file. You can combine `-c/--config` with most other options. +#### Download additional data before the current timerange + +Assuming you downloaded all data from 2022 (`--timerange 20220101-`) - but you'd now like to also backtest with earlier data. +You can do so by using the `--prepend` flag, combined with `--timerange` - specifying an end-date. + +``` bash +freqtrade download-data --exchange binance --pairs ETH/USDT XRP/USDT BTC/USDT --prepend --timerange 20210101-20220101 +``` + +!!! Note + Freqtrade will ignore the end-date in this mode if data is available, updating the end-date to the existing data start point. ### Data format diff --git a/docs/deprecated.md b/docs/deprecated.md index b50eab679..beceb12ab 100644 --- a/docs/deprecated.md +++ b/docs/deprecated.md @@ -38,7 +38,7 @@ The old section of configuration parameters (`"pairlist"`) has been deprecated i Since only quoteVolume can be compared between assets, the other options (bidVolume, askVolume) have been deprecated in 2020.4, and have been removed in 2020.9. -### Using order book steps for sell price +### Using order book steps for exit price Using `order_book_min` and `order_book_max` used to allow stepping the orderbook and trying to find the next ROI slot - trying to place sell-orders early. As this does however increase risk and provides no benefit, it's been removed for maintainability purposes in 2021.7. @@ -57,7 +57,20 @@ While we may drop support for the current interface sometime in the future, we w Please follow the [Strategy migration](strategy_migration.md) guide to migrate your strategy to the new format to start using the new functionalities. -### webhooks - `buy_tag` has been renamed to `enter_tag` +### webhooks - changes with 2022.4 + +#### `buy_tag` has been renamed to `enter_tag` This should apply only to your strategy and potentially to webhooks. We will keep a compatibility layer for 1-2 versions (so both `buy_tag` and `enter_tag` will still work), but support for this in webhooks will disappear after that. + +#### Naming changes + +Webhook terminology changed from "sell" to "exit", and from "buy" to "entry". + +* `webhookbuy` -> `webhookentry` +* `webhookbuyfill` -> `webhookentryfill` +* `webhookbuycancel` -> `webhookentrycancel` +* `webhooksell` -> `webhookexit` +* `webhooksellfill` -> `webhookexitfill` +* `webhooksellcancel` -> `webhookexitcancel` diff --git a/docs/developer.md b/docs/developer.md index ee4bac5c2..185bfc92e 100644 --- a/docs/developer.md +++ b/docs/developer.md @@ -26,6 +26,9 @@ Alternatively (e.g. if your system is not supported by the setup.sh script), fol This will install all required tools for development, including `pytest`, `flake8`, `mypy`, and `coveralls`. +Then install the git hook scripts by running `pre-commit install`, so your changes will be verified locally before committing. +This avoids a lot of waiting for CI already, as some basic formatting checks are done locally on your machine. + Before opening a pull request, please familiarize yourself with our [Contributing Guidelines](https://github.com/freqtrade/freqtrade/blob/develop/CONTRIBUTING.md). ### Devcontainer setup @@ -197,11 +200,12 @@ For that reason, they must implement the following methods: * `global_stop()` * `stop_per_pair()`. -`global_stop()` and `stop_per_pair()` must return a ProtectionReturn tuple, which consists of: +`global_stop()` and `stop_per_pair()` must return a ProtectionReturn object, which consists of: * lock pair - boolean * lock until - datetime - until when should the pair be locked (will be rounded up to the next new candle) * reason - string, used for logging and storage in the database +* lock_side - long, short or '*'. The `until` portion should be calculated using the provided `calculate_lock_end()` method. @@ -220,13 +224,13 @@ Protections can have 2 different ways to stop trading for a limited : ##### Protections - per pair Protections that implement the per pair approach must set `has_local_stop=True`. -The method `stop_per_pair()` will be called whenever a trade closed (sell order completed). +The method `stop_per_pair()` will be called whenever a trade closed (exit order completed). ##### Protections - global protection These Protections should do their evaluation across all pairs, and consequently will also lock all pairs from trading (called a global PairLock). Global protection must set `has_global_stop=True` to be evaluated for global stops. -The method `global_stop()` will be called whenever a trade closed (sell order completed). +The method `global_stop()` will be called whenever a trade closed (exit order completed). ##### Protections - calculating lock end time @@ -264,7 +268,7 @@ Additional tests / steps to complete: * Check if balance shows correctly (*) * Create market order (*) * Create limit order (*) -* Complete trade (buy + sell) (*) +* Complete trade (enter + exit) (*) * Compare result calculation between exchange and bot * Ensure fees are applied correctly (check the database against the exchange) diff --git a/docs/exchanges.md b/docs/exchanges.md index b808096d2..50ebf9e0a 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. @@ -227,6 +230,11 @@ OKX requires a passphrase for each api key, you will therefore need to add this !!! Warning OKX only provides 100 candles per api call. Therefore, the strategy will only have a pretty low amount of data available in backtesting mode. +!!! Warning "Futures" + OKX Futures has the concept of "position mode" - which can be Net or long/short (hedge mode). + Freqtrade supports both modes - but changing the mode mid-trading is not supported and will lead to exceptions and failures to place trades. + OKX also only provides MARK candles for the past ~3 months. Backtesting futures prior to that date will therefore lead to slight deviations, as funding-fees cannot be calculated correctly without this data. + ## Gate.io !!! Tip "Stoploss on Exchange" diff --git a/docs/hyperopt.md b/docs/hyperopt.md index 3f613a208..030d73f4b 100644 --- a/docs/hyperopt.md +++ b/docs/hyperopt.md @@ -116,7 +116,9 @@ optional arguments: ShortTradeDurHyperOptLoss, OnlyProfitHyperOptLoss, SharpeHyperOptLoss, SharpeHyperOptLossDaily, SortinoHyperOptLoss, SortinoHyperOptLossDaily, - CalmarHyperOptLoss, MaxDrawDownHyperOptLoss, ProfitDrawDownHyperOptLoss + CalmarHyperOptLoss, MaxDrawDownHyperOptLoss, + MaxDrawDownRelativeHyperOptLoss, + ProfitDrawDownHyperOptLoss --disable-param-export Disable automatic hyperopt parameter export. --ignore-missing-spaces, --ignore-unparameterized-spaces @@ -563,7 +565,8 @@ Currently, the following loss functions are builtin: * `SharpeHyperOptLossDaily` - optimizes Sharpe Ratio calculated on **daily** trade returns relative to standard deviation. * `SortinoHyperOptLoss` - optimizes Sortino Ratio calculated on trade returns relative to **downside** standard deviation. * `SortinoHyperOptLossDaily` - optimizes Sortino Ratio calculated on **daily** trade returns relative to **downside** standard deviation. -* `MaxDrawDownHyperOptLoss` - Optimizes Maximum drawdown. +* `MaxDrawDownHyperOptLoss` - Optimizes Maximum absolute drawdown. +* `MaxDrawDownRelativeHyperOptLoss` - Optimizes both maximum absolute drawdown while also adjusting for maximum relative drawdown. * `CalmarHyperOptLoss` - Optimizes Calmar Ratio calculated on trade returns relative to max drawdown. * `ProfitDrawDownHyperOptLoss` - Optimizes by max Profit & min Drawdown objective. `DRAWDOWN_MULT` variable within the hyperoptloss file can be adjusted to be stricter or more flexible on drawdown purposes. diff --git a/docs/includes/pairlists.md b/docs/includes/pairlists.md index cec5ceb19..0f55c1b79 100644 --- a/docs/includes/pairlists.md +++ b/docs/includes/pairlists.md @@ -44,7 +44,7 @@ It uses configuration from `exchange.pair_whitelist` and `exchange.pair_blacklis ```json "pairlists": [ {"method": "StaticPairList"} - ], +], ``` By default, only currently enabled pairs are allowed. @@ -160,17 +160,17 @@ This filter allows freqtrade to ignore pairs until they have been listed for at Offsets an incoming pairlist by a given `offset` value. -As an example it can be used in conjunction with `VolumeFilter` to remove the top X volume pairs. Or to split -a larger pairlist on two bot instances. +As an example it can be used in conjunction with `VolumeFilter` to remove the top X volume pairs. Or to split a larger pairlist on two bot instances. -Example to remove the first 10 pairs from the pairlist: +Example to remove the first 10 pairs from the pairlist, and takes the next 20 (taking items 10-30 of the initial list): ```json "pairlists": [ // ... { "method": "OffsetFilter", - "offset": 10 + "offset": 10, + "number_assets": 20 } ], ``` @@ -181,7 +181,7 @@ Example to remove the first 10 pairs from the pairlist: `VolumeFilter`. !!! Note - An offset larger then the total length of the incoming pairlist will result in an empty pairlist. + An offset larger than the total length of the incoming pairlist will result in an empty pairlist. #### PerformanceFilter diff --git a/docs/includes/protections.md b/docs/includes/protections.md index 0757d2f6d..d67924cfe 100644 --- a/docs/includes/protections.md +++ b/docs/includes/protections.md @@ -48,6 +48,8 @@ If `trade_limit` or more trades resulted in stoploss, trading will stop for `sto This applies across all pairs, unless `only_per_pair` is set to true, which will then only look at one pair at a time. +Similarly, this protection will by default look at all trades (long and short). For futures bots, setting `only_per_side` will make the bot only consider one side, and will then only lock this one side, allowing for example shorts to continue after a series of long stoplosses. + The below example stops trading for all pairs for 4 candles after the last trade if the bot hit stoploss 4 times within the last 24 candles. ``` python @@ -59,7 +61,8 @@ def protections(self): "lookback_period_candles": 24, "trade_limit": 4, "stop_duration_candles": 4, - "only_per_pair": False + "only_per_pair": False, + "only_per_side": False } ] ``` @@ -93,6 +96,8 @@ def protections(self): `LowProfitPairs` uses all trades for a pair within `lookback_period` in minutes (or in candles when using `lookback_period_candles`) to determine the overall profit ratio. If that ratio is below `required_profit`, that pair will be locked for `stop_duration` in minutes (or in candles when using `stop_duration_candles`). +For futures bots, setting `only_per_side` will make the bot only consider one side, and will then only lock this one side, allowing for example shorts to continue after a series of long losses. + The below example will stop trading a pair for 60 minutes if the pair does not have a required profit of 2% (and a minimum of 2 trades) within the last 6 candles. ``` python @@ -104,7 +109,8 @@ def protections(self): "lookback_period_candles": 6, "trade_limit": 2, "stop_duration": 60, - "required_profit": 0.02 + "required_profit": 0.02, + "only_per_pair": False, } ] ``` 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: 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/docs/leverage.md b/docs/leverage.md index 70f345601..79d3c9842 100644 --- a/docs/leverage.md +++ b/docs/leverage.md @@ -13,6 +13,16 @@ Please only use advanced trading modes when you know how freqtrade (and your strategy) works. Also, never risk more than what you can afford to lose. +Please read the [strategy migration guide](strategy_migration.md#strategy-migration-between-v2-and-v3) to migrate your strategy from a freqtrade v2 strategy, to v3 strategy that can short and trade futures. + +## Shorting + +Shorting is not possible when trading with [`trading_mode`](#understand-tradingmode) set to `spot`. To short trade, `trading_mode` must be set to `margin`(currently unavailable) or [`futures`](#futures), with [`margin_mode`](#margin-mode) set to `cross`(currently unavailable) or [`isolated`](#isolated-margin-mode) + +For a strategy to short, the strategy class must set the class variable `can_short = True` + +Please read [strategy customization](strategy-customization.md#entry-signal-rules) for instructions on how to set signals to enter and exit short trades. + ## Understand `trading_mode` The possible values are: `spot` (default), `margin`(*Currently unavailable*) or `futures`. diff --git a/docs/plotting.md b/docs/plotting.md index df988c578..6ae0c3f11 100644 --- a/docs/plotting.md +++ b/docs/plotting.md @@ -96,7 +96,7 @@ Strategy arguments: Example: ``` bash -freqtrade plot-dataframe -p BTC/ETH +freqtrade plot-dataframe -p BTC/ETH --strategy AwesomeStrategy ``` The `-p/--pairs` argument can be used to specify pairs you would like to plot. @@ -107,9 +107,6 @@ The `-p/--pairs` argument can be used to specify pairs you would like to plot. Specify custom indicators. Use `--indicators1` for the main plot and `--indicators2` for the subplot below (if values are in a different range than prices). -!!! Tip - You will almost certainly want to specify a custom strategy! This can be done by adding `-s Classname` / `--strategy ClassName` to the command. - ``` bash freqtrade plot-dataframe --strategy AwesomeStrategy -p BTC/ETH --indicators1 sma ema --indicators2 macd ``` diff --git a/docs/requirements-docs.txt b/docs/requirements-docs.txt index 1f7db75c5..b26e448ea 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,5 +1,5 @@ mkdocs==1.3.0 -mkdocs-material==8.2.8 +mkdocs-material==8.2.14 mdx_truly_sane_lists==1.2 -pymdown-extensions==9.3 -jinja2==3.1.1 +pymdown-extensions==9.4 +jinja2==3.1.2 diff --git a/docs/rest-api.md b/docs/rest-api.md index 25e7ee205..1ec9b6c12 100644 --- a/docs/rest-api.md +++ b/docs/rest-api.md @@ -147,8 +147,8 @@ python3 scripts/rest_client.py --config rest_config.json [optional par | `profit` | Display a summary of your profit/loss from close trades and some stats about your performance. | `forceexit ` | Instantly exits the given trade (Ignoring `minimum_roi`). | `forceexit all` | Instantly exits all open trades (Ignoring `minimum_roi`). -| `forceenter [rate]` | Instantly enters the given pair. Rate is optional. (`forcebuy_enable` must be set to True) -| `forceenter [rate]` | Instantly longs or shorts the given pair. Rate is optional. (`forcebuy_enable` must be set to True) +| `forceenter [rate]` | Instantly enters the given pair. Rate is optional. (`force_entry_enable` must be set to True) +| `forceenter [rate]` | Instantly longs or shorts the given pair. Rate is optional. (`force_entry_enable` must be set to True) | `performance` | Show performance of each finished trade grouped by pair. | `balance` | Show account balance per currency. | `daily ` | Shows profit or loss per day, over the last n days (n defaults to 7). @@ -223,8 +223,8 @@ forceenter :param side: 'long' or 'short' :param price: Optional - price to buy -forcesell - Force-sell a trade. +forceexit + Force-exit a trade. :param tradeid: Id of the trade (can be received via status command) diff --git a/docs/sql_cheatsheet.md b/docs/sql_cheatsheet.md index 0e2abc239..49372b002 100644 --- a/docs/sql_cheatsheet.md +++ b/docs/sql_cheatsheet.md @@ -52,11 +52,11 @@ SELECT * FROM trades; ## Fix trade still open after a manual exit on the exchange !!! Warning - Manually selling a pair on the exchange will not be detected by the bot and it will try to sell anyway. Whenever possible, forceexit should be used to accomplish the same thing. + Manually selling a pair on the exchange will not be detected by the bot and it will try to sell anyway. Whenever possible, /forceexit should be used to accomplish the same thing. It is strongly advised to backup your database file before making any manual changes. !!! Note - This should not be necessary after /forceexit, as forceexit orders are closed automatically by the bot on the next iteration. + This should not be necessary after /forceexit, as force_exit orders are closed automatically by the bot on the next iteration. ```sql UPDATE trades @@ -65,7 +65,7 @@ SET is_open=0, close_rate=, close_profit = close_rate / open_rate - 1, close_profit_abs = (amount * * (1 - fee_close) - (amount * (open_rate * (1 - fee_open)))), - sell_reason= + exit_reason= WHERE id=; ``` @@ -78,7 +78,7 @@ SET is_open=0, close_rate=0.19638016, close_profit=0.0496, close_profit_abs = (amount * 0.19638016 * (1 - fee_close) - (amount * (open_rate * (1 - fee_open)))), - sell_reason='force_sell' + exit_reason='force_exit' WHERE id=31; ``` diff --git a/docs/stoploss.md b/docs/stoploss.md index 2d95813ac..573fdbd6c 100644 --- a/docs/stoploss.md +++ b/docs/stoploss.md @@ -17,7 +17,7 @@ Those stoploss modes can be *on exchange* or *off exchange*. These modes can be configured with these values: ``` python - 'emergencyexit': 'market', + 'emergency_exit': 'market', 'stoploss_on_exchange': False 'stoploss_on_exchange_interval': 60, 'stoploss_on_exchange_limit_ratio': 0.99 @@ -52,17 +52,17 @@ The bot cannot do these every 5 seconds (at each iteration), otherwise it would So this parameter will tell the bot how often it should update the stoploss order. The default value is 60 (1 minute). This same logic will reapply a stoploss order on the exchange should you cancel it accidentally. -### forceexit +### force_exit -`forceexit` is an optional value, which defaults to the same value as `exit` and is used when sending a `/forceexit` command from Telegram or from the Rest API. +`force_exit` is an optional value, which defaults to the same value as `exit` and is used when sending a `/forceexit` command from Telegram or from the Rest API. -### forceentry +### force_entry -`forceentry` is an optional value, which defaults to the same value as `entry` and is used when sending a `/forceentry` command from Telegram or from the Rest API. +`force_entry` is an optional value, which defaults to the same value as `entry` and is used when sending a `/forceentry` command from Telegram or from the Rest API. -### emergencyexit +### emergency_exit -`emergencyexit` is an optional value, which defaults to `market` and is used when creating stop loss on exchange orders fails. +`emergency_exit` is an optional value, which defaults to `market` and is used when creating stop loss on exchange orders fails. The below is the default which is used if not changed in strategy or configuration file. Example from strategy file: @@ -71,7 +71,7 @@ Example from strategy file: order_types = { "entry": "limit", "exit": "limit", - "emergencyexit": "market", + "emergency_exit": "market", "stoploss": "market", "stoploss_on_exchange": True, "stoploss_on_exchange_interval": 60, diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index dfd29d544..ab67a3c26 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) @@ -16,11 +17,35 @@ Currently available callbacks: * [`confirm_trade_entry()`](#trade-entry-buy-order-confirmation) * [`confirm_trade_exit()`](#trade-exit-sell-order-confirmation) * [`adjust_trade_position()`](#adjust-trade-position) +* [`adjust_entry_price()`](#adjust-entry-price) * [`leverage()`](#leverage-callback) !!! 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 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 requests + +class AwesomeStrategy(IStrategy): + + # ... populate_* methods + + 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. + """ + 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.cust_remote_data = requests.get('https://some_remote_source.example.com') + +``` ## 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). @@ -84,16 +109,17 @@ Freqtrade will fall back to the `proposed_stake` value should your code raise an Called for open trade every throttling iteration (roughly every 5 seconds) until a trade is closed. -Allows to define custom sell signals, indicating that specified position should be sold. This is very useful when we need to customize sell conditions for each individual trade, or if you need trade data to make an exit decision. +Allows to define custom exit signals, indicating that specified position should be sold. This is very useful when we need to customize exit conditions for each individual trade, or if you need trade data to make an exit decision. For example you could implement a 1:2 risk-reward ROI with `custom_exit()`. -Using custom_exit() signals in place of stoploss though *is not recommended*. It is a inferior method to using `custom_stoploss()` in this regard - which also allows you to keep the stoploss on exchange. +Using `custom_exit()` signals in place of stoploss though *is not recommended*. It is a inferior method to using `custom_stoploss()` in this regard - which also allows you to keep the stoploss on exchange. !!! Note - Returning a (none-empty) `string` or `True` from this method is equal to setting sell signal on a candle at specified time. This method is not called when sell signal is set already, or if sell signals are disabled (`use_sell_signal=False` or `sell_profit_only=True` while profit is below `sell_profit_offset`). `string` max length is 64 characters. Exceeding this limit will cause the message to be truncated to 64 characters. + Returning a (none-empty) `string` or `True` from this method is equal to setting exit signal on a candle at specified time. This method is not called when exit signal is set already, or if exit signals are disabled (`use_exit_signal=False`). `string` max length is 64 characters. Exceeding this limit will cause the message to be truncated to 64 characters. + `custom_exit()` will ignore `exit_profit_only`, and will always be called unless `use_exit_signal=False`, even if there is a new enter signal. -An example of how we can use different indicators depending on the current profit and also sell trades that were open longer than one day: +An example of how we can use different indicators depending on the current profit and also exit trades that were open longer than one day: ``` python class AwesomeStrategy(IStrategy): @@ -121,11 +147,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. @@ -364,36 +390,36 @@ class AwesomeStrategy(IStrategy): # ... populate_* methods - def custom_entry_price(self, pair: str, current_time: datetime, proposed_rate: float, - entry_tag: Optional[str], **kwargs) -> 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, 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) 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" Custom prices are supported in backtesting (starting with 2021.12), and orders will fill if the price falls within the candle's low/high range. Orders that don't fill immediately are subject to regular timeout handling, which happens once per (detail) candle. - `custom_exit_price()` is only called for sells of type Sell_signal and Custom sell. All other sell-types will use regular backtesting prices. + `custom_exit_price()` is only called for sells of type exit_signal and Custom exit. All other exit-types will use regular backtesting prices. ## Custom order timeout rules @@ -417,7 +443,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): @@ -429,7 +455,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 @@ -440,7 +466,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 @@ -458,7 +484,7 @@ class AwesomeStrategy(IStrategy): ``` python from datetime import datetime -from freqtrade.persistence import Trade +from freqtrade.persistence import Trade, Order class AwesomeStrategy(IStrategy): @@ -470,22 +496,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 ``` @@ -507,7 +533,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. @@ -564,13 +590,13 @@ class AwesomeStrategy(IStrategy): :param time_in_force: Time in force. Defaults to GTC (Good-til-cancelled). :param exit_reason: Exit reason. Can be any of ['roi', 'stop_loss', 'stoploss_on_exchange', 'trailing_stop_loss', - 'sell_signal', 'force_sell', 'emergency_sell'] + 'exit_signal', 'force_exit', 'emergency_exit'] :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 sell-order is placed on the exchange. + :return bool: When True is returned, then the exit-order is placed on the exchange. False aborts the process """ - if exit_reason == 'force_sell' and trade.calc_profit_ratio(rate) < 0: + if exit_reason == 'force_exit' and trade.calc_profit_ratio(rate) < 0: # Reject force-sells with negative profit # This is just a sample, please adjust to your needs # (this does not necessarily make sense, assuming you know when you're force-selling) @@ -615,35 +641,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. @@ -653,7 +679,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 @@ -665,7 +691,7 @@ class DigDeeperStrategy(IStrategy): if last_candle['close'] < previous_candle['close']: return None - filled_entries = trade.select_filled_orders(trade.enter_side) + filled_entries = trade.select_filled_orders(trade.entry_side) count_of_entries = trade.nr_of_successful_entries # Allow up to 3 additional increasingly larger buys (4 in total) # Initial buy is 1x @@ -688,6 +714,69 @@ class DigDeeperStrategy(IStrategy): ``` +## Adjust Entry Price + +The `adjust_entry_price()` callback may be used by strategy developer to refresh/replace limit orders upon arrival of new candles. +Be aware that `custom_entry_price()` is still the one dictating initial entry limit order price target at the time of entry trigger. + +Orders can be cancelled out of this callback by returning `None`. + +Returning `current_order_rate` will keep the order on the exchange "as is". +Returning any other price will cancel the existing order, and replace it with a new order. + +The trade open-date (`trade.open_date_utc`) will remain at the time of the very first order placed. +Please make sure to be aware of this - and eventually adjust your logic in other callbacks to account for this, and use the date of the first filled order instead. + +!!! Warning "Regular timeout" + Entry `unfilledtimeout` mechanism (as well as `check_entry_timeout()`) takes precedence over this. + Entry Orders that are cancelled via the above methods will not have this callback called. Be sure to update timeout values to match your expectations. + +```python +from freqtrade.persistence import Trade +from datetime import timedelta + +class AwesomeStrategy(IStrategy): + + # ... populate_* methods + + def adjust_entry_price(self, trade: Trade, order: Optional[Order], pair: str, + current_time: datetime, proposed_rate: float, current_order_rate: float, + entry_tag: Optional[str], side: str, **kwargs) -> float: + """ + Entry price re-adjustment logic, returning the user desired limit price. + This only executes when a order was already placed, still open (unfilled fully or partially) + and not timed out on subsequent candles after entry trigger. + + When not implemented by a strategy, returns current_order_rate as default. + If current_order_rate is returned then the existing order is maintained. + If None is returned then order gets canceled but not replaced by a new one. + + :param pair: Pair that's currently analyzed + :param trade: Trade object. + :param order: Order object + :param current_time: datetime object, containing the current datetime + :param proposed_rate: Rate, calculated based on pricing settings in entry_pricing. + :param current_order_rate: Rate of the existing order in place. + :param entry_tag: Optional entry_tag (buy_tag) if provided with the buy signal. + :param side: 'long' or 'short' - indicating the direction of the proposed trade + :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. + :return float: New entry price value if provided + + """ + # Limit orders to use and follow SMA200 as price target for the first 10 minutes since entry trigger for BTC/USDT pair. + if pair == 'BTC/USDT' and entry_tag == 'long_sma200' and side == 'long' and (current_time - timedelta(minutes=10) > trade.open_date_utc: + # just cancel the order if it has been filled more than half of the amount + if order.filled > order.remaining: + return None + else: + dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe) + current_candle = dataframe.iloc[-1].squeeze() + # desired price + return current_candle['sma_200'] + # default: maintain existing order + return current_order_rate +``` + ## Leverage Callback When trading in markets that allow leverage, this method must return the desired Leverage (Defaults to 1 -> No leverage). diff --git a/docs/strategy-customization.md b/docs/strategy-customization.md index c33ec5fb9..6947380dd 100644 --- a/docs/strategy-customization.md +++ b/docs/strategy-customization.md @@ -99,7 +99,7 @@ With this section, you have a new column in your dataframe, which has `1` assign ### Customize Indicators -Buy and sell strategies need indicators. You can add more indicators by extending the list contained in the method `populate_indicators()` from your strategy file. +Buy and sell signals need indicators. You can add more indicators by extending the list contained in the method `populate_indicators()` from your strategy file. You should only add the indicators used in either `populate_entry_trend()`, `populate_exit_trend()`, or to populate another indicator, otherwise performance may suffer. @@ -205,7 +205,7 @@ Edit the method `populate_entry_trend()` in your strategy file to update your en It's important to always return the dataframe without removing/modifying the columns `"open", "high", "low", "close", "volume"`, otherwise these fields would contain something unexpected. -This method will also define a new column, `"enter_long"`, which needs to contain 1 for entries, and 0 for "no action". `enter_long` column is a mandatory column that must be set even if the strategy is shorting only. +This method will also define a new column, `"enter_long"` (`"enter_short"` for shorts), which needs to contain 1 for entries, and 0 for "no action". `enter_long` is a mandatory column that must be set even if the strategy is shorting only. Sample from `user_data/strategies/sample_strategy.py`: @@ -263,19 +263,19 @@ def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFram ### Exit signal rules -Edit the method `populate_exit_trend()` into your strategy file to update your sell strategy. -Please note that the sell-signal is only used if `use_sell_signal` is set to true in the configuration. +Edit the method `populate_exit_trend()` into your strategy file to update your exit strategy. +Please note that the exit-signal is only used if `use_exit_signal` is set to true in the configuration. It's important to always return the dataframe without removing/modifying the columns `"open", "high", "low", "close", "volume"`, otherwise these fields would contain something unexpected. -This method will also define a new column, `"exit_long"`, which needs to contain 1 for sells, and 0 for "no action". +This method will also define a new column, `"exit_long"` (`"exit_short"` for shorts), which needs to contain 1 for exits, and 0 for "no action". Sample from `user_data/strategies/sample_strategy.py`: ```python def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """ - Based on TA indicators, populates the sell signal for the given dataframe + Based on TA indicators, populates the exit signal for the given dataframe :param dataframe: DataFrame populated with indicators :param metadata: Additional information, like the currently traded pair :return: DataFrame with buy column @@ -319,7 +319,7 @@ def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame ### Minimal ROI -This dict defines the minimal Return On Investment (ROI) a trade should reach before selling, independent from the sell signal. +This dict defines the minimal Return On Investment (ROI) a trade should reach before exiting, independent from the exit signal. It is of the following format, with the dict key (left side of the colon) being the minutes passed since the trade opened, and the value (right side of the colon) being the percentage. @@ -334,10 +334,10 @@ minimal_roi = { The above configuration would therefore mean: -- Sell whenever 4% profit was reached -- Sell when 2% profit was reached (in effect after 20 minutes) -- Sell when 1% profit was reached (in effect after 30 minutes) -- Sell when trade is non-loosing (in effect after 40 minutes) +- Exit whenever 4% profit was reached +- Exit when 2% profit was reached (in effect after 20 minutes) +- Exit when 1% profit was reached (in effect after 30 minutes) +- Exit when trade is non-loosing (in effect after 40 minutes) The calculation does include fees. @@ -349,7 +349,7 @@ minimal_roi = { } ``` -While technically not completely disabled, this would sell once the trade reaches 10000% Profit. +While technically not completely disabled, this would exit once the trade reaches 10000% Profit. To use times based on candle duration (timeframe), the following snippet can be handy. This will allow you to change the timeframe for the strategy, and ROI times will still be set as candles (e.g. after 3 candles ...) @@ -385,7 +385,7 @@ For the full documentation on stoploss features, look at the dedicated [stoploss This is the set of candles the bot should download and use for the analysis. Common values are `"1m"`, `"5m"`, `"15m"`, `"1h"`, however all values supported by your exchange should work. -Please note that the same buy/sell signals may work well with one timeframe, but not with the others. +Please note that the same entry/exit signals may work well with one timeframe, but not with the others. This setting is accessible within the strategy methods as the `self.timeframe` attribute. @@ -898,7 +898,7 @@ Stoploss values returned from `custom_stoploss` must specify a percentage relati !!! Note Providing invalid input to `stoploss_from_open()` may produce "CustomStoploss function did not return valid stoploss" warnings. This may happen if `current_profit` parameter is below specified `open_relative_stop`. Such situations may arise when closing trade - is blocked by `confirm_trade_exit()` method. Warnings can be solved by never blocking stop loss sells by checking `sell_reason` in + is blocked by `confirm_trade_exit()` method. Warnings can be solved by never blocking stop loss sells by checking `exit_reason` in `confirm_trade_exit()`, or by using `return stoploss_from_open(...) or 1` idiom, which will request to not change stop loss when `current_profit < open_relative_stop`. @@ -1088,7 +1088,7 @@ The following lists some common patterns which should be avoided to prevent frus ### Colliding signals -When conflicting signals collide (e.g. both `'enter_long'` and `'exit_long'` are 1), freqtrade will do nothing and ignore the entry signal. This will avoid trades that buy, and sell immediately. Obviously, this can potentially lead to missed entries. +When conflicting signals collide (e.g. both `'enter_long'` and `'exit_long'` are 1), freqtrade will do nothing and ignore the entry signal. This will avoid trades that enter, and exit immediately. Obviously, this can potentially lead to missed entries. The following rules apply, and entry signals will be ignored if more than one of the 3 signals is set: diff --git a/docs/strategy_analysis_example.md b/docs/strategy_analysis_example.md index f2ee9c4e4..ae0c6a6a3 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" ``` @@ -129,7 +129,7 @@ print(stats['strategy_comparison']) trades = load_backtest_data(backtest_dir) # Show value-counts per pair -trades.groupby("pair")["sell_reason"].value_counts() +trades.groupby("pair")["exit_reason"].value_counts() ``` ## Plotting daily profit / equity line @@ -182,7 +182,7 @@ from freqtrade.data.btanalysis import load_trades_from_db trades = load_trades_from_db("sqlite:///tradesv3.sqlite") # Display results -trades.groupby("pair")["sell_reason"].value_counts() +trades.groupby("pair")["exit_reason"].value_counts() ``` ## Analyze the loaded trades for trade parallelism diff --git a/docs/strategy_migration.md b/docs/strategy_migration.md index 1ceb98fa5..458e80d0e 100644 --- a/docs/strategy_migration.md +++ b/docs/strategy_migration.md @@ -9,6 +9,8 @@ You can use the quick summary as checklist. Please refer to the detailed section ## Quick summary / migration checklist +Note : `forcesell`, `forcebuy`, `emergencysell` are changed to `force_exit`, `force_enter`, `emergency_exit` respectively. + * Strategy methods: * [`populate_buy_trend()` -> `populate_entry_trend()`](#populate_buy_trend) * [`populate_sell_trend()` -> `populate_exit_trend()`](#populate_sell_trend) @@ -18,13 +20,19 @@ You can use the quick summary as checklist. Please refer to the detailed section * New `side` argument to callbacks without trade object * [`custom_stake_amount`](#custom-stake-amount) * [`confirm_trade_entry`](#confirm_trade_entry) + * [`custom_entry_price`](#custom_entry_price) * [Changed argument name in `confirm_trade_exit`](#confirm_trade_exit) * Dataframe columns: * [`buy` -> `enter_long`](#populate_buy_trend) * [`sell` -> `exit_long`](#populate_sell_trend) * [`buy_tag` -> `enter_tag` (used for both long and short trades)](#populate_buy_trend) * [New column `enter_short` and corresponding new column `exit_short`](#populate_sell_trend) -* trade-object now has the following new properties: `is_short`, `enter_side`, `exit_side` and `trade_direction`. +* trade-object now has the following new properties: + * `is_short` + * `entry_side` + * `exit_side` + * `trade_direction` + * renamed: `sell_reason` -> `exit_reason` * [Renamed `trade.nr_of_successful_buys` to `trade.nr_of_successful_entries` (mostly relevant for `adjust_trade_position()`)](#adjust-trade-position-changes) * Introduced new [`leverage` callback](strategy-callbacks.md#leverage-callback). * Informative pairs can now pass a 3rd element in the Tuple, defining the candle type. @@ -35,6 +43,32 @@ You can use the quick summary as checklist. Please refer to the detailed section * `order_time_in_force` buy -> entry, sell -> exit. * `order_types` buy -> entry, sell -> exit. * `unfilledtimeout` buy -> entry, sell -> exit. +* Terminology changes + * Sell reasons changed to reflect the new naming of "exit" instead of sells. Be careful in your strategy if you're using `exit_reason` checks and eventually update your strategy. + * `sell_signal` -> `exit_signal` + * `custom_sell` -> `custom_exit` + * `force_sell` -> `force_exit` + * `emergency_sell` -> `emergency_exit` + * Webhook terminology changed from "sell" to "exit", and from "buy" to entry + * `webhookbuy` -> `webhookentry` + * `webhookbuyfill` -> `webhookentryfill` + * `webhookbuycancel` -> `webhookentrycancel` + * `webhooksell` -> `webhookexit` + * `webhooksellfill` -> `webhookexitfill` + * `webhooksellcancel` -> `webhookexitcancel` + * Telegram notification settings + * `buy` -> `entry` + * `buy_fill` -> `entry_fill` + * `buy_cancel` -> `entry_cancel` + * `sell` -> `exit` + * `sell_fill` -> `exit_fill` + * `sell_cancel` -> `exit_cancel` + * Strategy/config settings: + * `use_sell_signal` -> `use_exit_signal` + * `sell_profit_only` -> `exit_profit_only` + * `sell_profit_offset` -> `exit_profit_offset` + * `ignore_roi_if_buy_signal` -> `ignore_roi_if_entry_signal` + * `forcebuy_enable` -> `force_entry_enable` ## Extensive explanation @@ -111,6 +145,9 @@ Please refer to the [Strategy documentation](strategy-customization.md#exit-sign ### `custom_sell` +`custom_sell` has been renamed to `custom_exit`. +It's now also being called for every iteration, independent of current profit and `exit_profit_only` settings. + ``` python hl_lines="2" class AwesomeStrategy(IStrategy): def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float, @@ -146,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 ``` @@ -222,6 +259,26 @@ class AwesomeStrategy(IStrategy): return True ``` +### `custom_entry_price` + +New string argument `side` - which can be either `"long"` or `"short"`. + +``` python hl_lines="3" +class AwesomeStrategy(IStrategy): + def custom_entry_price(self, pair: str, current_time: datetime, proposed_rate: float, + entry_tag: Optional[str], **kwargs) -> float: + return proposed_rate +``` + +After: + +``` python hl_lines="3" +class AwesomeStrategy(IStrategy): + def custom_entry_price(self, pair: str, current_time: datetime, proposed_rate: float, + entry_tag: Optional[str], side: str, **kwargs) -> float: + return proposed_rate +``` + ### Adjust trade position changes While adjust-trade-position itself did not change, you should no longer use `trade.nr_of_successful_buys` - and instead use `trade.nr_of_successful_entries`, which will also include short entries. @@ -283,6 +340,7 @@ After: #### `order_types` `order_types` have changed all wordings from `buy` to `entry` - and `sell` to `exit`. +And two words are joined with `_`. ``` python hl_lines="2-6" order_types = { @@ -303,15 +361,40 @@ After: order_types = { "entry": "limit", "exit": "limit", - "emergencyexit": "market", - "forceexit": "market", - "forceentry": "market", + "emergency_exit": "market", + "force_exit": "market", + "force_entry": "market", "stoploss": "market", "stoploss_on_exchange": false, "stoploss_on_exchange_interval": 60 } ``` +#### Strategy level settings + +* `use_sell_signal` -> `use_exit_signal` +* `sell_profit_only` -> `exit_profit_only` +* `sell_profit_offset` -> `exit_profit_offset` +* `ignore_roi_if_buy_signal` -> `ignore_roi_if_entry_signal` + +``` python hl_lines="2-5" + # These values can be overridden in the config. + use_sell_signal = True + sell_profit_only = True + sell_profit_offset: 0.01 + ignore_roi_if_buy_signal = False +``` + +After: + +``` python hl_lines="2-5" + # These values can be overridden in the config. + use_exit_signal = True + exit_profit_only = True + exit_profit_offset: 0.01 + ignore_roi_if_entry_signal = False +``` + #### `unfilledtimeout` `unfilledtimeout` have changed all wordings from `buy` to `entry` - and `sell` to `exit`. diff --git a/docs/telegram-usage.md b/docs/telegram-usage.md index 3de3c8846..27f5f91b6 100644 --- a/docs/telegram-usage.md +++ b/docs/telegram-usage.md @@ -81,21 +81,21 @@ Example configuration showing the different settings: "status": "silent", "warning": "on", "startup": "off", - "buy": "silent", - "sell": { + "entry": "silent", + "exit": { "roi": "silent", - "emergency_sell": "on", - "force_sell": "on", - "sell_signal": "silent", + "emergency_exit": "on", + "force_exit": "on", + "exit_signal": "silent", "trailing_stop_loss": "on", "stop_loss": "on", "stoploss_on_exchange": "on", - "custom_sell": "silent" + "custom_exit": "silent" }, - "buy_cancel": "silent", - "sell_cancel": "on", - "buy_fill": "off", - "sell_fill": "off", + "entry_cancel": "silent", + "exit_cancel": "on", + "entry_fill": "off", + "exit_fill": "off", "protection_trigger": "off", "protection_trigger_global": "on" }, @@ -104,8 +104,8 @@ Example configuration showing the different settings: }, ``` -`buy` notifications are sent when the order is placed, while `buy_fill` notifications are sent when the order is filled on the exchange. -`sell` notifications are sent when the order is placed, while `sell_fill` notifications are sent when the order is filled on the exchange. +`entry` notifications are sent when the order is placed, while `entry_fill` notifications are sent when the order is filled on the exchange. +`exit` notifications are sent when the order is placed, while `exit_fill` notifications are sent when the order is filled on the exchange. `*_fill` notifications are off by default and must be explicitly enabled. `protection_trigger` notifications are sent when a protection triggers and `protection_trigger_global` notifications trigger when global protections are triggered. @@ -173,14 +173,17 @@ official commands. You can ask at any moment for help with `/help`. | `/profit []` | Display a summary of your profit/loss from close trades and some stats about your performance, over the last n days (all trades by default) | `/forceexit ` | Instantly exits the given trade (Ignoring `minimum_roi`). | `/forceexit all` | Instantly exits all open trades (Ignoring `minimum_roi`). -| `/forcelong [rate]` | Instantly buys the given pair. Rate is optional and only applies to limit orders. (`forcebuy_enable` must be set to True) -| `/forceshort [rate]` | Instantly shorts the given pair. Rate is optional and only applies to limit orders. This will only work on non-spot markets. (`forcebuy_enable` must be set to True) +| `/fx` | alias for `/forceexit` +| `/forcelong [rate]` | Instantly buys the given pair. Rate is optional and only applies to limit orders. (`force_entry_enable` must be set to True) +| `/forceshort [rate]` | Instantly shorts the given pair. Rate is optional and only applies to limit orders. This will only work on non-spot markets. (`force_entry_enable` must be set to True) | `/performance` | Show performance of each finished trade grouped by pair | `/balance` | Show account balance per currency | `/daily ` | Shows profit or loss per day, over the last n days (n defaults to 7) | `/weekly ` | Shows profit or loss per week, over the last n weeks (n defaults to 8) | `/monthly ` | Shows profit or loss per month, over the last n months (n defaults to 6) -| `/stats` | Shows Wins / losses by Sell reason as well as Avg. holding durations for buys and sells +| `/stats` | Shows Wins / losses by Exit reason as well as Avg. holding durations for buys and sells +| `/exits` | Shows Wins / losses by Exit reason as well as Avg. holding durations for buys and sells +| `/entries` | Shows Wins / losses by Exit reason as well as Avg. holding durations for buys and sells | `/whitelist` | Show the current whitelist | `/blacklist [pair]` | Show the current blacklist, or adds a pair to the blacklist. | `/edge` | Show validated pairs by Edge if it is enabled. @@ -272,9 +275,12 @@ The relative profit of `1.2%` is the average profit per trade. The relative profit of `15.2 Σ%` is be based on the starting capital - so in this case, the starting capital was `0.00485701 * 1.152 = 0.00738 BTC`. Starting capital is either taken from the `available_capital` setting, or calculated by using current wallet size - profits. -### /forcesell +### /forceexit -> **BINANCE:** Selling BTC/LTC with limit `0.01650000 (profit: ~-4.07%, -0.00008168)` +> **BINANCE:** Exiting BTC/LTC with limit `0.01650000 (profit: ~-4.07%, -0.00008168)` + +!!! Tip + You can get a list of all open trades by calling `/forceexit` without parameter, which will show a list of buttons to simply exit a trade. ### /forcelong [rate] | /forceshort [rate] @@ -283,13 +289,13 @@ Starting capital is either taken from the `available_capital` setting, or calcul > **BINANCE:** Long ETH/BTC with limit `0.03400000` (`1.000000 ETH`, `225.290 USD`) Omitting the pair will open a query asking for the pair to trade (based on the current whitelist). -Trades crated through `/forceentry` will have the buy-tag of `forceentry`. +Trades created through `/forcelong` will have the buy-tag of `force_entry`. ![Telegram force-buy screenshot](assets/telegram_forcebuy.png) -Note that for this to work, `forcebuy_enable` needs to be set to true. +Note that for this to work, `force_entry_enable` needs to be set to true. -[More details](configuration.md#understand-forcebuy_enable) +[More details](configuration.md#understand-force_entry_enable) ### /performance diff --git a/docs/updating.md b/docs/updating.md index b23ce32dc..1839edc4c 100644 --- a/docs/updating.md +++ b/docs/updating.md @@ -2,6 +2,10 @@ To update your freqtrade installation, please use one of the below methods, corresponding to your installation method. +!!! Note "Tracking changes" + Breaking changes / changed behavior will be documented in the changelog that is posted alongside every release. + For the develop branch, please follow PR's to avoid being surprised by changes. + ## docker-compose !!! Note "Legacy installations using the `master` image" diff --git a/docs/utils.md b/docs/utils.md index 5ef5646c3..9b799e5fc 100644 --- a/docs/utils.md +++ b/docs/utils.md @@ -119,6 +119,7 @@ This subcommand is useful for finding problems in your environment with loading usage: freqtrade list-strategies [-h] [-v] [--logfile FILE] [-V] [-c PATH] [-d PATH] [--userdir PATH] [--strategy-path PATH] [-1] [--no-color] + [--recursive-strategy-search] optional arguments: -h, --help show this help message and exit @@ -126,6 +127,9 @@ optional arguments: -1, --one-column Print output in one column. --no-color Disable colorization of hyperopt results. May be useful if you are redirecting output to a file. + --recursive-strategy-search + Recursively search for a strategy in the strategies + folder. Common arguments: -v, --verbose Verbose mode (-vv for more, -vvv to get all messages). @@ -134,9 +138,10 @@ Common arguments: details. -V, --version show program's version number and exit -c PATH, --config PATH - Specify configuration file (default: `config.json`). - Multiple --config options may be used. Can be set to - `-` to read config from stdin. + Specify configuration file (default: + `userdir/config.json` or `config.json` whichever + exists). Multiple --config options may be used. Can be + set to `-` to read config from stdin. -d PATH, --datadir PATH Path to directory with historical backtesting data. --userdir PATH, --user-data-dir PATH @@ -549,6 +554,27 @@ Show whitelist when using a [dynamic pairlist](plugins.md#pairlists). freqtrade test-pairlist --config config.json --quote USDT BTC ``` +## Convert database + +`freqtrade convert-db` can be used to convert your database from one system to another (sqlite -> postgres, postgres -> other postgres), migrating all trades, orders and Pairlocks. + +Please refer to the [SQL cheatsheet](sql_cheatsheet.md#use-a-different-database-system) to learn about requirements for different database systems. + +``` +usage: freqtrade convert-db [-h] [--db-url PATH] [--db-url-from PATH] + +optional arguments: + -h, --help show this help message and exit + --db-url PATH Override trades database URL, this is useful in custom + deployments (default: `sqlite:///tradesv3.sqlite` for + Live Run mode, `sqlite:///tradesv3.dryrun.sqlite` for + Dry Run). + --db-url-from PATH Source db url to use when migrating a database. +``` + +!!! Warning + Please ensure to only use this on an empty target database. Freqtrade will perform a regular migration, but may fail if entries already existed. + ## Webserver mode !!! Warning "Experimental" diff --git a/docs/webhook-config.md b/docs/webhook-config.md index 1266618f6..5f5933b47 100644 --- a/docs/webhook-config.md +++ b/docs/webhook-config.md @@ -10,33 +10,33 @@ Sample configuration (tested using IFTTT). "webhook": { "enabled": true, "url": "https://maker.ifttt.com/trigger//with/key//", - "webhookbuy": { + "webhookentry": { "value1": "Buying {pair}", "value2": "limit {limit:8f}", "value3": "{stake_amount:8f} {stake_currency}" }, - "webhookbuycancel": { + "webhookentrycancel": { "value1": "Cancelling Open Buy Order for {pair}", "value2": "limit {limit:8f}", "value3": "{stake_amount:8f} {stake_currency}" }, - "webhookbuyfill": { + "webhookentryfill": { "value1": "Buy Order for {pair} filled", "value2": "at {open_rate:8f}", "value3": "" }, - "webhooksell": { - "value1": "Selling {pair}", + "webhookexit": { + "value1": "Exiting {pair}", "value2": "limit {limit:8f}", "value3": "profit: {profit_amount:8f} {stake_currency} ({profit_ratio})" }, - "webhooksellcancel": { - "value1": "Cancelling Open Sell Order for {pair}", + "webhookexitcancel": { + "value1": "Cancelling Open Exit Order for {pair}", "value2": "limit {limit:8f}", "value3": "profit: {profit_amount:8f} {stake_currency} ({profit_ratio})" }, - "webhooksellfill": { - "value1": "Sell Order for {pair} filled", + "webhookexitfill": { + "value1": "Exit Order for {pair} filled", "value2": "at {close_rate:8f}.", "value3": "" }, @@ -96,9 +96,9 @@ Optional parameters are available to enable automatic retries for webhook messag Different payloads can be configured for different events. Not all fields are necessary, but you should configure at least one of the dicts, otherwise the webhook will never be called. -### Webhookbuy +### Webhookentry -The fields in `webhook.webhookbuy` are filled when the bot executes a long/short. Parameters are filled using string.format. +The fields in `webhook.webhookentry` are filled when the bot executes a long/short. Parameters are filled using string.format. Possible parameters are: * `trade_id` @@ -118,9 +118,9 @@ Possible parameters are: * `current_rate` * `enter_tag` -### Webhookbuycancel +### Webhookentrycancel -The fields in `webhook.webhookbuycancel` are filled when the bot cancels a long/short order. Parameters are filled using string.format. +The fields in `webhook.webhookentrycancel` are filled when the bot cancels a long/short order. Parameters are filled using string.format. Possible parameters are: * `trade_id` @@ -139,9 +139,9 @@ Possible parameters are: * `current_rate` * `enter_tag` -### Webhookbuyfill +### Webhookentryfill -The fields in `webhook.webhookbuyfill` are filled when the bot filled a long/short order. Parameters are filled using string.format. +The fields in `webhook.webhookentryfill` are filled when the bot filled a long/short order. Parameters are filled using string.format. Possible parameters are: * `trade_id` @@ -160,8 +160,9 @@ Possible parameters are: * `current_rate` * `enter_tag` -### Webhooksell -The fields in `webhook.webhooksell` are filled when the bot sells a trade. Parameters are filled using string.format. +### Webhookexit + +The fields in `webhook.webhookexit` are filled when the bot exits a trade. Parameters are filled using string.format. Possible parameters are: * `trade_id` @@ -178,14 +179,14 @@ Possible parameters are: * `stake_currency` * `base_currency` * `fiat_currency` -* `sell_reason` +* `exit_reason` * `order_type` * `open_date` * `close_date` -### Webhooksellfill +### Webhookexitfill -The fields in `webhook.webhooksellfill` are filled when the bot fills a sell order (closes a Trae). Parameters are filled using string.format. +The fields in `webhook.webhookexitfill` are filled when the bot fills a exit order (closes a Trade). Parameters are filled using string.format. Possible parameters are: * `trade_id` @@ -203,14 +204,14 @@ Possible parameters are: * `stake_currency` * `base_currency` * `fiat_currency` -* `sell_reason` +* `exit_reason` * `order_type` * `open_date` * `close_date` -### Webhooksellcancel +### Webhookexitcancel -The fields in `webhook.webhooksellcancel` are filled when the bot cancels a sell order. Parameters are filled using string.format. +The fields in `webhook.webhookexitcancel` are filled when the bot cancels a exit order. Parameters are filled using string.format. Possible parameters are: * `trade_id` @@ -228,7 +229,7 @@ Possible parameters are: * `stake_currency` * `base_currency` * `fiat_currency` -* `sell_reason` +* `exit_reason` * `order_type` * `open_date` * `close_date` 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.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/freqtrade/commands/__init__.py b/freqtrade/commands/__init__.py index 129836000..0e637c487 100644 --- a/freqtrade/commands/__init__.py +++ b/freqtrade/commands/__init__.py @@ -10,6 +10,7 @@ from freqtrade.commands.arguments import Arguments from freqtrade.commands.build_config_commands import start_new_config from freqtrade.commands.data_commands import (start_convert_data, start_convert_trades, start_download_data, start_list_data) +from freqtrade.commands.db_commands import start_convert_db from freqtrade.commands.deploy_commands import (start_create_userdir, start_install_ui, start_new_strategy) from freqtrade.commands.hyperopt_commands import start_hyperopt_list, start_hyperopt_show diff --git a/freqtrade/commands/arguments.py b/freqtrade/commands/arguments.py index 7d4624bd1..815e28175 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"] @@ -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"] @@ -71,7 +72,8 @@ ARGS_LIST_DATA = ["exchange", "dataformat_ohlcv", "pairs", "trading_mode"] ARGS_DOWNLOAD_DATA = ["pairs", "pairs_file", "days", "new_pairs_days", "include_inactive", "timerange", "download_trades", "exchange", "timeframes", - "erase", "dataformat_ohlcv", "dataformat_trades", "trading_mode"] + "erase", "dataformat_ohlcv", "dataformat_trades", "trading_mode", + "prepend_data"] ARGS_PLOT_DATAFRAME = ["pairs", "indicators1", "indicators2", "plot_limit", "db_url", "trade_source", "export", "exportfilename", @@ -80,7 +82,9 @@ ARGS_PLOT_DATAFRAME = ["pairs", "indicators1", "indicators2", "plot_limit", ARGS_PLOT_PROFIT = ["pairs", "timerange", "export", "exportfilename", "db_url", "trade_source", "timeframe", "plot_auto_open", ] -ARGS_INSTALL_UI = ["erase_ui_only", 'ui_version'] +ARGS_CONVERT_DB = ["db_url", "db_url_from"] + +ARGS_INSTALL_UI = ["erase_ui_only", "ui_version"] ARGS_SHOW_TRADES = ["db_url", "trade_ids", "print_json"] @@ -179,7 +183,7 @@ class Arguments: self._build_args(optionlist=['version'], parser=self.parser) from freqtrade.commands import (start_backtesting, start_backtesting_show, - start_convert_data, start_convert_trades, + start_convert_data, start_convert_db, start_convert_trades, start_create_userdir, start_download_data, start_edge, start_hyperopt, start_hyperopt_list, start_hyperopt_show, start_install_ui, start_list_data, start_list_exchanges, @@ -372,6 +376,14 @@ class Arguments: test_pairlist_cmd.set_defaults(func=start_test_pairlist) self._build_args(optionlist=ARGS_TEST_PAIRLIST, parser=test_pairlist_cmd) + # Add db-convert subcommand + convert_db = subparsers.add_parser( + "convert-db", + help="Migrate database to different system", + ) + convert_db.set_defaults(func=start_convert_db) + self._build_args(optionlist=ARGS_CONVERT_DB, parser=convert_db) + # Add install-ui subcommand install_ui_cmd = subparsers.add_parser( 'install-ui', diff --git a/freqtrade/commands/build_config_commands.py b/freqtrade/commands/build_config_commands.py index b401f52c7..be881c8ed 100644 --- a/freqtrade/commands/build_config_commands.py +++ b/freqtrade/commands/build_config_commands.py @@ -202,6 +202,8 @@ def ask_user_config() -> Dict[str, Any]: if not answers: # Interrupted questionary sessions return an empty dict. raise OperationalException("User interrupted interactive questions.") + # Ensure default is set for non-futures exchanges + answers['trading_mode'] = answers.get('trading_mode', "spot") answers['margin_mode'] = ( 'isolated' if answers.get('trading_mode') == 'futures' diff --git a/freqtrade/commands/cli_options.py b/freqtrade/commands/cli_options.py index 61890d650..aac9f5713 100644 --- a/freqtrade/commands/cli_options.py +++ b/freqtrade/commands/cli_options.py @@ -83,6 +83,11 @@ AVAILABLE_CLI_OPTIONS = { help='Reset sample files to their original state.', action='store_true', ), + "recursive_strategy_search": Arg( + '--recursive-strategy-search', + help='Recursively search for a strategy in the strategies folder.', + action='store_true', + ), # Main options "strategy": Arg( '-s', '--strategy', @@ -101,6 +106,11 @@ AVAILABLE_CLI_OPTIONS = { f'`{constants.DEFAULT_DB_DRYRUN_URL}` for Dry Run).', metavar='PATH', ), + "db_url_from": Arg( + '--db-url-from', + help='Source db url to use when migrating a database.', + metavar='PATH', + ), "sd_notify": Arg( '--sd-notify', help='Notify systemd service manager.', @@ -438,6 +448,11 @@ AVAILABLE_CLI_OPTIONS = { default=['1m', '5m'], nargs='+', ), + "prepend_data": Arg( + '--prepend', + help='Allow data prepending.', + action='store_true', + ), "erase": Arg( '--erase', help='Clean all existing data for the selected exchange/pairs/timeframes.', diff --git a/freqtrade/commands/data_commands.py b/freqtrade/commands/data_commands.py index e41512ccc..61a99782e 100644 --- a/freqtrade/commands/data_commands.py +++ b/freqtrade/commands/data_commands.py @@ -79,12 +79,19 @@ def start_download_data(args: Dict[str, Any]) -> None: data_format_trades=config['dataformat_trades'], ) else: + if not exchange._ft_has.get('ohlcv_has_history', True): + raise OperationalException( + f"Historic klines not available for {exchange.name}. " + "Please use `--dl-trades` instead for this exchange " + "(will unfortunately take a long time)." + ) pairs_not_available = refresh_backtest_ohlcv_data( exchange, pairs=expanded_pairs, timeframes=config['timeframes'], datadir=config['datadir'], timerange=timerange, new_pairs_days=config['new_pairs_days'], erase=bool(config.get('erase')), data_format=config['dataformat_ohlcv'], trading_mode=config.get('trading_mode', 'spot'), + prepend=config.get('prepend_data', False) ) except KeyboardInterrupt: diff --git a/freqtrade/commands/db_commands.py b/freqtrade/commands/db_commands.py new file mode 100644 index 000000000..d93aafcb6 --- /dev/null +++ b/freqtrade/commands/db_commands.py @@ -0,0 +1,55 @@ +import logging +from typing import Any, Dict + +from sqlalchemy import func + +from freqtrade.configuration.config_setup import setup_utils_configuration +from freqtrade.enums.runmode import RunMode + + +logger = logging.getLogger(__name__) + + +def start_convert_db(args: Dict[str, Any]) -> None: + from sqlalchemy.orm import make_transient + + from freqtrade.persistence import Order, Trade, init_db + from freqtrade.persistence.migrations import set_sequence_ids + from freqtrade.persistence.pairlock import PairLock + + config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) + + init_db(config['db_url'], False) + session_target = Trade._session + init_db(config['db_url_from'], False) + logger.info("Starting db migration.") + + trade_count = 0 + pairlock_count = 0 + for trade in Trade.get_trades(): + trade_count += 1 + make_transient(trade) + for o in trade.orders: + make_transient(o) + + session_target.add(trade) + + session_target.commit() + + for pairlock in PairLock.query: + pairlock_count += 1 + make_transient(pairlock) + session_target.add(pairlock) + session_target.commit() + + # Update sequences + max_trade_id = session_target.query(func.max(Trade.id)).scalar() + max_order_id = session_target.query(func.max(Order.id)).scalar() + max_pairlock_id = session_target.query(func.max(PairLock.id)).scalar() + + set_sequence_ids(session_target.get_bind(), + trade_id=max_trade_id, + order_id=max_order_id, + pairlock_id=max_pairlock_id) + + logger.info(f"Migrated {trade_count} Trades, and {pairlock_count} Pairlocks.") diff --git a/freqtrade/commands/list_commands.py b/freqtrade/commands/list_commands.py index c4bd0bf4d..2a5223917 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/configuration/PeriodicCache.py b/freqtrade/configuration/PeriodicCache.py index 64fff668e..1a535440d 100644 --- a/freqtrade/configuration/PeriodicCache.py +++ b/freqtrade/configuration/PeriodicCache.py @@ -16,4 +16,4 @@ class PeriodicCache(TTLCache): return ts - offset # Init with smlight offset - super().__init__(maxsize=maxsize, ttl=ttl-1e-5, timer=local_timer, getsizeof=getsizeof) + super().__init__(maxsize=maxsize, ttl=ttl - 1e-5, timer=local_timer, getsizeof=getsizeof) diff --git a/freqtrade/configuration/config_setup.py b/freqtrade/configuration/config_setup.py index 02f2d4089..d49bf61f6 100644 --- a/freqtrade/configuration/config_setup.py +++ b/freqtrade/configuration/config_setup.py @@ -22,6 +22,6 @@ def setup_utils_configuration(args: Dict[str, Any], method: RunMode) -> Dict[str # Ensure these modes are using Dry-run config['dry_run'] = True - validate_config_consistency(config) + validate_config_consistency(config, preliminary=True) return config diff --git a/freqtrade/configuration/config_validation.py b/freqtrade/configuration/config_validation.py index 09e7b3335..ee846e7e6 100644 --- a/freqtrade/configuration/config_validation.py +++ b/freqtrade/configuration/config_validation.py @@ -39,7 +39,7 @@ def _extend_validator(validator_class): FreqtradeValidator = _extend_validator(Draft4Validator) -def validate_config_schema(conf: Dict[str, Any]) -> Dict[str, Any]: +def validate_config_schema(conf: Dict[str, Any], preliminary: bool = False) -> Dict[str, Any]: """ Validate the configuration follow the Config Schema :param conf: Config in JSON format @@ -49,7 +49,10 @@ def validate_config_schema(conf: Dict[str, Any]) -> Dict[str, Any]: if conf.get('runmode', RunMode.OTHER) in (RunMode.DRY_RUN, RunMode.LIVE): conf_schema['required'] = constants.SCHEMA_TRADE_REQUIRED elif conf.get('runmode', RunMode.OTHER) in (RunMode.BACKTEST, RunMode.HYPEROPT): - conf_schema['required'] = constants.SCHEMA_BACKTEST_REQUIRED + if preliminary: + conf_schema['required'] = constants.SCHEMA_BACKTEST_REQUIRED + else: + conf_schema['required'] = constants.SCHEMA_BACKTEST_REQUIRED_FINAL else: conf_schema['required'] = constants.SCHEMA_MINIMAL_REQUIRED try: @@ -64,7 +67,7 @@ def validate_config_schema(conf: Dict[str, Any]) -> Dict[str, Any]: ) -def validate_config_consistency(conf: Dict[str, Any]) -> None: +def validate_config_consistency(conf: Dict[str, Any], preliminary: bool = False) -> None: """ Validate the configuration consistency. Should be ran after loading both configuration and strategy, @@ -85,7 +88,7 @@ def validate_config_consistency(conf: Dict[str, Any]) -> None: # validate configuration before returning logger.info('Validating configuration ...') - validate_config_schema(conf) + validate_config_schema(conf, preliminary=preliminary) def _validate_unlimited_amount(conf: Dict[str, Any]) -> None: @@ -94,8 +97,8 @@ def _validate_unlimited_amount(conf: Dict[str, Any]) -> None: :raise: OperationalException if config validation failed """ if (not conf.get('edge', {}).get('enabled') - and conf.get('max_open_trades') == float('inf') - and conf.get('stake_amount') == constants.UNLIMITED_STAKE_AMOUNT): + and conf.get('max_open_trades') == float('inf') + and conf.get('stake_amount') == constants.UNLIMITED_STAKE_AMOUNT): raise OperationalException("`max_open_trades` and `stake_amount` cannot both be unlimited.") @@ -154,9 +157,9 @@ def _validate_edge(conf: Dict[str, Any]) -> None: if not conf.get('edge', {}).get('enabled'): return - if not conf.get('use_sell_signal', True): + if not conf.get('use_exit_signal', True): raise OperationalException( - "Edge requires `use_sell_signal` to be True, otherwise no sells will happen." + "Edge requires `use_exit_signal` to be True, otherwise no sells will happen." ) @@ -219,6 +222,7 @@ def validate_migrated_strategy_settings(conf: Dict[str, Any]) -> None: _validate_order_types(conf) _validate_unfilledtimeout(conf) _validate_pricing_rules(conf) + _strategy_settings(conf) def _validate_time_in_force(conf: Dict[str, Any]) -> None: @@ -243,7 +247,9 @@ def _validate_time_in_force(conf: Dict[str, Any]) -> None: def _validate_order_types(conf: Dict[str, Any]) -> None: order_types = conf.get('order_types', {}) - if any(x in order_types for x in ['buy', 'sell', 'emergencysell', 'forcebuy', 'forcesell']): + old_order_types = ['buy', 'sell', 'emergencysell', 'forcebuy', + 'forcesell', 'emergencyexit', 'forceexit', 'forceentry'] + if any(x in order_types for x in old_order_types): if conf.get('trading_mode', TradingMode.SPOT) != TradingMode.SPOT: raise OperationalException( "Please migrate your order_types settings to use the new wording.") @@ -255,9 +261,12 @@ def _validate_order_types(conf: Dict[str, Any]) -> None: for o, n in [ ('buy', 'entry'), ('sell', 'exit'), - ('emergencysell', 'emergencyexit'), - ('forcesell', 'forceexit'), - ('forcebuy', 'forceentry'), + ('emergencysell', 'emergency_exit'), + ('forcesell', 'force_exit'), + ('forcebuy', 'force_entry'), + ('emergencyexit', 'emergency_exit'), + ('forceexit', 'force_exit'), + ('forceentry', 'force_entry'), ]: process_deprecated_setting(conf, 'order_types', o, 'order_types', n) @@ -312,3 +321,12 @@ def _validate_pricing_rules(conf: Dict[str, Any]) -> None: else: process_deprecated_setting(conf, 'ask_strategy', obj, 'exit_pricing', obj) del conf['ask_strategy'] + + +def _strategy_settings(conf: Dict[str, Any]) -> None: + + process_deprecated_setting(conf, None, 'use_sell_signal', None, 'use_exit_signal') + process_deprecated_setting(conf, None, 'sell_profit_only', None, 'exit_profit_only') + process_deprecated_setting(conf, None, 'sell_profit_offset', None, 'exit_profit_offset') + process_deprecated_setting(conf, None, 'ignore_roi_if_buy_signal', + None, 'ignore_roi_if_entry_signal') diff --git a/freqtrade/configuration/configuration.py b/freqtrade/configuration/configuration.py index aa8f51a1d..96b585cd1 100644 --- a/freqtrade/configuration/configuration.py +++ b/freqtrade/configuration/configuration.py @@ -12,7 +12,7 @@ from freqtrade.configuration.check_exchange import check_exchange from freqtrade.configuration.deprecated_settings import process_temporary_deprecated_settings from freqtrade.configuration.directory_operations import create_datadir, create_userdata_dir from freqtrade.configuration.environment_vars import enironment_vars_to_dict -from freqtrade.configuration.load_config import load_config_file, load_file +from freqtrade.configuration.load_config import load_file, load_from_files from freqtrade.enums import NON_UTIL_MODES, TRADING_MODES, CandleType, RunMode, TradingMode from freqtrade.exceptions import OperationalException from freqtrade.loggers import setup_logging @@ -55,45 +55,28 @@ class Configuration: :param files: List of file paths :return: configuration dictionary """ + # Keep this method as staticmethod, so it can be used from interactive environments c = Configuration({'config': files}, RunMode.OTHER) return c.get_config() - def load_from_files(self, files: List[str]) -> Dict[str, Any]: - - # Keep this method as staticmethod, so it can be used from interactive environments - config: Dict[str, Any] = {} - - if not files: - return deepcopy(constants.MINIMAL_CONFIG) - - # We expect here a list of config filenames - for path in files: - logger.info(f'Using config: {path} ...') - - # Merge config options, overwriting old values - config = deep_merge_dicts(load_config_file(path), config) - - # Load environment variables - env_data = enironment_vars_to_dict() - config = deep_merge_dicts(env_data, config) - - config['config_files'] = files - # Normalize config - if 'internals' not in config: - config['internals'] = {} - - if 'pairlists' not in config: - config['pairlists'] = [] - - return config - def load_config(self) -> Dict[str, Any]: """ Extract information for sys.argv and load the bot configuration :return: Configuration dictionary """ # Load all configs - config: Dict[str, Any] = self.load_from_files(self.args.get("config", [])) + config: Dict[str, Any] = load_from_files(self.args.get("config", [])) + + # Load environment variables + env_data = enironment_vars_to_dict() + config = deep_merge_dicts(env_data, config) + + # Normalize config + if 'internals' not in config: + config['internals'] = {} + + if 'pairlists' not in config: + config['pairlists'] = [] # Keep a copy of the original configuration file config['original_config'] = deepcopy(config) @@ -164,8 +147,11 @@ class Configuration: config.update({'db_url': self.args['db_url']}) logger.info('Parameter --db-url detected ...') - if config.get('forcebuy_enable', False): - logger.warning('`forcebuy` RPC message enabled.') + self._args_to_config(config, argname='db_url_from', + logstring='Parameter --db-url-from detected ...') + + if config.get('force_entry_enable', False): + logger.warning('`force_entry_enable` RPC message enabled.') # Support for sd_notify if 'sd_notify' in self.args and self.args['sd_notify']: @@ -265,6 +251,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_strategy_search', + logstring='Recursively searching for a strategy in the strategies folder.', + ) + self._args_to_config(config, argname='timeframe', logstring='Overriding timeframe with Command line argument') @@ -404,6 +396,8 @@ class Configuration: self._args_to_config(config, argname='trade_source', logstring='Using trades from: {}') + self._args_to_config(config, argname='prepend_data', + logstring='Prepend detected. Allowing data prepending.') self._args_to_config(config, argname='erase', logstring='Erase detected. Deleting existing data.') @@ -433,8 +427,9 @@ class Configuration: logstring='Detected --new-pairs-days: {}') self._args_to_config(config, argname='trading_mode', logstring='Detected --trading-mode: {}') - config['candle_type_def'] = CandleType.get_default(config.get('trading_mode', 'spot')) - config['trading_mode'] = TradingMode(config.get('trading_mode', 'spot')) + config['candle_type_def'] = CandleType.get_default( + config.get('trading_mode', 'spot') or 'spot') + config['trading_mode'] = TradingMode(config.get('trading_mode', 'spot') or 'spot') self._args_to_config(config, argname='candle_types', logstring='Detected --candle-types: {}') diff --git a/freqtrade/configuration/deprecated_settings.py b/freqtrade/configuration/deprecated_settings.py index aa65e713a..70d29e2bd 100644 --- a/freqtrade/configuration/deprecated_settings.py +++ b/freqtrade/configuration/deprecated_settings.py @@ -12,14 +12,15 @@ logger = logging.getLogger(__name__) def check_conflicting_settings(config: Dict[str, Any], - section_old: str, name_old: str, + section_old: Optional[str], name_old: str, section_new: Optional[str], name_new: str) -> None: section_new_config = config.get(section_new, {}) if section_new else config - section_old_config = config.get(section_old, {}) + section_old_config = config.get(section_old, {}) if section_old else config if name_new in section_new_config and name_old in section_old_config: new_name = f"{section_new}.{name_new}" if section_new else f"{name_new}" + old_name = f"{section_old}.{name_old}" if section_old else f"{name_old}" raise OperationalException( - f"Conflicting settings `{new_name}` and `{section_old}.{name_old}` " + f"Conflicting settings `{new_name}` and `{old_name}` " "(DEPRECATED) detected in the configuration file. " "This deprecated setting will be removed in the next versions of Freqtrade. " f"Please delete it from your configuration and use the `{new_name}` " @@ -47,17 +48,18 @@ def process_removed_setting(config: Dict[str, Any], def process_deprecated_setting(config: Dict[str, Any], - section_old: str, name_old: str, + section_old: Optional[str], name_old: str, section_new: Optional[str], name_new: str ) -> None: check_conflicting_settings(config, section_old, name_old, section_new, name_new) - section_old_config = config.get(section_old, {}) + section_old_config = config.get(section_old, {}) if section_old else config if name_old in section_old_config: + section_1 = f"{section_old}.{name_old}" if section_old else f"{name_old}" section_2 = f"{section_new}.{name_new}" if section_new else f"{name_new}" logger.warning( "DEPRECATED: " - f"The `{section_old}.{name_old}` setting is deprecated and " + f"The `{section_1}` setting is deprecated and " "will be removed in the next versions of Freqtrade. " f"Please use the `{section_2}` setting in your configuration instead." ) @@ -72,25 +74,51 @@ def process_temporary_deprecated_settings(config: Dict[str, Any]) -> None: # Kept for future deprecated / moved settings # check_conflicting_settings(config, 'ask_strategy', 'use_sell_signal', # 'experimental', 'use_sell_signal') - process_deprecated_setting(config, 'ask_strategy', 'use_sell_signal', - None, 'use_sell_signal') - process_deprecated_setting(config, 'ask_strategy', 'sell_profit_only', - None, 'sell_profit_only') - process_deprecated_setting(config, 'ask_strategy', 'sell_profit_offset', - None, 'sell_profit_offset') - process_deprecated_setting(config, 'ask_strategy', 'ignore_roi_if_buy_signal', - None, 'ignore_roi_if_buy_signal') + process_deprecated_setting(config, 'ask_strategy', 'ignore_buying_expired_candle_after', None, 'ignore_buying_expired_candle_after') - # Legacy way - having them in experimental ... - process_removed_setting(config, 'experimental', 'use_sell_signal', - None, 'use_sell_signal') - process_removed_setting(config, 'experimental', 'sell_profit_only', - None, 'sell_profit_only') - process_removed_setting(config, 'experimental', 'ignore_roi_if_buy_signal', - None, 'ignore_roi_if_buy_signal') + process_deprecated_setting(config, None, 'forcebuy_enable', None, 'force_entry_enable') + # New settings + if config.get('telegram'): + process_deprecated_setting(config['telegram'], 'notification_settings', 'sell', + 'notification_settings', 'exit') + process_deprecated_setting(config['telegram'], 'notification_settings', 'sell_fill', + 'notification_settings', 'exit_fill') + process_deprecated_setting(config['telegram'], 'notification_settings', 'sell_cancel', + 'notification_settings', 'exit_cancel') + process_deprecated_setting(config['telegram'], 'notification_settings', 'buy', + 'notification_settings', 'entry') + process_deprecated_setting(config['telegram'], 'notification_settings', 'buy_fill', + 'notification_settings', 'entry_fill') + process_deprecated_setting(config['telegram'], 'notification_settings', 'buy_cancel', + 'notification_settings', 'entry_cancel') + if config.get('webhook'): + process_deprecated_setting(config, 'webhook', 'webhookbuy', 'webhook', 'webhookentry') + process_deprecated_setting(config, 'webhook', 'webhookbuycancel', + 'webhook', 'webhookentrycancel') + process_deprecated_setting(config, 'webhook', 'webhookbuyfill', + 'webhook', 'webhookentryfill') + process_deprecated_setting(config, 'webhook', 'webhooksell', 'webhook', 'webhookexit') + process_deprecated_setting(config, 'webhook', 'webhooksellcancel', + 'webhook', 'webhookexitcancel') + process_deprecated_setting(config, 'webhook', 'webhooksellfill', + 'webhook', 'webhookexitfill') + + # Legacy way - having them in experimental ... + + process_removed_setting(config, 'experimental', 'use_sell_signal', None, 'use_exit_signal') + process_removed_setting(config, 'experimental', 'sell_profit_only', None, 'exit_profit_only') + process_removed_setting(config, 'experimental', 'ignore_roi_if_buy_signal', + None, 'ignore_roi_if_entry_signal') + + process_removed_setting(config, 'ask_strategy', 'use_sell_signal', None, 'exit_sell_signal') + process_removed_setting(config, 'ask_strategy', 'sell_profit_only', None, 'exit_profit_only') + process_removed_setting(config, 'ask_strategy', 'sell_profit_offset', + None, 'exit_profit_offset') + process_removed_setting(config, 'ask_strategy', 'ignore_roi_if_buy_signal', + None, 'ignore_roi_if_entry_signal') if (config.get('edge', {}).get('enabled', False) and 'capital_available_percentage' in config.get('edge', {})): raise OperationalException( diff --git a/freqtrade/configuration/load_config.py b/freqtrade/configuration/load_config.py index 27190d259..3fcbd1f2f 100644 --- a/freqtrade/configuration/load_config.py +++ b/freqtrade/configuration/load_config.py @@ -4,12 +4,15 @@ This module contain functions to load the configuration file import logging import re import sys +from copy import deepcopy from pathlib import Path -from typing import Any, Dict +from typing import Any, Dict, List import rapidjson +from freqtrade.constants import MINIMAL_CONFIG from freqtrade.exceptions import OperationalException +from freqtrade.misc import deep_merge_dicts logger = logging.getLogger(__name__) @@ -28,7 +31,7 @@ def log_config_error_range(path: str, errmsg: str) -> str: offset = int(offsetlist[0]) text = Path(path).read_text() # Fetch an offset of 80 characters around the error line - subtext = text[offset-min(80, offset):offset+80] + subtext = text[offset - min(80, offset):offset + 80] segments = subtext.split('\n') if len(segments) > 3: # Remove first and last lines, to avoid odd truncations @@ -70,3 +73,43 @@ def load_config_file(path: str) -> Dict[str, Any]: ) return config + + +def load_from_files(files: List[str], base_path: Path = None, level: int = 0) -> Dict[str, Any]: + """ + Recursively load configuration files if specified. + Sub-files are assumed to be relative to the initial config. + """ + config: Dict[str, Any] = {} + if level > 5: + raise OperationalException("Config loop detected.") + + if not files: + return deepcopy(MINIMAL_CONFIG) + files_loaded = [] + # We expect here a list of config filenames + for filename in files: + logger.info(f'Using config: {filename} ...') + if filename == '-': + # Immediately load stdin and return + return load_config_file(filename) + file = Path(filename) + if base_path: + # Prepend basepath to allow for relative assignments + file = base_path / file + + config_tmp = load_config_file(str(file)) + if 'add_config_files' in config_tmp: + config_sub = load_from_files( + config_tmp['add_config_files'], file.resolve().parent, level + 1) + files_loaded.extend(config_sub.get('config_files', [])) + config_tmp = deep_merge_dicts(config_tmp, config_sub) + + files_loaded.insert(0, str(file)) + + # Merge config options, overwriting prior values + config = deep_merge_dicts(config_tmp, config) + + config['config_files'] = files_loaded + + return config diff --git a/freqtrade/constants.py b/freqtrade/constants.py index a06e2771f..372472db8 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -3,7 +3,7 @@ """ bot constants """ -from typing import List, Tuple +from typing import List, Literal, Tuple from freqtrade.enums import CandleType @@ -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' @@ -28,7 +28,8 @@ HYPEROPT_LOSS_BUILTIN = ['ShortTradeDurHyperOptLoss', 'OnlyProfitHyperOptLoss', 'SharpeHyperOptLoss', 'SharpeHyperOptLossDaily', 'SortinoHyperOptLoss', 'SortinoHyperOptLossDaily', 'CalmarHyperOptLoss', - 'MaxDrawDownHyperOptLoss', 'ProfitDrawDownHyperOptLoss'] + 'MaxDrawDownHyperOptLoss', 'MaxDrawDownRelativeHyperOptLoss', + 'ProfitDrawDownHyperOptLoss'] AVAILABLE_PAIRLISTS = ['StaticPairList', 'VolumePairList', 'AgeFilter', 'OffsetFilter', 'PerformanceFilter', 'PrecisionFilter', 'PriceFilter', 'RangeStabilityFilter', @@ -86,20 +87,19 @@ SUPPORTED_FIAT = [ "AUD", "BRL", "CAD", "CHF", "CLP", "CNY", "CZK", "DKK", "EUR", "GBP", "HKD", "HUF", "IDR", "ILS", "INR", "JPY", "KRW", "MXN", "MYR", "NOK", "NZD", "PHP", "PKR", "PLN", - "RUB", "SEK", "SGD", "THB", "TRY", "TWD", "ZAR", "USD", - "BTC", "ETH", "XRP", "LTC", "BCH" + "RUB", "UAH", "SEK", "SGD", "THB", "TRY", "TWD", "ZAR", + "USD", "BTC", "ETH", "XRP", "LTC", "BCH" ] MINIMAL_CONFIG = { - 'stake_currency': '', - 'dry_run': True, - 'exchange': { - 'name': '', - 'key': '', - 'secret': '', - 'pair_whitelist': [], - 'ccxt_async_config': { - 'enableRateLimit': True, + "stake_currency": "", + "dry_run": True, + "exchange": { + "name": "", + "key": "", + "secret": "", + "pair_whitelist": [], + "ccxt_async_config": { } } } @@ -149,10 +149,10 @@ CONF_SCHEMA = { 'trailing_stop_positive': {'type': 'number', 'minimum': 0, 'maximum': 1}, 'trailing_stop_positive_offset': {'type': 'number', 'minimum': 0, 'maximum': 1}, 'trailing_only_offset_is_reached': {'type': 'boolean'}, - 'use_sell_signal': {'type': 'boolean'}, - 'sell_profit_only': {'type': 'boolean'}, - 'sell_profit_offset': {'type': 'number'}, - 'ignore_roi_if_buy_signal': {'type': 'boolean'}, + 'use_exit_signal': {'type': 'boolean'}, + 'exit_profit_only': {'type': 'boolean'}, + 'exit_profit_offset': {'type': 'number'}, + 'ignore_roi_if_entry_signal': {'type': 'boolean'}, 'ignore_buying_expired_candle_after': {'type': 'number'}, 'trading_mode': {'type': 'string', 'enum': TRADING_MODES}, 'margin_mode': {'type': 'string', 'enum': MARGIN_MODES}, @@ -216,9 +216,9 @@ CONF_SCHEMA = { 'properties': { 'entry': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES}, 'exit': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES}, - 'forceexit': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES}, - 'forceentry': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES}, - 'emergencyexit': { + 'force_exit': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES}, + 'force_entry': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES}, + 'emergency_exit': { 'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES, 'default': 'market'}, @@ -285,21 +285,21 @@ CONF_SCHEMA = { 'status': {'type': 'string', 'enum': TELEGRAM_SETTING_OPTIONS}, 'warning': {'type': 'string', 'enum': TELEGRAM_SETTING_OPTIONS}, 'startup': {'type': 'string', 'enum': TELEGRAM_SETTING_OPTIONS}, - 'buy': {'type': 'string', 'enum': TELEGRAM_SETTING_OPTIONS}, - 'buy_cancel': {'type': 'string', 'enum': TELEGRAM_SETTING_OPTIONS}, - 'buy_fill': {'type': 'string', - 'enum': TELEGRAM_SETTING_OPTIONS, - 'default': 'off' - }, - 'sell': { + 'entry': {'type': 'string', 'enum': TELEGRAM_SETTING_OPTIONS}, + 'entry_cancel': {'type': 'string', 'enum': TELEGRAM_SETTING_OPTIONS}, + 'entry_fill': {'type': 'string', + 'enum': TELEGRAM_SETTING_OPTIONS, + 'default': 'off' + }, + 'exit': { 'type': ['string', 'object'], 'additionalProperties': { 'type': 'string', 'enum': TELEGRAM_SETTING_OPTIONS } }, - 'sell_cancel': {'type': 'string', 'enum': TELEGRAM_SETTING_OPTIONS}, - 'sell_fill': { + 'exit_cancel': {'type': 'string', 'enum': TELEGRAM_SETTING_OPTIONS}, + 'exit_fill': { 'type': 'string', 'enum': TELEGRAM_SETTING_OPTIONS, 'default': 'off' @@ -327,12 +327,12 @@ CONF_SCHEMA = { 'format': {'type': 'string', 'enum': WEBHOOK_FORMAT_OPTIONS, 'default': 'form'}, 'retries': {'type': 'integer', 'minimum': 0}, 'retry_delay': {'type': 'number', 'minimum': 0}, - 'webhookbuy': {'type': 'object'}, - 'webhookbuycancel': {'type': 'object'}, - 'webhookbuyfill': {'type': 'object'}, - 'webhooksell': {'type': 'object'}, - 'webhooksellcancel': {'type': 'object'}, - 'webhooksellfill': {'type': 'object'}, + 'webhookentry': {'type': 'object'}, + 'webhookentrycancel': {'type': 'object'}, + 'webhookentryfill': {'type': 'object'}, + 'webhookexit': {'type': 'object'}, + 'webhookexitcancel': {'type': 'object'}, + 'webhookexitfill': {'type': 'object'}, 'webhookstatus': {'type': 'object'}, }, }, @@ -358,7 +358,7 @@ CONF_SCHEMA = { 'export': {'type': 'string', 'enum': EXPORT_OPTIONS, 'default': 'trades'}, 'disableparamexport': {'type': 'boolean'}, 'initial_state': {'type': 'string', 'enum': ['running', 'stopped']}, - 'forcebuy_enable': {'type': 'boolean'}, + 'force_entry_enable': {'type': 'boolean'}, 'disable_dataframe_checks': {'type': 'boolean'}, 'internals': { 'type': 'object', @@ -463,6 +463,10 @@ SCHEMA_BACKTEST_REQUIRED = [ 'dataformat_ohlcv', 'dataformat_trades', ] +SCHEMA_BACKTEST_REQUIRED_FINAL = SCHEMA_BACKTEST_REQUIRED + [ + 'stoploss', + 'minimal_roi', +] SCHEMA_MINIMAL_REQUIRED = [ 'exchange', @@ -478,7 +482,9 @@ CANCEL_REASON = { "FULLY_CANCELLED": "fully cancelled", "ALL_CANCELLED": "cancelled (all unfilled and partially filled open orders cancelled)", "CANCELLED_ON_EXCHANGE": "cancelled on exchange", - "FORCE_SELL": "forcesold", + "FORCE_EXIT": "forcesold", + "REPLACE": "cancelled to be replaced by new limit order", + "USER_CANCEL": "user requested order cancel" } # List of pairs with their timeframes @@ -487,3 +493,7 @@ ListPairsWithTimeframes = List[PairWithTimeframe] # Type for trades list TradeList = List[List] + +LongShort = Literal['long', 'short'] +EntryExit = Literal['entry', 'exit'] +BuySell = Literal['buy', 'sell'] diff --git a/freqtrade/data/btanalysis.py b/freqtrade/data/btanalysis.py index 4df8b2838..e29d9ebe4 100644 --- a/freqtrade/data/btanalysis.py +++ b/freqtrade/data/btanalysis.py @@ -5,14 +5,15 @@ import logging from copy import copy from datetime import datetime, timezone from pathlib import Path -from typing import Any, Dict, List, Optional, Tuple, Union +from typing import Any, Dict, List, Optional, Union import numpy as np 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 @@ -22,7 +23,7 @@ logger = logging.getLogger(__name__) BT_DATA_COLUMNS = ['pair', 'stake_amount', 'amount', 'open_date', 'close_date', 'open_rate', 'close_rate', 'fee_open', 'fee_close', 'trade_duration', - 'profit_ratio', 'profit_abs', 'sell_reason', + 'profit_ratio', 'profit_abs', 'exit_reason', 'initial_stop_loss_abs', 'initial_stop_loss_ratio', 'stop_loss_abs', 'stop_loss_ratio', 'min_rate', 'max_rate', 'is_open', 'enter_tag', 'is_short' @@ -149,7 +150,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] @@ -160,6 +168,30 @@ def _load_and_merge_backtest_result(strategy_name: str, filename: Path, results: break +def _get_backtest_files(dirname: Path) -> List[Path]: + return list(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 +211,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 @@ -193,14 +225,7 @@ def find_existing_backtest_stats(dirname: Union[Path, str], run_ids: Dict[str, s continue if min_backtest_date is not None: - try: - backtest_date = strategy_metadata['backtest_start_time'] - except KeyError: - # TODO: this can be removed starting from feb 2022 - # The metadata-file without start_time was only available in develop - # and was never included in an official release. - # Older metadata format without backtest time, too old to consider. - return results + backtest_date = strategy_metadata['backtest_start_time'] backtest_date = datetime.fromtimestamp(backtest_date, tz=timezone.utc) if backtest_date < min_backtest_date: # Do not use a cached result for this strategy as first result is too old. @@ -209,7 +234,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 @@ -375,157 +400,3 @@ def extract_trades_of_period(dataframe: pd.DataFrame, trades: pd.DataFrame, trades = trades.loc[(trades['open_date'] >= trades_start) & (trades['close_date'] <= trades_stop)] return trades - - -def calculate_market_change(data: Dict[str, pd.DataFrame], column: str = "close") -> float: - """ - Calculate market change based on "column". - Calculation is done by taking the first non-null and the last non-null element of each column - and calculating the pctchange as "(last - first) / first". - Then the results per pair are combined as mean. - - :param data: Dict of Dataframes, dict key should be pair. - :param column: Column in the original dataframes to use - :return: - """ - tmp_means = [] - for pair, df in data.items(): - start = df[column].dropna().iloc[0] - end = df[column].dropna().iloc[-1] - tmp_means.append((end - start) / start) - - return float(np.mean(tmp_means)) - - -def combine_dataframes_with_mean(data: Dict[str, pd.DataFrame], - column: str = "close") -> pd.DataFrame: - """ - Combine multiple dataframes "column" - :param data: Dict of Dataframes, dict key should be pair. - :param column: Column in the original dataframes to use - :return: DataFrame with the column renamed to the dict key, and a column - named mean, containing the mean of all pairs. - :raise: ValueError if no data is provided. - """ - df_comb = pd.concat([data[pair].set_index('date').rename( - {column: pair}, axis=1)[pair] for pair in data], axis=1) - - df_comb['mean'] = df_comb.mean(axis=1) - - return df_comb - - -def create_cum_profit(df: pd.DataFrame, trades: pd.DataFrame, col_name: str, - timeframe: str) -> pd.DataFrame: - """ - Adds a column `col_name` with the cumulative profit for the given trades array. - :param df: DataFrame with date index - :param trades: DataFrame containing trades (requires columns close_date and profit_abs) - :param col_name: Column name that will be assigned the results - :param timeframe: Timeframe used during the operations - :return: Returns df with one additional column, col_name, containing the cumulative profit. - :raise: ValueError if trade-dataframe was found empty. - """ - if len(trades) == 0: - raise ValueError("Trade dataframe empty.") - from freqtrade.exchange import timeframe_to_minutes - timeframe_minutes = timeframe_to_minutes(timeframe) - # Resample to timeframe to make sure trades match candles - _trades_sum = trades.resample(f'{timeframe_minutes}min', on='close_date' - )[['profit_abs']].sum() - df.loc[:, col_name] = _trades_sum['profit_abs'].cumsum() - # Set first value to 0 - df.loc[df.iloc[0].name, col_name] = 0 - # FFill to get continuous - df[col_name] = df[col_name].ffill() - return df - - -def _calc_drawdown_series(profit_results: pd.DataFrame, *, date_col: str, value_col: str - ) -> pd.DataFrame: - max_drawdown_df = pd.DataFrame() - max_drawdown_df['cumulative'] = profit_results[value_col].cumsum() - max_drawdown_df['high_value'] = max_drawdown_df['cumulative'].cummax() - max_drawdown_df['drawdown'] = max_drawdown_df['cumulative'] - max_drawdown_df['high_value'] - max_drawdown_df['date'] = profit_results.loc[:, date_col] - return max_drawdown_df - - -def calculate_underwater(trades: pd.DataFrame, *, date_col: str = 'close_date', - value_col: str = 'profit_ratio' - ): - """ - Calculate max drawdown and the corresponding close dates - :param trades: DataFrame containing trades (requires columns close_date and profit_ratio) - :param date_col: Column in DataFrame to use for dates (defaults to 'close_date') - :param value_col: Column in DataFrame to use for values (defaults to 'profit_ratio') - :return: Tuple (float, highdate, lowdate, highvalue, lowvalue) with absolute max drawdown, - high and low time and high and low value. - :raise: ValueError if trade-dataframe was found empty. - """ - if len(trades) == 0: - raise ValueError("Trade dataframe empty.") - profit_results = trades.sort_values(date_col).reset_index(drop=True) - max_drawdown_df = _calc_drawdown_series(profit_results, date_col=date_col, value_col=value_col) - - return max_drawdown_df - - -def calculate_max_drawdown(trades: pd.DataFrame, *, date_col: str = 'close_date', - value_col: str = 'profit_abs', starting_balance: float = 0 - ) -> Tuple[float, pd.Timestamp, pd.Timestamp, float, float, float]: - """ - Calculate max drawdown and the corresponding close dates - :param trades: DataFrame containing trades (requires columns close_date and profit_ratio) - :param date_col: Column in DataFrame to use for dates (defaults to 'close_date') - :param value_col: Column in DataFrame to use for values (defaults to 'profit_abs') - :param starting_balance: Portfolio starting balance - properly calculate relative drawdown. - :return: Tuple (float, highdate, lowdate, highvalue, lowvalue, relative_drawdown) - with absolute max drawdown, high and low time and high and low value, - and the relative account drawdown - :raise: ValueError if trade-dataframe was found empty. - """ - if len(trades) == 0: - raise ValueError("Trade dataframe empty.") - profit_results = trades.sort_values(date_col).reset_index(drop=True) - max_drawdown_df = _calc_drawdown_series(profit_results, date_col=date_col, value_col=value_col) - - idxmin = max_drawdown_df['drawdown'].idxmin() - if idxmin == 0: - raise ValueError("No losing trade, therefore no drawdown.") - high_date = profit_results.loc[max_drawdown_df.iloc[:idxmin]['high_value'].idxmax(), date_col] - low_date = profit_results.loc[idxmin, date_col] - high_val = max_drawdown_df.loc[max_drawdown_df.iloc[:idxmin] - ['high_value'].idxmax(), 'cumulative'] - low_val = max_drawdown_df.loc[idxmin, 'cumulative'] - max_drawdown_rel = 0.0 - if high_val + starting_balance != 0: - max_drawdown_rel = (high_val - low_val) / (high_val + starting_balance) - - return ( - abs(min(max_drawdown_df['drawdown'])), - high_date, - low_date, - high_val, - low_val, - max_drawdown_rel - ) - - -def calculate_csum(trades: pd.DataFrame, starting_balance: float = 0) -> Tuple[float, float]: - """ - Calculate min/max cumsum of trades, to show if the wallet/stake amount ratio is sane - :param trades: DataFrame containing trades (requires columns close_date and profit_percent) - :param starting_balance: Add starting balance to results, to show the wallets high / low points - :return: Tuple (float, float) with cumsum of profit_abs - :raise: ValueError if trade-dataframe was found empty. - """ - if len(trades) == 0: - raise ValueError("Trade dataframe empty.") - - csum_df = pd.DataFrame() - csum_df['sum'] = trades['profit_abs'].cumsum() - csum_min = csum_df['sum'].min() + starting_balance - csum_max = csum_df['sum'].max() + starting_balance - - return csum_min, csum_max diff --git a/freqtrade/data/history/history_utils.py b/freqtrade/data/history/history_utils.py index 515a345f1..eb36d2042 100644 --- a/freqtrade/data/history/history_utils.py +++ b/freqtrade/data/history/history_utils.py @@ -139,8 +139,9 @@ def _load_cached_data_for_updating( timeframe: str, timerange: Optional[TimeRange], data_handler: IDataHandler, - candle_type: CandleType -) -> Tuple[DataFrame, Optional[int]]: + candle_type: CandleType, + prepend: bool = False, +) -> Tuple[DataFrame, Optional[int], Optional[int]]: """ Load cached data to download more data. If timerange is passed in, checks whether data from an before the stored data will be @@ -150,9 +151,12 @@ def _load_cached_data_for_updating( Note: Only used by download_pair_history(). """ start = None + end = None if timerange: if timerange.starttype == 'date': start = datetime.fromtimestamp(timerange.startts, tz=timezone.utc) + if timerange.stoptype == 'date': + end = datetime.fromtimestamp(timerange.stopts, tz=timezone.utc) # Intentionally don't pass timerange in - since we need to load the full dataset. data = data_handler.ohlcv_load(pair, timeframe=timeframe, @@ -160,14 +164,17 @@ def _load_cached_data_for_updating( drop_incomplete=True, warn_no_data=False, candle_type=candle_type) if not data.empty: - if start and start < data.iloc[0]['date']: + if not prepend and start and start < data.iloc[0]['date']: # Earlier data than existing data requested, redownload all data = DataFrame(columns=DEFAULT_DATAFRAME_COLUMNS) else: - start = data.iloc[-1]['date'] - + if prepend: + end = data.iloc[0]['date'] + else: + start = data.iloc[-1]['date'] start_ms = int(start.timestamp() * 1000) if start else None - return data, start_ms + end_ms = int(end.timestamp() * 1000) if end else None + return data, start_ms, end_ms def _download_pair_history(pair: str, *, @@ -179,6 +186,8 @@ def _download_pair_history(pair: str, *, data_handler: IDataHandler = None, timerange: Optional[TimeRange] = None, candle_type: CandleType, + erase: bool = False, + prepend: bool = False, ) -> bool: """ Download latest candles from the exchange for the pair and timeframe passed in parameters @@ -186,25 +195,31 @@ def _download_pair_history(pair: str, *, exists in a cache. If timerange starts earlier than the data in the cache, the full data will be redownloaded - Based on @Rybolov work: https://github.com/rybolov/freqtrade-data - :param pair: pair to download :param timeframe: Timeframe (e.g "5m") :param timerange: range of time to download :param candle_type: Any of the enum CandleType (must match trading mode!) + :param erase: Erase existing data :return: bool with success state """ data_handler = get_datahandler(datadir, data_handler=data_handler) try: - logger.info( - f'Download history data for pair: "{pair}" ({process}), timeframe: {timeframe}, ' - f'candle type: {candle_type} and store in {datadir}.' - ) + if erase: + if data_handler.ohlcv_purge(pair, timeframe, candle_type=candle_type): + logger.info(f'Deleting existing data for pair {pair}, {timeframe}, {candle_type}.') - data, since_ms = _load_cached_data_for_updating(pair, timeframe, timerange, - data_handler=data_handler, - candle_type=candle_type) + data, since_ms, until_ms = _load_cached_data_for_updating( + pair, timeframe, timerange, + data_handler=data_handler, + candle_type=candle_type, + prepend=prepend) + + logger.info(f'({process}) - Download history data for "{pair}", {timeframe}, ' + f'{candle_type} and store in {datadir}.' + f'From {format_ms_time(since_ms) if since_ms else "start"} to ' + f'{format_ms_time(until_ms) if until_ms else "now"}' + ) logger.debug("Current Start: %s", f"{data.iloc[0]['date']:%Y-%m-%d %H:%M:%S}" if not data.empty else 'None') @@ -219,6 +234,7 @@ def _download_pair_history(pair: str, *, days=-new_pairs_days).int_timestamp * 1000, is_new_pair=data.empty, candle_type=candle_type, + until_ms=until_ms if until_ms else None ) # TODO: Maybe move parsing to exchange class (?) new_dataframe = ohlcv_to_dataframe(new_data, timeframe, pair, @@ -251,6 +267,7 @@ def refresh_backtest_ohlcv_data(exchange: Exchange, pairs: List[str], timeframes timerange: Optional[TimeRange] = None, new_pairs_days: int = 30, erase: bool = False, data_format: str = None, + prepend: bool = False, ) -> List[str]: """ Refresh stored ohlcv data for backtesting and hyperopt operations. @@ -267,35 +284,28 @@ def refresh_backtest_ohlcv_data(exchange: Exchange, pairs: List[str], timeframes continue for timeframe in timeframes: - if erase: - if data_handler.ohlcv_purge(pair, timeframe, candle_type=candle_type): - logger.info(f'Deleting existing data for pair {pair}, interval {timeframe}.') - logger.info(f'Downloading pair {pair}, interval {timeframe}.') process = f'{idx}/{len(pairs)}' _download_pair_history(pair=pair, process=process, datadir=datadir, exchange=exchange, timerange=timerange, data_handler=data_handler, timeframe=str(timeframe), new_pairs_days=new_pairs_days, - candle_type=candle_type) + candle_type=candle_type, + erase=erase, prepend=prepend) if trading_mode == 'futures': # Predefined candletype (and timeframe) depending on exchange # Downloads what is necessary to backtest based on futures data. - timeframe = exchange._ft_has['mark_ohlcv_timeframe'] + tf_mark = exchange._ft_has['mark_ohlcv_timeframe'] fr_candle_type = CandleType.from_string(exchange._ft_has['mark_ohlcv_price']) # All exchanges need FundingRate for futures trading. # The timeframe is aligned to the mark-price timeframe. for funding_candle_type in (CandleType.FUNDING_RATE, fr_candle_type): - # TODO: this could be in most parts to the above. - if erase: - if data_handler.ohlcv_purge(pair, timeframe, candle_type=funding_candle_type): - logger.info( - f'Deleting existing data for pair {pair}, interval {timeframe}.') _download_pair_history(pair=pair, process=process, datadir=datadir, exchange=exchange, timerange=timerange, data_handler=data_handler, - timeframe=str(timeframe), new_pairs_days=new_pairs_days, - candle_type=funding_candle_type) + timeframe=str(tf_mark), new_pairs_days=new_pairs_days, + candle_type=funding_candle_type, + erase=erase, prepend=prepend) return pairs_not_available @@ -313,8 +323,9 @@ def _download_trades_history(exchange: Exchange, try: until = None - if (timerange and timerange.starttype == 'date'): - since = timerange.startts * 1000 + if timerange: + if timerange.starttype == 'date': + since = timerange.startts * 1000 if timerange.stoptype == 'date': until = timerange.stopts * 1000 else: diff --git a/freqtrade/data/history/idatahandler.py b/freqtrade/data/history/idatahandler.py index 4a5eb6bc2..2e6b070ca 100644 --- a/freqtrade/data/history/idatahandler.py +++ b/freqtrade/data/history/idatahandler.py @@ -5,7 +5,7 @@ It's subclasses handle and storing data from disk. """ import logging import re -from abc import ABC, abstractclassmethod, abstractmethod +from abc import ABC, abstractmethod from copy import deepcopy from datetime import datetime, timezone from pathlib import Path @@ -38,7 +38,8 @@ class IDataHandler(ABC): """ raise NotImplementedError() - @abstractclassmethod + @classmethod + @abstractmethod def ohlcv_get_available_data( cls, datadir: Path, trading_mode: TradingMode) -> ListPairsWithTimeframes: """ @@ -48,7 +49,8 @@ class IDataHandler(ABC): :return: List of Tuples of (pair, timeframe) """ - @abstractclassmethod + @classmethod + @abstractmethod def ohlcv_get_pairs(cls, datadir: Path, timeframe: str, candle_type: CandleType) -> List[str]: """ Returns a list of all pairs with ohlcv data available in this datadir @@ -118,7 +120,8 @@ class IDataHandler(ABC): :param candle_type: Any of the enum CandleType (must match trading mode!) """ - @abstractclassmethod + @classmethod + @abstractmethod def trades_get_pairs(cls, datadir: Path) -> List[str]: """ Returns a list of all pairs for which trade data is available in this diff --git a/freqtrade/data/metrics.py b/freqtrade/data/metrics.py new file mode 100644 index 000000000..c11a2df88 --- /dev/null +++ b/freqtrade/data/metrics.py @@ -0,0 +1,192 @@ +import logging +from typing import Dict, Tuple + +import numpy as np +import pandas as pd + + +logger = logging.getLogger(__name__) + + +def calculate_market_change(data: Dict[str, pd.DataFrame], column: str = "close") -> float: + """ + Calculate market change based on "column". + Calculation is done by taking the first non-null and the last non-null element of each column + and calculating the pctchange as "(last - first) / first". + Then the results per pair are combined as mean. + + :param data: Dict of Dataframes, dict key should be pair. + :param column: Column in the original dataframes to use + :return: + """ + tmp_means = [] + for pair, df in data.items(): + start = df[column].dropna().iloc[0] + end = df[column].dropna().iloc[-1] + tmp_means.append((end - start) / start) + + return float(np.mean(tmp_means)) + + +def combine_dataframes_with_mean(data: Dict[str, pd.DataFrame], + column: str = "close") -> pd.DataFrame: + """ + Combine multiple dataframes "column" + :param data: Dict of Dataframes, dict key should be pair. + :param column: Column in the original dataframes to use + :return: DataFrame with the column renamed to the dict key, and a column + named mean, containing the mean of all pairs. + :raise: ValueError if no data is provided. + """ + df_comb = pd.concat([data[pair].set_index('date').rename( + {column: pair}, axis=1)[pair] for pair in data], axis=1) + + df_comb['mean'] = df_comb.mean(axis=1) + + return df_comb + + +def create_cum_profit(df: pd.DataFrame, trades: pd.DataFrame, col_name: str, + timeframe: str) -> pd.DataFrame: + """ + Adds a column `col_name` with the cumulative profit for the given trades array. + :param df: DataFrame with date index + :param trades: DataFrame containing trades (requires columns close_date and profit_abs) + :param col_name: Column name that will be assigned the results + :param timeframe: Timeframe used during the operations + :return: Returns df with one additional column, col_name, containing the cumulative profit. + :raise: ValueError if trade-dataframe was found empty. + """ + if len(trades) == 0: + raise ValueError("Trade dataframe empty.") + from freqtrade.exchange import timeframe_to_minutes + timeframe_minutes = timeframe_to_minutes(timeframe) + # Resample to timeframe to make sure trades match candles + _trades_sum = trades.resample(f'{timeframe_minutes}min', on='close_date' + )[['profit_abs']].sum() + df.loc[:, col_name] = _trades_sum['profit_abs'].cumsum() + # Set first value to 0 + df.loc[df.iloc[0].name, col_name] = 0 + # FFill to get continuous + df[col_name] = df[col_name].ffill() + return df + + +def _calc_drawdown_series(profit_results: pd.DataFrame, *, date_col: str, value_col: str, + starting_balance: float) -> pd.DataFrame: + max_drawdown_df = pd.DataFrame() + max_drawdown_df['cumulative'] = profit_results[value_col].cumsum() + max_drawdown_df['high_value'] = max_drawdown_df['cumulative'].cummax() + max_drawdown_df['drawdown'] = max_drawdown_df['cumulative'] - max_drawdown_df['high_value'] + max_drawdown_df['date'] = profit_results.loc[:, date_col] + if starting_balance: + cumulative_balance = starting_balance + max_drawdown_df['cumulative'] + max_balance = starting_balance + max_drawdown_df['high_value'] + max_drawdown_df['drawdown_relative'] = ((max_balance - cumulative_balance) / max_balance) + else: + # NOTE: This is not completely accurate, + # but might good enough if starting_balance is not available + max_drawdown_df['drawdown_relative'] = ( + (max_drawdown_df['high_value'] - max_drawdown_df['cumulative']) + / max_drawdown_df['high_value']) + return max_drawdown_df + + +def calculate_underwater(trades: pd.DataFrame, *, date_col: str = 'close_date', + value_col: str = 'profit_ratio', starting_balance: float = 0.0 + ): + """ + Calculate max drawdown and the corresponding close dates + :param trades: DataFrame containing trades (requires columns close_date and profit_ratio) + :param date_col: Column in DataFrame to use for dates (defaults to 'close_date') + :param value_col: Column in DataFrame to use for values (defaults to 'profit_ratio') + :return: Tuple (float, highdate, lowdate, highvalue, lowvalue) with absolute max drawdown, + high and low time and high and low value. + :raise: ValueError if trade-dataframe was found empty. + """ + if len(trades) == 0: + raise ValueError("Trade dataframe empty.") + profit_results = trades.sort_values(date_col).reset_index(drop=True) + max_drawdown_df = _calc_drawdown_series( + profit_results, + date_col=date_col, + value_col=value_col, + starting_balance=starting_balance) + + return max_drawdown_df + + +def calculate_max_drawdown(trades: pd.DataFrame, *, date_col: str = 'close_date', + value_col: str = 'profit_abs', starting_balance: float = 0, + relative: bool = False + ) -> Tuple[float, pd.Timestamp, pd.Timestamp, float, float, float]: + """ + Calculate max drawdown and the corresponding close dates + :param trades: DataFrame containing trades (requires columns close_date and profit_ratio) + :param date_col: Column in DataFrame to use for dates (defaults to 'close_date') + :param value_col: Column in DataFrame to use for values (defaults to 'profit_abs') + :param starting_balance: Portfolio starting balance - properly calculate relative drawdown. + :return: Tuple (float, highdate, lowdate, highvalue, lowvalue, relative_drawdown) + with absolute max drawdown, high and low time and high and low value, + and the relative account drawdown + :raise: ValueError if trade-dataframe was found empty. + """ + if len(trades) == 0: + raise ValueError("Trade dataframe empty.") + profit_results = trades.sort_values(date_col).reset_index(drop=True) + max_drawdown_df = _calc_drawdown_series( + profit_results, + date_col=date_col, + value_col=value_col, + starting_balance=starting_balance + ) + + idxmin = max_drawdown_df['drawdown_relative'].idxmax() if relative \ + else max_drawdown_df['drawdown'].idxmin() + if idxmin == 0: + raise ValueError("No losing trade, therefore no drawdown.") + high_date = profit_results.loc[max_drawdown_df.iloc[:idxmin]['high_value'].idxmax(), date_col] + low_date = profit_results.loc[idxmin, date_col] + high_val = max_drawdown_df.loc[max_drawdown_df.iloc[:idxmin] + ['high_value'].idxmax(), 'cumulative'] + low_val = max_drawdown_df.loc[idxmin, 'cumulative'] + max_drawdown_rel = max_drawdown_df.loc[idxmin, 'drawdown_relative'] + + return ( + abs(max_drawdown_df.loc[idxmin, 'drawdown']), + high_date, + low_date, + high_val, + low_val, + max_drawdown_rel + ) + + +def calculate_csum(trades: pd.DataFrame, starting_balance: float = 0) -> Tuple[float, float]: + """ + Calculate min/max cumsum of trades, to show if the wallet/stake amount ratio is sane + :param trades: DataFrame containing trades (requires columns close_date and profit_percent) + :param starting_balance: Add starting balance to results, to show the wallets high / low points + :return: Tuple (float, float) with cumsum of profit_abs + :raise: ValueError if trade-dataframe was found empty. + """ + if len(trades) == 0: + raise ValueError("Trade dataframe empty.") + + csum_df = pd.DataFrame() + csum_df['sum'] = trades['profit_abs'].cumsum() + csum_min = csum_df['sum'].min() + starting_balance + 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/edge/edge_positioning.py b/freqtrade/edge/edge_positioning.py index 8116949cf..2fe41a17b 100644 --- a/freqtrade/edge/edge_positioning.py +++ b/freqtrade/edge/edge_positioning.py @@ -470,7 +470,7 @@ class Edge: if len(ohlc_columns) - 1 < exit_index: break - exit_type = ExitType.SELL_SIGNAL + exit_type = ExitType.EXIT_SIGNAL exit_price = ohlc_columns[exit_index, 0] trade = {'pair': pair, diff --git a/freqtrade/enums/exittype.py b/freqtrade/enums/exittype.py index 36d2a4f9e..b2c5b62ea 100644 --- a/freqtrade/enums/exittype.py +++ b/freqtrade/enums/exittype.py @@ -3,16 +3,16 @@ from enum import Enum class ExitType(Enum): """ - Enum to distinguish between sell reasons + Enum to distinguish between exit reasons """ ROI = "roi" STOP_LOSS = "stop_loss" STOPLOSS_ON_EXCHANGE = "stoploss_on_exchange" TRAILING_STOP_LOSS = "trailing_stop_loss" - SELL_SIGNAL = "sell_signal" - FORCE_SELL = "force_sell" - EMERGENCY_SELL = "emergency_sell" - CUSTOM_SELL = "custom_sell" + EXIT_SIGNAL = "exit_signal" + FORCE_EXIT = "force_exit" + EMERGENCY_EXIT = "emergency_exit" + CUSTOM_EXIT = "custom_exit" NONE = "" def __str__(self): diff --git a/freqtrade/enums/rpcmessagetype.py b/freqtrade/enums/rpcmessagetype.py index 661f9ce5c..584a011c2 100644 --- a/freqtrade/enums/rpcmessagetype.py +++ b/freqtrade/enums/rpcmessagetype.py @@ -6,19 +6,13 @@ class RPCMessageType(Enum): WARNING = 'warning' STARTUP = 'startup' - BUY = 'buy' - BUY_FILL = 'buy_fill' - BUY_CANCEL = 'buy_cancel' + ENTRY = 'entry' + ENTRY_FILL = 'entry_fill' + ENTRY_CANCEL = 'entry_cancel' - SHORT = 'short' - SHORT_FILL = 'short_fill' - SHORT_CANCEL = 'short_cancel' - - # TODO: The below messagetypes should be renamed to "exit"! - # Careful - has an impact on webhooks, therefore needs proper communication - SELL = 'sell' - SELL_FILL = 'sell_fill' - SELL_CANCEL = 'sell_cancel' + EXIT = 'exit' + EXIT_FILL = 'exit_fill' + EXIT_CANCEL = 'exit_cancel' PROTECTION_TRIGGER = 'protection_trigger' PROTECTION_TRIGGER_GLOBAL = 'protection_trigger_global' diff --git a/freqtrade/exchange/binance.py b/freqtrade/exchange/binance.py index 8c442cd26..69ae5198a 100644 --- a/freqtrade/exchange/binance.py +++ b/freqtrade/exchange/binance.py @@ -95,6 +95,7 @@ class Binance(Exchange): async def _async_get_historic_ohlcv(self, pair: str, timeframe: str, since_ms: int, candle_type: CandleType, is_new_pair: bool = False, raise_: bool = False, + until_ms: int = None ) -> Tuple[str, str, str, List]: """ Overwrite to introduce "fast new pair" functionality by detecting the pair's listing date @@ -115,7 +116,8 @@ class Binance(Exchange): since_ms=since_ms, is_new_pair=is_new_pair, raise_=raise_, - candle_type=candle_type + candle_type=candle_type, + until_ms=until_ms, ) def funding_fee_cutoff(self, open_date: datetime): 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/common.py b/freqtrade/exchange/common.py index 997c16ff1..4355662a8 100644 --- a/freqtrade/exchange/common.py +++ b/freqtrade/exchange/common.py @@ -102,7 +102,7 @@ def calculate_backoff(retrycount, max_retries): def retrier_async(f): async def wrapper(*args, **kwargs): count = kwargs.pop('count', API_RETRY_COUNT) - kucoin = args[0].name == "Kucoin" # Check if the exchange is KuCoin. + kucoin = args[0].name == "KuCoin" # Check if the exchange is KuCoin. try: return await f(*args, **kwargs) except TemporaryError as ex: diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 09ada4452..ee804aa68 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 @@ -19,8 +20,8 @@ from ccxt.base.decimal_to_precision import (ROUND_DOWN, ROUND_UP, TICK_SIZE, TRU decimal_to_precision) from pandas import DataFrame -from freqtrade.constants import (DEFAULT_AMOUNT_RESERVE_PERCENT, NON_OPEN_EXCHANGE_STATES, - ListPairsWithTimeframes, PairWithTimeframe) +from freqtrade.constants import (DEFAULT_AMOUNT_RESERVE_PERCENT, NON_OPEN_EXCHANGE_STATES, BuySell, + EntryExit, ListPairsWithTimeframes, PairWithTimeframe) from freqtrade.data.converter import ohlcv_to_dataframe, trades_dict_to_list from freqtrade.enums import OPTIMIZE_MODES, CandleType, MarginMode, TradingMode from freqtrade.exceptions import (DDosProtection, ExchangeError, InsufficientFundsError, @@ -63,7 +64,9 @@ class Exchange: "time_in_force_parameter": "timeInForce", "ohlcv_params": {}, "ohlcv_candle_limit": 500, + "ohlcv_has_history": True, # Some exchanges (Kraken) don't provide history via ohlcv "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, @@ -95,6 +98,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 = {} @@ -166,7 +172,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 @@ -193,6 +199,7 @@ class Exchange: if self.trading_mode != TradingMode.SPOT: self.fill_leverage_tiers() + self.additional_exchange_init() def __del__(self): """ @@ -289,17 +296,28 @@ class Exchange: """exchange ccxt precisionMode""" return self._api.precisionMode + def additional_exchange_init(self) -> None: + """ + Additional exchange initialization logic. + .api will be available at this point. + Must be overridden in child methods if required. + """ + pass + def _log_exchange_response(self, endpoint, response) -> None: """ Log exchange responses """ if self.log_responses: logger.info(f"API {endpoint}: {response}") - def ohlcv_candle_limit(self, timeframe: str) -> int: + def ohlcv_candle_limit( + self, timeframe: str, candle_type: CandleType, since_ms: Optional[int] = None) -> int: """ Exchange ohlcv candle limit Uses ohlcv_candle_limit_per_timeframe if the exchange has different limits per timeframe (e.g. bittrex), otherwise falls back to ohlcv_candle_limit :param timeframe: Timeframe to check + :param candle_type: Candle-type + :param since_ms: Starting timestamp :return: Candle limit as integer """ return int(self._ft_has.get('ohlcv_candle_limit_per_timeframe', {}).get( @@ -341,15 +359,11 @@ class Exchange: return sorted(set([x['quote'] for _, x in markets.items()])) def get_pair_quote_currency(self, pair: str) -> str: - """ - Return a pair's quote currency - """ + """ Return a pair's quote currency (base/quote:settlement) """ return self.markets.get(pair, {}).get('quote', '') def get_pair_base_currency(self, pair: str) -> str: - """ - Return a pair's base currency - """ + """ Return a pair's base currency (base/quote:settlement) """ return self.markets.get(pair, {}).get('base', '') def market_is_future(self, market: Dict[str, Any]) -> bool: @@ -372,6 +386,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))) @@ -555,7 +572,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): @@ -602,19 +619,28 @@ class Exchange: Checks if required startup_candles is more than ohlcv_candle_limit(). Requires a grace-period of 5 candles - so a startup-period up to 494 is allowed by default. """ - candle_limit = self.ohlcv_candle_limit(timeframe) + + candle_limit = self.ohlcv_candle_limit( + timeframe, self._config['candle_type_def'], + int(date_minus_candles(timeframe, startup_candles).timestamp() * 1000) + if timeframe else None) # Require one more candle - to account for the still open candle. candle_count = startup_candles + 1 # Allow 5 calls to the exchange per pair required_candle_call_count = int( (candle_count / candle_limit) + (0 if candle_count % candle_limit == 0 else 1)) + if self._ft_has['ohlcv_has_history']: - if required_candle_call_count > 5: - # Only allow 5 calls per pair to somewhat limit the impact + if required_candle_call_count > 5: + # Only allow 5 calls per pair to somewhat limit the impact + raise OperationalException( + f"This strategy requires {startup_candles} candles to start, " + "which is more than 5x " + f"the amount of candles {self.name} provides for {timeframe}.") + elif required_candle_call_count > 1: raise OperationalException( - f"This strategy requires {startup_candles} candles to start, which is more than 5x " + f"This strategy requires {startup_candles} candles to start, which is more than " f"the amount of candles {self.name} provides for {timeframe}.") - if required_candle_call_count > 1: logger.warning(f"Using {required_candle_call_count} calls to get OHLCV. " f"This can result in slower operations for the bot. Please check " @@ -655,7 +681,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, @@ -785,7 +811,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, @@ -931,13 +959,14 @@ class Exchange: # Order handling - def _lev_prep(self, pair: str, leverage: float, side: str): + def _lev_prep(self, pair: str, leverage: float, side: BuySell): if self.trading_mode != TradingMode.SPOT: self.set_margin_mode(pair, self.margin_mode) self._set_leverage(leverage, pair) def _get_params( self, + side: BuySell, ordertype: str, leverage: float, reduceOnly: bool, @@ -956,7 +985,7 @@ class Exchange: *, pair: str, ordertype: str, - side: str, + side: BuySell, amount: float, rate: float, leverage: float, @@ -967,7 +996,7 @@ class Exchange: dry_order = self.create_dry_run_order(pair, ordertype, side, amount, rate, leverage) return dry_order - params = self._get_params(ordertype, leverage, reduceOnly, time_in_force) + params = self._get_params(side, ordertype, leverage, reduceOnly, time_in_force) try: # Set the precision for amount and price(rate) as accepted by the exchange @@ -1052,7 +1081,7 @@ class Exchange: @retrier(retries=0) def stoploss(self, pair: str, amount: float, stop_price: float, order_types: Dict, - side: str, leverage: float) -> Dict: + side: BuySell, leverage: float) -> Dict: """ creates a stoploss order. requires `_ft_has['stoploss_order_types']` to be set as a dict mapping limit and market @@ -1429,7 +1458,7 @@ class Exchange: raise OperationalException(e) from e def get_rate(self, pair: str, refresh: bool, - side: Literal['entry', 'exit'], is_short: bool) -> float: + side: EntryExit, is_short: bool) -> float: """ Calculates bid/ask target bid rate - between current ask price and last price @@ -1607,7 +1636,9 @@ class Exchange: order['fee']['cost'] / safe_value_fallback2(order, order, 'filled', 'amount'), 8) elif fee_curr in self.get_pair_quote_currency(order['symbol']): # Quote currency - divide by cost - return round(order['fee']['cost'] / order['cost'], 8) if order['cost'] else None + return round(self._contracts_to_amount( + order['symbol'], order['fee']['cost']) / order['cost'], + 8) if order['cost'] else None else: # If Fee currency is a different currency if not order['cost']: @@ -1622,7 +1653,8 @@ class Exchange: fee_to_quote_rate = self._config['exchange'].get('unknown_fee_rate', None) if not fee_to_quote_rate: return None - return round((order['fee']['cost'] * fee_to_quote_rate) / order['cost'], 8) + return round((self._contracts_to_amount( + order['symbol'], order['fee']['cost']) * fee_to_quote_rate) / order['cost'], 8) def extract_cost_curr_rate(self, order: Dict) -> Tuple[float, str, Optional[float]]: """ @@ -1639,7 +1671,8 @@ class Exchange: def get_historic_ohlcv(self, pair: str, timeframe: str, since_ms: int, candle_type: CandleType, - is_new_pair: bool = False) -> List: + is_new_pair: bool = False, + until_ms: int = None) -> List: """ Get candle history using asyncio and returns the list of candles. Handles all async work for this. @@ -1647,13 +1680,14 @@ class Exchange: :param pair: Pair to download :param timeframe: Timeframe to get data for :param since_ms: Timestamp in milliseconds to get history from + :param until_ms: Timestamp in milliseconds to get history up to :param candle_type: '', mark, index, premiumIndex, or funding_rate :return: List with candle (OHLCV) data """ pair, _, _, data = self.loop.run_until_complete( self._async_get_historic_ohlcv(pair=pair, timeframe=timeframe, - since_ms=since_ms, is_new_pair=is_new_pair, - candle_type=candle_type)) + since_ms=since_ms, until_ms=until_ms, + is_new_pair=is_new_pair, candle_type=candle_type)) logger.info(f"Downloaded data for {pair} with length {len(data)}.") return data @@ -1674,6 +1708,7 @@ class Exchange: async def _async_get_historic_ohlcv(self, pair: str, timeframe: str, since_ms: int, candle_type: CandleType, is_new_pair: bool = False, raise_: bool = False, + until_ms: int = None ) -> Tuple[str, str, str, List]: """ Download historic ohlcv @@ -1681,7 +1716,8 @@ class Exchange: :param candle_type: Any of the enum CandleType (must match trading mode!) """ - one_call = timeframe_to_msecs(timeframe) * self.ohlcv_candle_limit(timeframe) + one_call = timeframe_to_msecs(timeframe) * self.ohlcv_candle_limit( + timeframe, candle_type, since_ms) logger.debug( "one_call: %s msecs (%s)", one_call, @@ -1689,7 +1725,7 @@ class Exchange: ) input_coroutines = [self._async_get_candle_history( pair, timeframe, candle_type, since) for since in - range(since_ms, arrow.utcnow().int_timestamp * 1000, one_call)] + range(since_ms, until_ms or (arrow.utcnow().int_timestamp * 1000), one_call)] data: List = [] # Chunk requests into batches of 100 to avoid overwelming ccxt Throttling @@ -1714,9 +1750,11 @@ 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) + one_call = timeframe_to_msecs(timeframe) * self.ohlcv_candle_limit( + timeframe, candle_type, since_ms) move_to = one_call * self.required_candle_call_count now = timeframe_to_next_date(timeframe) since_ms = int((now - timedelta(seconds=move_to // 1000)).timestamp() * 1000) @@ -1774,7 +1812,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): @@ -1833,17 +1872,20 @@ class Exchange: pair, timeframe, since_ms, s ) params = deepcopy(self._ft_has.get('ohlcv_params', {})) + candle_limit = self.ohlcv_candle_limit( + timeframe, candle_type=candle_type, since_ms=since_ms) + 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. @@ -2030,9 +2072,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: @@ -2141,8 +2184,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, @@ -2181,7 +2224,7 @@ class Exchange: lev = tier['lev'] if tier_index < len(pair_tiers) - 1: - next_tier = pair_tiers[tier_index+1] + next_tier = pair_tiers[tier_index + 1] next_floor = next_tier['min'] / next_tier['lev'] if next_floor > stake_amount: # Next tier min too high for stake amount return min((tier['max'] / stake_amount), lev) @@ -2648,9 +2691,10 @@ def timeframe_to_msecs(timeframe: str) -> int: def timeframe_to_prev_date(timeframe: str, date: datetime = None) -> datetime: """ - Use Timeframe and determine last possible candle. + Use Timeframe and determine the candle start date for this date. + Does not round when given a candle start date. :param timeframe: timeframe in string format (e.g. "5m") - :param date: date to use. Defaults to utcnow() + :param date: date to use. Defaults to now(utc) :returns: date of previous candle (with utc timezone) """ if not date: @@ -2665,7 +2709,7 @@ def timeframe_to_next_date(timeframe: str, date: datetime = None) -> datetime: """ Use Timeframe and determine next candle. :param timeframe: timeframe in string format (e.g. "5m") - :param date: date to use. Defaults to utcnow() + :param date: date to use. Defaults to now(utc) :returns: date of next candle (with utc timezone) """ if not date: @@ -2675,6 +2719,23 @@ def timeframe_to_next_date(timeframe: str, date: datetime = None) -> datetime: return datetime.fromtimestamp(new_timestamp, tz=timezone.utc) +def date_minus_candles( + timeframe: str, candle_count: int, date: Optional[datetime] = None) -> datetime: + """ + subtract X candles from a date. + :param timeframe: timeframe in string format (e.g. "5m") + :param candle_count: Amount of candles to subtract. + :param date: date to use. Defaults to now(utc) + + """ + if not date: + date = datetime.now(timezone.utc) + + tf_min = timeframe_to_minutes(timeframe) + new_date = timeframe_to_prev_date(timeframe, date) - timedelta(minutes=tf_min * candle_count) + return new_date + + def market_is_active(market: Dict) -> bool: """ Return True if the market is active. diff --git a/freqtrade/exchange/ftx.py b/freqtrade/exchange/ftx.py index f20aab138..65c2a53ca 100644 --- a/freqtrade/exchange/ftx.py +++ b/freqtrade/exchange/ftx.py @@ -4,6 +4,7 @@ from typing import Any, Dict, List, Tuple import ccxt +from freqtrade.constants import BuySell from freqtrade.enums import MarginMode, TradingMode from freqtrade.exceptions import (DDosProtection, InsufficientFundsError, InvalidOrderException, OperationalException, TemporaryError) @@ -20,6 +21,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", @@ -43,7 +45,7 @@ class Ftx(Exchange): @retrier(retries=0) def stoploss(self, pair: str, amount: float, stop_price: float, - order_types: Dict, side: str, leverage: float) -> Dict: + order_types: Dict, side: BuySell, leverage: float) -> Dict: """ Creates a stoploss order. depending on order_types.stoploss configuration, uses 'market' or limit order. diff --git a/freqtrade/exchange/kraken.py b/freqtrade/exchange/kraken.py index 94727afa6..900f6c898 100644 --- a/freqtrade/exchange/kraken.py +++ b/freqtrade/exchange/kraken.py @@ -6,6 +6,7 @@ from typing import Any, Dict, List, Optional, Tuple import ccxt from pandas import DataFrame +from freqtrade.constants import BuySell from freqtrade.enums import MarginMode, TradingMode from freqtrade.exceptions import (DDosProtection, InsufficientFundsError, InvalidOrderException, OperationalException, TemporaryError) @@ -22,6 +23,7 @@ class Kraken(Exchange): _ft_has: Dict = { "stoploss_on_exchange": True, "ohlcv_candle_limit": 720, + "ohlcv_has_history": False, "trades_pagination": "id", "trades_pagination_arg": "since", "mark_ohlcv_timeframe": "4h", @@ -95,7 +97,7 @@ class Kraken(Exchange): @retrier(retries=0) def stoploss(self, pair: str, amount: float, stop_price: float, - order_types: Dict, side: str, leverage: float) -> Dict: + order_types: Dict, side: BuySell, leverage: float) -> Dict: """ Creates a stoploss market order. Stoploss market orders is the only stoploss type supported by kraken. @@ -165,12 +167,14 @@ class Kraken(Exchange): def _get_params( self, + side: BuySell, ordertype: str, leverage: float, reduceOnly: bool, time_in_force: str = 'gtc' ) -> Dict: params = super()._get_params( + side=side, ordertype=ordertype, leverage=leverage, reduceOnly=reduceOnly, diff --git a/freqtrade/exchange/okx.py b/freqtrade/exchange/okx.py index fb7388ee1..012f51080 100644 --- a/freqtrade/exchange/okx.py +++ b/freqtrade/exchange/okx.py @@ -1,12 +1,15 @@ import logging -from typing import Dict, List, Tuple +from typing import Dict, List, Optional, Tuple import ccxt +from freqtrade.constants import BuySell from freqtrade.enums import MarginMode, TradingMode +from freqtrade.enums.candletype import CandleType from freqtrade.exceptions import DDosProtection, OperationalException, TemporaryError from freqtrade.exchange import Exchange from freqtrade.exchange.common import retrier +from freqtrade.exchange.exchange import date_minus_candles logger = logging.getLogger(__name__) @@ -19,7 +22,7 @@ class Okx(Exchange): """ _ft_has: Dict = { - "ohlcv_candle_limit": 300, + "ohlcv_candle_limit": 100, # Warning, special case with data prior to X months "mark_ohlcv_timeframe": "4h", "funding_fee_timeframe": "8h", } @@ -34,14 +37,69 @@ class Okx(Exchange): (TradingMode.FUTURES, MarginMode.ISOLATED), ] + net_only = True + + def ohlcv_candle_limit( + self, timeframe: str, candle_type: CandleType, since_ms: Optional[int] = None) -> int: + """ + Exchange ohlcv candle limit + OKX has the following behaviour: + * 300 candles for uptodate data + * 100 candles for historic data + * 100 candles for additional candles (not futures or spot). + :param timeframe: Timeframe to check + :param candle_type: Candle-type + :param since_ms: Starting timestamp + :return: Candle limit as integer + """ + if ( + candle_type in (CandleType.FUTURES, CandleType.SPOT) and + (not since_ms or since_ms > (date_minus_candles(timeframe, 300).timestamp() * 1000)) + ): + return 300 + + return super().ohlcv_candle_limit(timeframe, candle_type, since_ms) + + @retrier + def additional_exchange_init(self) -> None: + """ + Additional exchange initialization logic. + .api will be available at this point. + Must be overridden in child methods if required. + """ + try: + if self.trading_mode == TradingMode.FUTURES and not self._config['dry_run']: + accounts = self._api.fetch_accounts() + if len(accounts) > 0: + self.net_only = accounts[0].get('info', {}).get('posMode') == 'net_mode' + except ccxt.DDoSProtection as e: + raise DDosProtection(e) from e + except (ccxt.NetworkError, ccxt.ExchangeError) as e: + raise TemporaryError( + f'Could not set leverage due to {e.__class__.__name__}. Message: {e}') from e + except ccxt.BaseError as e: + raise OperationalException(e) from e + + def _get_posSide(self, side: BuySell, reduceOnly: bool): + if self.net_only: + return 'net' + if not reduceOnly: + # Enter + return 'long' if side == 'buy' else 'short' + else: + # Exit + return 'long' if side == 'sell' else 'short' + def _get_params( self, + side: BuySell, ordertype: str, leverage: float, reduceOnly: bool, time_in_force: str = 'gtc', ) -> Dict: params = super()._get_params( + side=side, ordertype=ordertype, leverage=leverage, reduceOnly=reduceOnly, @@ -49,10 +107,11 @@ class Okx(Exchange): ) if self.trading_mode == TradingMode.FUTURES and self.margin_mode: params['tdMode'] = self.margin_mode.value + params['posSide'] = self._get_posSide(side, reduceOnly) return params @retrier - def _lev_prep(self, pair: str, leverage: float, side: str): + def _lev_prep(self, pair: str, leverage: float, side: BuySell): if self.trading_mode != TradingMode.SPOT and self.margin_mode is not None: try: # TODO-lev: Test me properly (check mgnMode passed) @@ -61,7 +120,7 @@ class Okx(Exchange): symbol=pair, params={ "mgnMode": self.margin_mode.value, - # "posSide": "net"", + "posSide": self._get_posSide(side, False), }) except ccxt.DDoSProtection as e: raise DDosProtection(e) from e diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 9a07020ad..315db3ae6 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -7,12 +7,13 @@ import traceback from datetime import datetime, time, timezone from math import isclose from threading import Lock -from typing import Any, Dict, List, Literal, Optional, Tuple +from typing import Any, Dict, List, Optional, Tuple from schedule import Scheduler from freqtrade import __version__, constants from freqtrade.configuration import validate_config_consistency +from freqtrade.constants import BuySell, LongShort from freqtrade.data.converter import order_book_to_dataframe from freqtrade.data.dataprovider import DataProvider from freqtrade.edge import Edge @@ -21,6 +22,7 @@ from freqtrade.enums import (ExitCheckTuple, ExitType, RPCMessageType, RunMode, from freqtrade.exceptions import (DependencyException, ExchangeError, InsufficientFundsError, InvalidOrderException, PricingError) from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds +from freqtrade.exchange.exchange import timeframe_to_next_date from freqtrade.misc import safe_value_fallback, safe_value_fallback2 from freqtrade.mixins import LoggingMixin from freqtrade.persistence import Order, PairLocks, Trade, cleanup_db, init_db @@ -121,6 +123,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 @@ -187,10 +191,10 @@ class FreqtradeBot(LoggingMixin): self.strategy.analyze(self.active_pair_whitelist) with self._exit_lock: - # Check and handle any timed out open orders - self.check_handle_timedout() + # Check for exchange cancelations, timeouts and user requested replace + self.manage_open_orders() - # Protect from collisions with forceexit. + # Protect from collisions with force_exit. # Without this, freqtrade my try to recreate stoploss_on_exchange orders # while exiting is in process, since telegram messages arrive in an different thread. with self._exit_lock: @@ -329,12 +333,12 @@ class FreqtradeBot(LoggingMixin): trades: List[Trade] = Trade.get_open_trades_without_assigned_fees() for trade in trades: - if trade.is_open and not trade.fee_updated(trade.enter_side): - order = trade.select_order(trade.enter_side, False) - open_order = trade.select_order(trade.enter_side, True) + if trade.is_open and not trade.fee_updated(trade.entry_side): + order = trade.select_order(trade.entry_side, False) + open_order = trade.select_order(trade.entry_side, True) if order and open_order is None: logger.info( - f"Updating {trade.enter_side}-fee on trade {trade}" + f"Updating {trade.entry_side}-fee on trade {trade}" f"for order {order.order_id}." ) self.update_trade_state(trade, order.order_id, send_msg=False) @@ -363,7 +367,7 @@ class FreqtradeBot(LoggingMixin): if fo and fo['status'] == 'open': # Assume this as the open order trade.open_order_id = order.order_id - elif order.ft_order_side == trade.enter_side: + elif order.ft_order_side == trade.entry_side: if fo and fo['status'] == 'open': trade.open_order_id = order.order_id if fo: @@ -398,7 +402,10 @@ class FreqtradeBot(LoggingMixin): logger.info("No currency pair in active pair whitelist, " "but checking to exit open trades.") return trades_created - if PairLocks.is_global_lock(): + if PairLocks.is_global_lock(side='*'): + # This only checks for total locks (both sides). + # per-side locks will be evaluated by `is_pair_locked` within create_trade, + # once the direction for the trade is clear. lock = PairLocks.get_pair_longest_lock('*') if lock: self.log_once(f"Global pairlock active until " @@ -432,16 +439,6 @@ class FreqtradeBot(LoggingMixin): analyzed_df, _ = self.dataprovider.get_analyzed_dataframe(pair, self.strategy.timeframe) nowtime = analyzed_df.iloc[-1]['date'] if len(analyzed_df) > 0 else None - if self.strategy.is_pair_locked(pair, nowtime): - lock = PairLocks.get_pair_longest_lock(pair, nowtime) - if lock: - self.log_once(f"Pair {pair} is still locked until " - f"{lock.lock_end_time.strftime(constants.DATETIME_PRINT_FORMAT)} " - f"due to {lock.reason}.", - logger.info) - else: - self.log_once(f"Pair {pair} is still locked.", logger.info) - return False # get_free_open_trades is checked before create_trade is called # but it is still used here to prevent opening too many trades within one iteration @@ -457,6 +454,16 @@ class FreqtradeBot(LoggingMixin): ) if signal: + if self.strategy.is_pair_locked(pair, candle_date=nowtime, side=signal): + lock = PairLocks.get_pair_longest_lock(pair, nowtime, signal) + if lock: + self.log_once(f"Pair {pair} {lock.side} is locked until " + f"{lock.lock_end_time.strftime(constants.DATETIME_PRINT_FORMAT)} " + f"due to {lock.reason}.", + logger.info) + else: + self.log_once(f"Pair {pair} is currently locked.", logger.info) + return False stake_amount = self.wallets.get_trade_stake_amount(pair, self.edge) bid_check_dom = self.config.get('entry_pricing', {}).get('check_depth_of_market', {}) @@ -529,7 +536,8 @@ class FreqtradeBot(LoggingMixin): if stake_amount is not None and stake_amount > 0.0: # We should increase our position - self.execute_entry(trade.pair, stake_amount, trade=trade, is_short=trade.is_short) + self.execute_entry(trade.pair, stake_amount, price=current_rate, + trade=trade, is_short=trade.is_short) if stake_amount is not None and stake_amount < 0.0: # We should decrease our position @@ -548,9 +556,9 @@ class FreqtradeBot(LoggingMixin): order_book_bids = order_book_data_frame['b_size'].sum() order_book_asks = order_book_data_frame['a_size'].sum() - enter_side = order_book_bids if side == SignalDirection.LONG else order_book_asks + entry_side = order_book_bids if side == SignalDirection.LONG else order_book_asks exit_side = order_book_asks if side == SignalDirection.LONG else order_book_bids - bids_ask_delta = enter_side / exit_side + bids_ask_delta = entry_side / exit_side bids = f"Bids: {order_book_bids}" asks = f"Asks: {order_book_asks}" @@ -579,22 +587,23 @@ class FreqtradeBot(LoggingMixin): ordertype: Optional[str] = None, enter_tag: Optional[str] = None, trade: Optional[Trade] = None, + order_adjust: bool = False ) -> bool: """ 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'] - [side, name] = ['sell', 'Short'] if is_short else ['buy', 'Long'] - trade_side: Literal['long', 'short'] = 'short' if is_short else 'long' + side: BuySell = 'sell' if is_short else 'buy' + name = 'Short' if is_short else 'Long' + trade_side: LongShort = 'short' if is_short else 'long' pos_adjust = trade is not None enter_limit_requested, stake_amount, leverage = self.get_valid_enter_price_and_stake( - pair, price, stake_amount, trade_side, enter_tag, trade) + pair, price, stake_amount, trade_side, enter_tag, trade, order_adjust) if not stake_amount: return False @@ -662,18 +671,9 @@ 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) open_date = datetime.now(timezone.utc) funding_fees = self.exchange.get_funding_fees( pair=pair, amount=amount, is_short=is_short, open_date=open_date) @@ -681,6 +681,8 @@ class FreqtradeBot(LoggingMixin): if trade is None: trade = Trade( pair=pair, + base_currency=base_currency, + stake_currency=self.config['stake_currency'], stake_amount=stake_amount, amount=amount, is_open=True, @@ -697,8 +699,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 ) @@ -746,23 +746,28 @@ class FreqtradeBot(LoggingMixin): def get_valid_enter_price_and_stake( self, pair: str, price: Optional[float], stake_amount: float, - trade_side: Literal['long', 'short'], + trade_side: LongShort, entry_tag: Optional[str], - trade: Optional[Trade] + trade: Optional[Trade], + order_adjust: bool, ) -> Tuple[float, float, float]: if price: enter_limit_requested = price else: # Calculate price - proposed_enter_rate = self.exchange.get_rate( + enter_limit_requested = self.exchange.get_rate( pair, side='entry', is_short=(trade_side == 'short'), refresh=True) + if not order_adjust: + # Don't call custom_entry_price in order-adjust scenario custom_entry_price = strategy_safe_wrapper(self.strategy.custom_entry_price, - default_retval=proposed_enter_rate)( + default_retval=enter_limit_requested)( pair=pair, current_time=datetime.now(timezone.utc), - proposed_rate=proposed_enter_rate, entry_tag=entry_tag) + proposed_rate=enter_limit_requested, entry_tag=entry_tag, + side=trade_side, + ) - enter_limit_requested = self.get_valid_price(custom_entry_price, proposed_enter_rate) + enter_limit_requested = self.get_valid_price(custom_entry_price, enter_limit_requested) if not enter_limit_requested: raise PricingError('Could not determine entry price.') @@ -816,10 +821,7 @@ class FreqtradeBot(LoggingMixin): """ Sends rpc notification when a entry order occurred. """ - if fill: - msg_type = RPCMessageType.SHORT_FILL if trade.is_short else RPCMessageType.BUY_FILL - else: - msg_type = RPCMessageType.SHORT if trade.is_short else RPCMessageType.BUY + msg_type = RPCMessageType.ENTRY_FILL if fill else RPCMessageType.ENTRY open_rate = safe_value_fallback(order, 'average', 'price') if open_rate is None: open_rate = trade.open_rate @@ -834,7 +836,7 @@ class FreqtradeBot(LoggingMixin): 'type': msg_type, 'buy_tag': trade.enter_tag, 'enter_tag': trade.enter_tag, - 'exchange': self.exchange.name.capitalize(), + 'exchange': trade.exchange.capitalize(), 'pair': trade.pair, 'leverage': trade.leverage if trade.leverage else None, 'direction': 'Short' if trade.is_short else 'Long', @@ -858,13 +860,13 @@ class FreqtradeBot(LoggingMixin): """ current_rate = self.exchange.get_rate( trade.pair, side='entry', is_short=trade.is_short, refresh=False) - msg_type = RPCMessageType.SHORT_CANCEL if trade.is_short else RPCMessageType.BUY_CANCEL + msg = { 'trade_id': trade.id, - 'type': msg_type, + 'type': RPCMessageType.ENTRY_CANCEL, 'buy_tag': trade.enter_tag, 'enter_tag': trade.enter_tag, - 'exchange': self.exchange.name.capitalize(), + 'exchange': trade.exchange.capitalize(), 'pair': trade.pair, 'leverage': trade.leverage, 'direction': 'Short' if trade.is_short else 'Long', @@ -926,8 +928,8 @@ class FreqtradeBot(LoggingMixin): exit_tag = None exit_signal_type = "exit_short" if trade.is_short else "exit_long" - if (self.config.get('use_sell_signal', True) or - self.config.get('ignore_roi_if_buy_signal', False)): + if (self.config.get('use_exit_signal', True) or + self.config.get('ignore_roi_if_entry_signal', False)): analyzed_df, _ = self.dataprovider.get_analyzed_dataframe(trade.pair, self.strategy.timeframe) @@ -978,7 +980,7 @@ class FreqtradeBot(LoggingMixin): logger.error(f'Unable to place a stoploss order on exchange. {e}') logger.warning('Exiting the trade forcefully') self.execute_trade_exit(trade, trade.stop_loss, exit_check=ExitCheckTuple( - exit_type=ExitType.EMERGENCY_SELL)) + exit_type=ExitType.EMERGENCY_EXIT)) except ExchangeError: trade.stoploss_order_id = None @@ -1010,7 +1012,7 @@ class FreqtradeBot(LoggingMixin): # We check if stoploss order is fulfilled if stoploss_order and stoploss_order['status'] in ('closed', 'triggered'): - trade.sell_reason = ExitType.STOPLOSS_ON_EXCHANGE.value + trade.exit_reason = ExitType.STOPLOSS_ON_EXCHANGE.value self.update_trade_state(trade, trade.stoploss_order_id, stoploss_order, stoploss_order=True) # Lock pair for one candle to prevent immediate rebuys @@ -1119,13 +1121,13 @@ class FreqtradeBot(LoggingMixin): return True return False - def check_handle_timedout(self) -> None: + def manage_open_orders(self) -> None: """ - Check if any orders are timed out and cancel if necessary - :param timeoutvalue: Number of minutes until order is considered timed out + Management of open orders on exchange. Unfilled orders might be cancelled if timeout + was met or replaced if there's a new candle and user has requested it. + Timeout setting takes priority over limit order adjustment request. :return: None """ - for trade in Trade.get_open_order_trades(): try: if not trade.open_order_id: @@ -1136,33 +1138,88 @@ class FreqtradeBot(LoggingMixin): continue fully_cancelled = self.update_trade_state(trade, trade.open_order_id, order) - is_entering = order['side'] == trade.enter_side not_closed = order['status'] == 'open' or fully_cancelled - max_timeouts = self.config.get('unfilledtimeout', {}).get('exit_timeout_count', 0) - order_obj = trade.select_order_by_order_id(trade.open_order_id) - if not_closed and (fully_cancelled or (order_obj and self.strategy.ft_check_timed_out( - trade, order_obj, datetime.now(timezone.utc))) - ): - if is_entering: - self.handle_cancel_enter(trade, order, constants.CANCEL_REASON['TIMEOUT']) + if not_closed: + if fully_cancelled or (order_obj and self.strategy.ft_check_timed_out( + trade, order_obj, datetime.now(timezone.utc))): + self.handle_timedout_order(order, trade) else: - canceled = self.handle_cancel_exit( - trade, order, constants.CANCEL_REASON['TIMEOUT']) - canceled_count = trade.get_exit_order_count() - max_timeouts = self.config.get( - 'unfilledtimeout', {}).get('exit_timeout_count', 0) - if canceled and max_timeouts > 0 and canceled_count >= max_timeouts: - logger.warning(f'Emergency exiting trade {trade}, as the exit order ' - f'timed out {max_timeouts} times.') - try: - self.execute_trade_exit( - trade, order.get('price'), - exit_check=ExitCheckTuple(exit_type=ExitType.EMERGENCY_SELL)) - except DependencyException as exception: - logger.warning( - f'Unable to emergency sell trade {trade.pair}: {exception}') + self.replace_order(order, order_obj, trade) + + def handle_timedout_order(self, order: Dict, trade: Trade) -> None: + """ + Check if current analyzed order timed out and cancel if necessary. + :param order: Order dict grabbed with exchange.fetch_order() + :param trade: Trade object. + :return: None + """ + if order['side'] == trade.entry_side: + self.handle_cancel_enter(trade, order, constants.CANCEL_REASON['TIMEOUT']) + else: + canceled = self.handle_cancel_exit( + trade, order, constants.CANCEL_REASON['TIMEOUT']) + canceled_count = trade.get_exit_order_count() + max_timeouts = self.config.get('unfilledtimeout', {}).get('exit_timeout_count', 0) + if canceled and max_timeouts > 0 and canceled_count >= max_timeouts: + logger.warning(f'Emergency exiting trade {trade}, as the exit order ' + f'timed out {max_timeouts} times.') + try: + self.execute_trade_exit( + trade, order['price'], + exit_check=ExitCheckTuple(exit_type=ExitType.EMERGENCY_EXIT)) + except DependencyException as exception: + logger.warning( + f'Unable to emergency sell trade {trade.pair}: {exception}') + + def replace_order(self, order: Dict, order_obj: Optional[Order], trade: Trade) -> None: + """ + Check if current analyzed entry order should be replaced or simply cancelled. + To simply cancel the existing order(no replacement) adjust_entry_price() should return None + To maintain existing order adjust_entry_price() should return order_obj.price + To replace existing order adjust_entry_price() should return desired price for limit order + :param order: Order dict grabbed with exchange.fetch_order() + :param order_obj: Order object. + :param trade: Trade object. + :return: None + """ + analyzed_df, _ = self.dataprovider.get_analyzed_dataframe(trade.pair, + self.strategy.timeframe) + latest_candle_open_date = analyzed_df.iloc[-1]['date'] if len(analyzed_df) > 0 else None + latest_candle_close_date = timeframe_to_next_date(self.strategy.timeframe, + latest_candle_open_date) + # Check if new candle + if order_obj and latest_candle_close_date > order_obj.order_date_utc: + # New candle + proposed_rate = self.exchange.get_rate( + trade.pair, side='entry', is_short=trade.is_short, refresh=True) + adjusted_entry_price = strategy_safe_wrapper(self.strategy.adjust_entry_price, + default_retval=order_obj.price)( + trade=trade, order=order_obj, pair=trade.pair, + current_time=datetime.now(timezone.utc), proposed_rate=proposed_rate, + current_order_rate=order_obj.price, entry_tag=trade.enter_tag, + side=trade.entry_side) + + full_cancel = False + cancel_reason = constants.CANCEL_REASON['REPLACE'] + if not adjusted_entry_price: + full_cancel = True if trade.nr_of_successful_entries == 0 else False + cancel_reason = constants.CANCEL_REASON['USER_CANCEL'] + if order_obj.price != adjusted_entry_price: + # cancel existing order if new price is supplied or None + self.handle_cancel_enter(trade, order, cancel_reason, + allow_full_cancel=full_cancel) + if adjusted_entry_price: + # place new order only if new price is supplied + self.execute_entry( + pair=trade.pair, + stake_amount=(order_obj.remaining * order_obj.price), + price=adjusted_entry_price, + trade=trade, + is_short=trade.is_short, + order_adjust=True, + ) def cancel_all_open_orders(self) -> None: """ @@ -1177,14 +1234,17 @@ class FreqtradeBot(LoggingMixin): logger.info('Cannot query order for %s due to %s', trade, traceback.format_exc()) continue - if order['side'] == trade.enter_side: + if order['side'] == trade.entry_side: self.handle_cancel_enter(trade, order, constants.CANCEL_REASON['ALL_CANCELLED']) elif order['side'] == trade.exit_side: self.handle_cancel_exit(trade, order, constants.CANCEL_REASON['ALL_CANCELLED']) Trade.commit() - def handle_cancel_enter(self, trade: Trade, order: Dict, reason: str) -> bool: + def handle_cancel_enter( + self, trade: Trade, order: Dict, reason: str, + allow_full_cancel: Optional[bool] = True + ) -> bool: """ Buy cancel - cancel order :return: True if order was fully cancelled @@ -1216,15 +1276,16 @@ class FreqtradeBot(LoggingMixin): corder = order reason = constants.CANCEL_REASON['CANCELLED_ON_EXCHANGE'] - side = trade.enter_side.capitalize() + side = trade.entry_side.capitalize() logger.info('%s order %s for %s.', side, reason, trade) # Using filled to determine the filled amount filled_amount = safe_value_fallback2(corder, order, 'filled', 'filled') if isclose(filled_amount, 0.0, abs_tol=constants.MATH_CLOSE_PREC): - logger.info(f'{side} order fully cancelled. Removing {trade} from database.') # if trade is not partially completed and it's the only order, just delete the trade - if len(trade.orders) <= 1: + open_order_count = len([order for order in trade.orders if order.status == 'open']) + if open_order_count <= 1 and allow_full_cancel: + logger.info(f'{side} order fully cancelled. Removing {trade} from database.') trade.delete() was_trade_fully_canceled = True reason += f", {constants.CANCEL_REASON['FULLY_CANCELLED']}" @@ -1247,7 +1308,7 @@ class FreqtradeBot(LoggingMixin): self.update_trade_state(trade, trade.open_order_id, corder) trade.open_order_id = None - logger.info(f'Partial {trade.enter_side} order timeout for {trade}.') + logger.info(f'Partial {trade.entry_side} order timeout for {trade}.') reason += f", {constants.CANCEL_REASON['PARTIALLY_FILLED']}" self.wallets.update() @@ -1286,7 +1347,7 @@ class FreqtradeBot(LoggingMixin): trade.close_date = None trade.is_open = True trade.open_order_id = None - trade.sell_reason = None + trade.exit_reason = None cancelled = True else: # TODO: figure out how to handle partially complete sell orders @@ -1353,6 +1414,7 @@ class FreqtradeBot(LoggingMixin): open_date=trade.open_date_utc, ) exit_type = 'exit' + exit_reason = exit_tag or exit_check.exit_reason if exit_check.exit_type in (ExitType.STOP_LOSS, ExitType.TRAILING_STOP_LOSS): exit_type = 'stoploss' @@ -1369,7 +1431,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_reason) limit = self.get_valid_price(custom_exit_price, proposed_limit_rate) @@ -1377,17 +1440,17 @@ class FreqtradeBot(LoggingMixin): trade = self.cancel_stoploss_on_exchange(trade) order_type = ordertype or self.strategy.order_types[exit_type] - if exit_check.exit_type == ExitType.EMERGENCY_SELL: + if exit_check.exit_type == ExitType.EMERGENCY_EXIT: # Emergency sells (default to market!) - order_type = self.strategy.order_types.get("emergencyexit", "market") + order_type = self.strategy.order_types.get("emergency_exit", "market") amount = self._safe_exit_amount(trade.pair, trade.amount) time_in_force = self.strategy.order_time_in_force['exit'] if not strategy_safe_wrapper(self.strategy.confirm_trade_exit, default_retval=True)( pair=trade.pair, trade=trade, order_type=order_type, amount=amount, rate=limit, - time_in_force=time_in_force, exit_reason=exit_check.exit_reason, - sell_reason=exit_check.exit_reason, # sellreason -> compatibility + time_in_force=time_in_force, exit_reason=exit_reason, + sell_reason=exit_reason, # sellreason -> compatibility current_time=datetime.now(timezone.utc)): logger.info(f"User requested abortion of exiting {trade.pair}") return False @@ -1414,9 +1477,9 @@ class FreqtradeBot(LoggingMixin): trade.orders.append(order_obj) trade.open_order_id = order['id'] - trade.sell_order_status = '' + trade.exit_order_status = '' trade.close_rate_requested = limit - trade.sell_reason = exit_tag or exit_check.exit_reason + trade.exit_reason = exit_reason # Lock pair for one candle to prevent immediate re-trading self.strategy.lock_pair(trade.pair, datetime.now(timezone.utc), @@ -1443,8 +1506,8 @@ class FreqtradeBot(LoggingMixin): gain = "profit" if profit_ratio > 0 else "loss" msg = { - 'type': (RPCMessageType.SELL_FILL if fill - else RPCMessageType.SELL), + 'type': (RPCMessageType.EXIT_FILL if fill + else RPCMessageType.EXIT), 'trade_id': trade.id, 'exchange': trade.exchange.capitalize(), 'pair': trade.pair, @@ -1461,7 +1524,8 @@ class FreqtradeBot(LoggingMixin): 'profit_ratio': profit_ratio, 'buy_tag': trade.enter_tag, 'enter_tag': trade.enter_tag, - 'sell_reason': trade.sell_reason, + 'sell_reason': trade.exit_reason, # Deprecated + 'exit_reason': trade.exit_reason, 'open_date': trade.open_date, 'close_date': trade.close_date or datetime.utcnow(), 'stake_currency': self.config['stake_currency'], @@ -1480,10 +1544,10 @@ class FreqtradeBot(LoggingMixin): """ Sends rpc notification when a sell cancel occurred. """ - if trade.sell_order_status == reason: + if trade.exit_order_status == reason: return else: - trade.sell_order_status = reason + trade.exit_order_status = reason profit_rate = trade.close_rate if trade.close_rate else trade.close_rate_requested profit_trade = trade.calc_profit(rate=profit_rate) @@ -1493,7 +1557,7 @@ class FreqtradeBot(LoggingMixin): gain = "profit" if profit_ratio > 0 else "loss" msg = { - 'type': RPCMessageType.SELL_CANCEL, + 'type': RPCMessageType.EXIT_CANCEL, 'trade_id': trade.id, 'exchange': trade.exchange.capitalize(), 'pair': trade.pair, @@ -1509,7 +1573,8 @@ class FreqtradeBot(LoggingMixin): 'profit_ratio': profit_ratio, 'buy_tag': trade.enter_tag, 'enter_tag': trade.enter_tag, - 'sell_reason': trade.sell_reason, + 'sell_reason': trade.exit_reason, # Deprecated + 'exit_reason': trade.exit_reason, 'open_date': trade.open_date, 'close_date': trade.close_date or datetime.now(timezone.utc), 'stake_currency': self.config['stake_currency'], @@ -1575,12 +1640,11 @@ class FreqtradeBot(LoggingMixin): if order['status'] in constants.NON_OPEN_EXCHANGE_STATES: # If a entry order was closed, force update on stoploss on exchange - if order.get('side', None) == trade.enter_side: + if order.get('side', None) == trade.entry_side: trade = self.cancel_stoploss_on_exchange(trade) # TODO: Margin will need to use interest_rate as well. # interest_rate = self.exchange.get_interest_rate() trade.set_isolated_liq(self.exchange.get_liquidation_price( - leverage=trade.leverage, pair=trade.pair, amount=trade.amount, @@ -1598,21 +1662,21 @@ class FreqtradeBot(LoggingMixin): if not trade.is_open: if send_msg and not stoploss_order and not trade.open_order_id: self._notify_exit(trade, '', True) - self.handle_protections(trade.pair) + self.handle_protections(trade.pair, trade.trade_direction) elif send_msg and not trade.open_order_id: # Enter fill self._notify_enter(trade, order, fill=True) return False - def handle_protections(self, pair: str) -> None: - prot_trig = self.protections.stop_per_pair(pair) + def handle_protections(self, pair: str, side: LongShort) -> None: + prot_trig = self.protections.stop_per_pair(pair, side=side) if prot_trig: msg = {'type': RPCMessageType.PROTECTION_TRIGGER, } msg.update(prot_trig.to_json()) self.rpc.send_msg(msg) - prot_trig_glb = self.protections.global_stop() + prot_trig_glb = self.protections.global_stop(side=side) if prot_trig_glb: msg = {'type': RPCMessageType.PROTECTION_TRIGGER_GLOBAL, } msg.update(prot_trig_glb.to_json()) diff --git a/freqtrade/leverage/interest.py b/freqtrade/leverage/interest.py index ff375b05e..367df5821 100644 --- a/freqtrade/leverage/interest.py +++ b/freqtrade/leverage/interest.py @@ -31,13 +31,13 @@ def interest( """ exchange_name = exchange_name.lower() if exchange_name == "binance": - return borrowed * rate * ceil(hours)/twenty_four + return borrowed * rate * ceil(hours) / twenty_four elif exchange_name == "kraken": # Rounded based on https://kraken-fees-calculator.github.io/ - return borrowed * rate * (one+ceil(hours/four)) + return borrowed * rate * (one + ceil(hours / four)) elif exchange_name == "ftx": # As Explained under #Interest rates section in # https://help.ftx.com/hc/en-us/articles/360053007671-Spot-Margin-Trading-Explainer - return borrowed * rate * ceil(hours)/twenty_four + return borrowed * rate * ceil(hours) / twenty_four else: raise OperationalException(f"Leverage not available on {exchange_name} with freqtrade") diff --git a/freqtrade/misc.py b/freqtrade/misc.py index acc7fc2e4..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 @@ -86,6 +84,22 @@ def file_dump_json(filename: Path, data: Any, is_zip: bool = False, log: bool = logger.debug(f'done json to "{filename}"') +def file_dump_joblib(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: + """ + import joblib + + if log: + logger.info(f'dumping joblib to "{filename}"') + with open(filename, 'wb') as fp: + joblib.dump(data, fp) + logger.debug(f'done joblib dump to "{filename}"') + + def json_load(datafile: IO) -> Any: """ load data with rapidjson @@ -126,7 +140,7 @@ def format_ms_time(date: int) -> str: convert MS date to readable format. : epoch-string in ms """ - return datetime.fromtimestamp(date/1000.0).strftime('%Y-%m-%dT%H:%M:%S') + return datetime.fromtimestamp(date / 1000.0).strftime('%Y-%m-%dT%H:%M:%S') def deep_merge_dicts(source, destination, allow_null_overrides: bool = True): @@ -235,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..d9d270072 --- /dev/null +++ b/freqtrade/optimize/backtest_caching.py @@ -0,0 +1,40 @@ +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')) + # 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() + + +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 old mode 100644 new mode 100755 index b63c404fc..64107ae18 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -9,23 +9,26 @@ from copy import deepcopy from datetime import datetime, timedelta, timezone from typing import Any, Dict, List, Optional, Tuple +import pandas as pd from numpy import nan from pandas import DataFrame from freqtrade import constants from freqtrade.configuration import TimeRange, validate_config_consistency -from freqtrade.constants import DATETIME_PRINT_FORMAT +from freqtrade.constants import DATETIME_PRINT_FORMAT, LongShort 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, 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.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, store_backtest_stats) from freqtrade.persistence import LocalTrade, Order, PairLocks, Trade from freqtrade.plugins.pairlistmanager import PairListManager @@ -51,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: """ @@ -73,6 +81,8 @@ class Backtesting: self.run_ids: Dict[str, str] = {} 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) @@ -174,9 +184,10 @@ 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 + self.strategy.bot_start() def _load_protections(self, strategy: IStrategy): if self.config.get('enable_protections', False): @@ -259,10 +270,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 = {} @@ -300,10 +319,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)) @@ -315,7 +331,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}), @@ -328,59 +344,59 @@ 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:]: + 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( [nan], [0 if not tag_col else None]).shift(1) - else: + elif not df_analyzed.empty: df_analyzed.loc[:, col] = 0 if not tag_col else None df_analyzed = df_analyzed.drop(df_analyzed.head(1).index) # Convert from Pandas to list for performance reasons # (Looping Pandas is slow.) - data[pair] = df_analyzed[headers].values.tolist() + data[pair] = df_analyzed[HEADERS].values.tolist() if not df_analyzed.empty else [] return data - def _get_close_rate(self, sell_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(sell_row, trade, sell, trade_dur) - elif sell.exit_type == (ExitType.ROI): - return self._get_close_rate_for_roi(sell_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 sell_row[OPEN_IDX] + return row[OPEN_IDX] - def _get_close_rate_for_stoploss(self, sell_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 if is_short: - if trade.stop_loss < sell_row[LOW_IDX]: - return sell_row[OPEN_IDX] + if trade.stop_loss < row[LOW_IDX]: + return row[OPEN_IDX] else: - if trade.stop_loss > sell_row[HIGH_IDX]: - return sell_row[OPEN_IDX] + if trade.stop_loss > row[HIGH_IDX]: + return row[OPEN_IDX] # 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 @@ -388,29 +404,28 @@ class Backtesting: and self.strategy.trailing_stop_positive ): # Worst case: price reaches stop_positive_offset and dives down. - stop_rate = (sell_row[OPEN_IDX] * + stop_rate = (row[OPEN_IDX] * (1 + side_1 * abs(self.strategy.trailing_stop_positive_offset) - side_1 * abs(self.strategy.trailing_stop_positive / leverage))) else: # Worst case: price ticks tiny bit above open and dives down. - stop_rate = sell_row[OPEN_IDX] * (1 - - side_1 * abs(trade.stop_loss_pct / leverage)) + stop_rate = row[OPEN_IDX] * (1 - side_1 * abs(trade.stop_loss_pct / leverage)) if is_short: - assert stop_rate > sell_row[LOW_IDX] + assert stop_rate > row[LOW_IDX] else: - assert stop_rate < sell_row[HIGH_IDX] + 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(sell_row[HIGH_IDX], stop_rate) + return min(row[HIGH_IDX], stop_rate) else: - return max(sell_row[LOW_IDX], stop_rate) + return max(row[LOW_IDX], stop_rate) # Set close_rate to stoploss return trade.stop_loss - def _get_close_rate_for_roi(self, sell_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 @@ -418,57 +433,57 @@ class Backtesting: roi_entry, roi = self.strategy.min_roi_reached_entry(trade_dur) if roi is not None and roi_entry is not None: if roi == -1 and roi_entry % self.timeframe_min == 0: - # When forceselling with ROI=-1, the roi time will always be equal to trade_dur. + # When force_exiting with ROI=-1, the roi time will always be equal to trade_dur. # If that entry is a multiple of the timeframe (so on candle open) # - we'll use open instead of close - return sell_row[OPEN_IDX] + return row[OPEN_IDX] # - (Expected abs profit - open_rate - open_fee) / (fee_close -1) roi_rate = trade.open_rate * roi / leverage open_fee_rate = side_1 * trade.open_rate * (1 + side_1 * trade.fee_open) close_rate = -(roi_rate + open_fee_rate) / (trade.fee_close - side_1 * 1) if is_short: - is_new_roi = sell_row[OPEN_IDX] < close_rate + is_new_roi = row[OPEN_IDX] < close_rate else: - is_new_roi = sell_row[OPEN_IDX] > close_rate + is_new_roi = row[OPEN_IDX] > close_rate if (trade_dur > 0 and trade_dur == roi_entry 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 - return sell_row[OPEN_IDX] + # use Open rate if open_rate > calculated exit rate + return row[OPEN_IDX] if (trade_dur == 0 and ( ( is_short # Red candle (for longs) - and sell_row[OPEN_IDX] < sell_row[CLOSE_IDX] # Red candle - and trade.open_rate > sell_row[OPEN_IDX] # trade-open above open_rate - and close_rate < sell_row[CLOSE_IDX] # closes below close + and row[OPEN_IDX] < row[CLOSE_IDX] # Red candle + and trade.open_rate > row[OPEN_IDX] # trade-open above open_rate + and close_rate < row[CLOSE_IDX] # closes below close ) or ( not is_short # green candle (for shorts) - and sell_row[OPEN_IDX] > sell_row[CLOSE_IDX] # green candle - and trade.open_rate < sell_row[OPEN_IDX] # trade-open below open_rate - and close_rate > sell_row[CLOSE_IDX] # closes above close + and row[OPEN_IDX] > row[CLOSE_IDX] # green candle + and trade.open_rate < row[OPEN_IDX] # trade-open below open_rate + and close_rate > row[CLOSE_IDX] # closes above close ) )): # 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, sell_row[LOW_IDX]), sell_row[HIGH_IDX]) + return min(max(close_rate, row[LOW_IDX]), row[HIGH_IDX]) else: # This should not be reached... - return sell_row[OPEN_IDX] + return row[OPEN_IDX] def _get_adjust_trade_entry_for_candle(self, trade: LocalTrade, row: Tuple ) -> LocalTrade: @@ -497,8 +512,8 @@ 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, - sell_row: Tuple) -> Optional[LocalTrade]: + def _get_exit_trade_entry_for_candle(self, trade: LocalTrade, + row: Tuple) -> Optional[LocalTrade]: # Check if we need to adjust our current positions if self.strategy.position_adjustment_enable: @@ -507,42 +522,53 @@ class Backtesting: entry_count = trade.nr_of_successful_entries check_adjust_entry = (entry_count <= self.strategy.max_entry_position_adjustment) if check_adjust_entry: - trade = self._get_adjust_trade_entry_for_candle(trade, sell_row) + trade = self._get_adjust_trade_entry_for_candle(trade, row) - sell_candle_time: datetime = sell_row[DATE_IDX].to_pydatetime() - enter = sell_row[SHORT_IDX] if trade.is_short else sell_row[LONG_IDX] - exit_ = sell_row[ESHORT_IDX] if trade.is_short else sell_row[ELONG_IDX] - sell = self.strategy.should_exit( - trade, sell_row[OPEN_IDX], sell_candle_time, # type: ignore - enter=enter, exit_=exit_, - low=sell_row[LOW_IDX], high=sell_row[HIGH_IDX] + exit_candle_time: datetime = row[DATE_IDX].to_pydatetime() + enter = row[SHORT_IDX] if trade.is_short else row[LONG_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_sig, + 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 + exit_reason = exit_.exit_reason trade_dur = int((trade.close_date_utc - trade.open_date_utc).total_seconds() // 60) try: - closerate = self._get_close_rate(sell_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.SELL_SIGNAL, ExitType.CUSTOM_SELL): - # Custom exit pricing only for sell-signals + if exit_.exit_type in (ExitType.EXIT_SIGNAL, ExitType.CUSTOM_EXIT): + # Checks and adds an exit tag, after checking that the length of the + # row has the length for an exit tag column + if( + 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,) + ): + exit_reason = row[EXIT_TAG_IDX] + # 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, - proposed_rate=closerate, current_profit=current_profit) + current_time=exit_candle_time, + proposed_rate=closerate, current_profit=current_profit, + exit_tag=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: - closerate = min(closerate, sell_row[HIGH_IDX]) + closerate = min(closerate, row[HIGH_IDX]) else: - closerate = max(closerate, sell_row[LOW_IDX]) + closerate = max(closerate, row[LOW_IDX]) # Confirm trade exit: time_in_force = self.strategy.order_time_in_force['exit'] @@ -550,28 +576,19 @@ 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_reason, # deprecated + exit_reason=exit_reason, + current_time=exit_candle_time): return None - trade.sell_reason = sell.exit_reason - - # Checks and adds an exit tag, after checking that the length of the - # sell_row has the length for an exit tag column - if( - len(sell_row) > EXIT_TAG_IDX - and sell_row[EXIT_TAG_IDX] is not None - and len(sell_row[EXIT_TAG_IDX]) > 0 - ): - trade.sell_reason = sell_row[EXIT_TAG_IDX] + trade.exit_reason = exit_reason self.order_id_counter += 1 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), @@ -592,8 +609,8 @@ class Backtesting: return None - def _get_sell_trade_entry(self, trade: LocalTrade, sell_row: Tuple) -> Optional[LocalTrade]: - sell_candle_time: datetime = sell_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( @@ -601,41 +618,39 @@ 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, sell_row) - detail_data.loc[:, 'enter_long'] = sell_row[LONG_IDX] - detail_data.loc[:, 'exit_long'] = sell_row[ELONG_IDX] - detail_data.loc[:, 'enter_short'] = sell_row[SHORT_IDX] - detail_data.loc[:, 'exit_short'] = sell_row[ESHORT_IDX] - detail_data.loc[:, 'enter_tag'] = sell_row[ENTER_TAG_IDX] - detail_data.loc[:, 'exit_tag'] = sell_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(): - res = self._get_sell_trade_entry_for_candle(trade, det_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] + 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] + for det_row in detail_data[HEADERS].values.tolist(): + 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, sell_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], - direction: str, current_time: datetime, entry_tag: Optional[str], + direction: LongShort, current_time: datetime, entry_tag: Optional[str], trade: Optional[LocalTrade], order_type: str ) -> Tuple[float, float, float, float]: @@ -643,8 +658,10 @@ class Backtesting: propose_rate = strategy_safe_wrapper(self.strategy.custom_entry_price, default_retval=propose_rate)( pair=pair, current_time=current_time, - proposed_rate=propose_rate, entry_tag=entry_tag) # default value is the open rate - # We can't place orders higher than current high (otherwise it'd be a stop limit buy) + 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 entry) # which freqtrade does not support in live. if direction == "short": propose_rate = max(propose_rate, row[LOW_IDX]) @@ -694,21 +711,27 @@ class Backtesting: return propose_rate, stake_amount_val, leverage, min_stake_amount - def _enter_trade(self, pair: str, row: Tuple, direction: str, + def _enter_trade(self, pair: str, row: Tuple, direction: LongShort, stake_amount: Optional[float] = None, - trade: Optional[LocalTrade] = None) -> Optional[LocalTrade]: + trade: Optional[LocalTrade] = None, + requested_rate: Optional[float] = None, + requested_stake: Optional[float] = None) -> Optional[LocalTrade]: current_time = row[DATE_IDX].to_pydatetime() entry_tag = row[ENTER_TAG_IDX] if len(row) >= ENTER_TAG_IDX + 1 else None # let's call the custom entry price, using the open price as default price order_type = self.strategy.order_types['entry'] - pos_adjust = trade is not None + pos_adjust = trade is not None and requested_rate is None propose_rate, stake_amount, leverage, min_stake_amount = self.get_valid_price_and_stake( pair, row, row[OPEN_IDX], stake_amount, direction, current_time, entry_tag, trade, order_type ) + # replace proposed rate if another rate was requested + propose_rate = requested_rate if requested_rate else propose_rate + stake_amount = requested_stake if requested_stake else stake_amount + if not stake_amount: # In case of pos adjust, still return the original trade # If not pos adjust, trade is None @@ -725,6 +748,7 @@ class Backtesting: if stake_amount and (not min_stake_amount or stake_amount > min_stake_amount): self.order_id_counter += 1 + base_currency = self.exchange.get_pair_base_currency(pair) amount = round((stake_amount / propose_rate) * leverage, 8) is_short = (direction == 'short') # Necessary for Margin trading. Disabled until support is enabled. @@ -737,6 +761,8 @@ class Backtesting: id=self.trade_id_counter, open_order_id=self.order_id_counter, pair=pair, + base_currency=base_currency, + stake_currency=self.config['stake_currency'], open_rate=propose_rate, open_rate_requested=propose_rate, open_date=current_time, @@ -772,8 +798,8 @@ class Backtesting: ft_pair=trade.pair, order_id=str(self.order_id_counter), symbol=trade.pair, - ft_order_side=trade.enter_side, - side=trade.enter_side, + ft_order_side=trade.entry_side, + side=trade.entry_side, order_type=order_type, status="open", order_date=current_time, @@ -786,11 +812,11 @@ class Backtesting: remaining=amount, cost=stake_amount + trade.fee_open, ) + trade.orders.append(order) if pos_adjust and self._get_order_filled(order.price, row): - order.close_bt_order(current_time) + order.close_bt_order(current_time, trade) else: trade.open_order_id = str(self.order_id_counter) - trade.orders.append(order) trade.recalc_trade_from_orders() return trade @@ -805,13 +831,13 @@ 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] + exit_row = data[pair][-1] - trade.close_date = sell_row[DATE_IDX].to_pydatetime() - trade.sell_reason = ExitType.FORCE_SELL.value - trade.close(sell_row[OPEN_IDX], show_msg=False) + trade.close_date = exit_row[DATE_IDX].to_pydatetime() + trade.exit_reason = ExitType.FORCE_EXIT.value + trade.close(exit_row[OPEN_IDX], show_msg=False) LocalTrade.close_bt_trade(trade) # Deepcopy object to have wallets update correctly trade1 = deepcopy(trade) @@ -827,7 +853,7 @@ class Backtesting: self.rejected_trades += 1 return False - def check_for_trade_entry(self, row) -> Optional[str]: + def check_for_trade_entry(self, row) -> Optional[LongShort]: enter_long = row[LONG_IDX] == 1 exit_long = row[ELONG_IDX] == 1 enter_short = self._can_short and row[SHORT_IDX] == 1 @@ -841,40 +867,89 @@ class Backtesting: return 'short' return None - def run_protections(self, enable_protections, pair: str, current_time: datetime): + def run_protections( + self, enable_protections, pair: str, current_time: datetime, side: LongShort): if enable_protections: - self.protections.stop_per_pair(pair, current_time) - self.protections.global_stop(current_time) + self.protections.stop_per_pair(pair, current_time, side) + self.protections.global_stop(current_time, side) - def check_order_cancel(self, trade: LocalTrade, current_time) -> bool: + def manage_open_orders(self, trade: LocalTrade, current_time, row: Tuple) -> bool: """ - Check if an order has been canceled. - Returns True if the trade should be Deleted (initial order was canceled). + Check if any open order needs to be cancelled or replaced. + Returns True if the trade should be deleted. """ for order in [o for o in trade.orders if o.ft_is_open]: + if self.check_order_cancel(trade, order, current_time): + # delete trade due to order timeout + return True + elif self.check_order_replace(trade, order, current_time, row): + # delete trade due to user request + return True + # default maintain trade + return False - timedout = self.strategy.ft_check_timed_out(trade, order, current_time) - if timedout: - if order.side == trade.enter_side: - self.timedout_entry_orders += 1 - if trade.nr_of_successful_entries == 0: - # Remove trade due to entry timeout expiration. - return True - else: - # Close additional buy order - del trade.orders[trade.orders.index(order)] - if order.side == trade.exit_side: - self.timedout_exit_orders += 1 - # Close exit order and retry exiting on next signal. + def check_order_cancel(self, trade: LocalTrade, order: Order, current_time) -> bool: + """ + Check if current analyzed order has to be canceled. + Returns True if the trade should be Deleted (initial order was canceled). + """ + timedout = self.strategy.ft_check_timed_out(trade, order, current_time) + if timedout: + if order.side == trade.entry_side: + self.timedout_entry_orders += 1 + if trade.nr_of_successful_entries == 0: + # Remove trade due to entry timeout expiration. + return True + else: + # Close additional entry order del trade.orders[trade.orders.index(order)] + if order.side == trade.exit_side: + self.timedout_exit_orders += 1 + # Close exit order and retry exiting on next signal. + del trade.orders[trade.orders.index(order)] return False + def check_order_replace(self, trade: LocalTrade, order: Order, current_time, + row: Tuple) -> bool: + """ + Check if current analyzed entry order has to be replaced and do so. + If user requested cancellation and there are no filled orders in the trade will + instruct caller to delete the trade. + Returns True if the trade should be deleted. + """ + # only check on new candles for open entry orders + if order.side == trade.entry_side and current_time > order.order_date_utc: + requested_rate = strategy_safe_wrapper(self.strategy.adjust_entry_price, + default_retval=order.price)( + trade=trade, order=order, pair=trade.pair, current_time=current_time, + proposed_rate=row[OPEN_IDX], current_order_rate=order.price, + entry_tag=trade.enter_tag, side=trade.trade_direction + ) # default value is current order price + + # cancel existing order whenever a new rate is requested (or None) + if requested_rate == order.price: + # assumption: there can't be multiple open entry orders at any given time + return False + else: + del trade.orders[trade.orders.index(order)] + + # place new order if result was not None + if requested_rate: + self._enter_trade(pair=trade.pair, row=row, trade=trade, + requested_rate=requested_rate, + requested_stake=(order.remaining * order.price), + direction='short' if trade.is_short else 'long') + else: + # assumption: there can't be multiple open entry orders at any given time + return (trade.nr_of_successful_entries == 0) + return False + def validate_row( 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. @@ -939,14 +1014,14 @@ class Backtesting: self.dataprovider._set_dataframe_max_index(row_index) for t in list(open_trades[pair]): - # 1. Cancel expired buy/sell orders. - if self.check_order_cancel(t, current_time): - # Close trade due to buy timeout expiration. + # 1. Manage currently open orders of active trades + if self.manage_open_orders(t, current_time, row): + # Close trade 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 @@ -956,13 +1031,13 @@ class Backtesting: and self.trade_slot_available(max_open_trades, open_trade_count_start) and current_time != end_date and trade_dir is not None - and not PairLocks.is_pair_locked(pair, row[DATE_IDX]) + and not PairLocks.is_pair_locked(pair, row[DATE_IDX], trade_dir) ): trade = self._enter_trade(pair, row, trade_dir) 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}.") @@ -970,31 +1045,32 @@ class Backtesting: for trade in list(open_trades[pair]): # 3. Process entry orders. - order = trade.select_order(trade.enter_side, is_open=True) + order = trade.select_order(trade.entry_side, is_open=True) if order and self._get_order_filled(order.price, row): - order.close_bt_order(current_time) + order.close_bt_order(current_time, trade) trade.open_order_id = None 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) trades.append(trade) self.wallets.update() - self.run_protections(enable_protections, pair, current_time) + self.run_protections( + enable_protections, pair, current_time, trade.trade_direction) # Move time one configured time_interval ahead. self.progress.increment() @@ -1018,7 +1094,7 @@ class Backtesting: timerange: TimeRange): self.progress.init_step(BacktestState.ANALYZE, 0) - logger.info("Running backtesting for Strategy %s", strat.get_strategy_name()) + logger.info(f"Running backtesting for Strategy {strat.get_strategy_name()}") backtest_start_time = datetime.now(timezone.utc) self._set_strategy(strat) @@ -1044,7 +1120,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)} ' @@ -1066,8 +1142,31 @@ class Backtesting: }) self.all_results[self.strategy.get_strategy_name()] = results + 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 + 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 = pd.concat([signal_candles_only_df, 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) @@ -1126,9 +1225,13 @@ 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_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( 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']) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index de1817eed..1dafb483c 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 @@ -114,8 +114,8 @@ class Hyperopt: self.position_stacking = self.config.get('position_stacking', False) if HyperoptTools.has_space(self.config, 'sell'): - # Make sure use_sell_signal is enabled - self.config['use_sell_signal'] = True + # Make sure use_exit_signal is enabled + self.config['use_exit_signal'] = True self.print_all = self.config.get('print_all', False) self.hyperopt_table_header = 0 @@ -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'): @@ -409,6 +409,51 @@ 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) -> Tuple[List[List[Any]], List[bool]]: + """ + 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` + """ + def unique_list(a_list): + 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] = [] + while i < 5 and len(asked_non_tried) < n_points: + if i < 3: + self.opt.cache_ = {} + asked = unique_list(self.opt.ask(n_points=n_points * 5)) + is_random = [False for _ in range(len(asked))] + else: + asked = unique_list(self.opt.space.rvs(n_samples=n_points * 5)) + is_random = [True for _ in range(len(asked))] + 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: + 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), [False for _ in range(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}") @@ -420,9 +465,10 @@ 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._loop_lock = None # type: ignore # self.backtesting.exchange = None # type: ignore self.backtesting.pairlists = None # type: ignore @@ -473,7 +519,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, 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]) @@ -492,6 +538,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_loss_calmar.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_calmar.py similarity index 96% rename from freqtrade/optimize/hyperopt_loss_calmar.py rename to freqtrade/optimize/hyperopt_loss/hyperopt_loss_calmar.py index 846dae9ea..ea6c151e5 100644 --- a/freqtrade/optimize/hyperopt_loss_calmar.py +++ b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_calmar.py @@ -10,7 +10,7 @@ from typing import Any, Dict from pandas import DataFrame -from freqtrade.data.btanalysis import calculate_max_drawdown +from freqtrade.data.metrics import calculate_max_drawdown from freqtrade.optimize.hyperopt import IHyperOptLoss diff --git a/freqtrade/optimize/hyperopt_loss_max_drawdown.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_max_drawdown.py similarity index 95% rename from freqtrade/optimize/hyperopt_loss_max_drawdown.py rename to freqtrade/optimize/hyperopt_loss/hyperopt_loss_max_drawdown.py index ce955d928..a8af704cd 100644 --- a/freqtrade/optimize/hyperopt_loss_max_drawdown.py +++ b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_max_drawdown.py @@ -8,7 +8,7 @@ from datetime import datetime from pandas import DataFrame -from freqtrade.data.btanalysis import calculate_max_drawdown +from freqtrade.data.metrics import calculate_max_drawdown from freqtrade.optimize.hyperopt import IHyperOptLoss diff --git a/freqtrade/optimize/hyperopt_loss/hyperopt_loss_max_drawdown_relative.py b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_max_drawdown_relative.py new file mode 100644 index 000000000..3182afb47 --- /dev/null +++ b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_max_drawdown_relative.py @@ -0,0 +1,47 @@ +""" +MaxDrawDownRelativeHyperOptLoss + +This module defines the alternative HyperOptLoss class which can be used for +Hyperoptimization. +""" +from typing import Dict + +from pandas import DataFrame + +from freqtrade.data.metrics import calculate_underwater +from freqtrade.optimize.hyperopt import IHyperOptLoss + + +class MaxDrawDownRelativeHyperOptLoss(IHyperOptLoss): + + """ + Defines the loss function for hyperopt. + + This implementation optimizes for max draw down and profit + Less max drawdown more profit -> Lower return value + """ + + @staticmethod + def hyperopt_loss_function(results: DataFrame, config: Dict, + *args, **kwargs) -> float: + + """ + Objective function. + + Uses profit ratio weighted max_drawdown when drawdown is available. + Otherwise directly optimizes profit ratio. + """ + total_profit = results['profit_abs'].sum() + try: + drawdown_df = calculate_underwater( + results, + value_col='profit_abs', + starting_balance=config['dry_run_wallet'] + ) + max_drawdown = abs(min(drawdown_df['drawdown'])) + relative_drawdown = max(drawdown_df['drawdown_relative']) + if max_drawdown == 0: + return -total_profit + return -total_profit / max_drawdown / relative_drawdown + except (Exception, ValueError): + return -total_profit 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 93% rename from freqtrade/optimize/hyperopt_loss_profit_drawdown.py rename to freqtrade/optimize/hyperopt_loss/hyperopt_loss_profit_drawdown.py index 5bd12ff52..ed689edba 100644 --- a/freqtrade/optimize/hyperopt_loss_profit_drawdown.py +++ b/freqtrade/optimize/hyperopt_loss/hyperopt_loss_profit_drawdown.py @@ -9,7 +9,7 @@ individual needs. """ from pandas import DataFrame -from freqtrade.data.btanalysis import calculate_max_drawdown +from freqtrade.data.metrics import calculate_max_drawdown from freqtrade.optimize.hyperopt import IHyperOptLoss 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/optimize/hyperopt_loss_interface.py b/freqtrade/optimize/hyperopt_loss_interface.py index ac8239b75..8366dcc4f 100644 --- a/freqtrade/optimize/hyperopt_loss_interface.py +++ b/freqtrade/optimize/hyperopt_loss_interface.py @@ -19,11 +19,11 @@ class IHyperOptLoss(ABC): @staticmethod @abstractmethod - def hyperopt_loss_function(results: DataFrame, trade_count: int, + def hyperopt_loss_function(*, results: DataFrame, trade_count: int, min_date: datetime, max_date: datetime, config: Dict, processed: Dict[str, DataFrame], backtest_stats: Dict[str, Any], - *args, **kwargs) -> float: + **kwargs) -> float: """ Objective function, returns smaller number for better results """ diff --git a/freqtrade/optimize/hyperopt_tools.py b/freqtrade/optimize/hyperopt_tools.py index 8c84f772a..0421e6e38 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] @@ -310,6 +311,8 @@ 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( @@ -322,12 +325,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 +352,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 @@ -390,8 +395,8 @@ class HyperoptTools(): lambda x: '{} {}'.format( round_coin_value(x['Total profit'], stake_currency, keep_trailing_zeros=True), f"({x['Profit']:,.2%})".rjust(10, ' ') - ).rjust(25+len(stake_currency)) - if x['Total profit'] != 0.0 else '--'.rjust(25+len(stake_currency)), + ).rjust(25 + len(stake_currency)) + if x['Total profit'] != 0.0 else '--'.rjust(25 + len(stake_currency)), axis=1 ) trials = trials.drop(columns=['Total profit']) @@ -399,15 +404,15 @@ class HyperoptTools(): if print_colorized: for i in range(len(trials)): if trials.loc[i]['is_profit']: - for j in range(len(trials.loc[i])-3): + for j in range(len(trials.loc[i]) - 3): trials.iat[i, j] = "{}{}{}".format(Fore.GREEN, str(trials.loc[i][j]), Fore.RESET) if trials.loc[i]['is_best'] and highlight_best: - for j in range(len(trials.loc[i])-3): + for j in range(len(trials.loc[i]) - 3): 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', @@ -459,7 +464,7 @@ class HyperoptTools(): 'loss', 'is_initial_point', 'is_best'] perc_multi = 100 - param_metrics = [("params_dict."+param) for param in results[0]['params_dict'].keys()] + param_metrics = [("params_dict." + param) for param in results[0]['params_dict'].keys()] trials = trials[base_metrics + param_metrics] base_columns = ['Best', 'Epoch', 'Trades', 'Avg profit', 'Median profit', 'Total profit', diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index 97cadd683..42db366a1 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -9,10 +9,10 @@ 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, - calculate_max_drawdown) -from freqtrade.misc import (decimals_per_coin, file_dump_json, get_backtest_metadata_filename, - round_coin_value) +from freqtrade.data.metrics import (calculate_cagr, calculate_csum, calculate_market_change, + calculate_max_drawdown) +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__) @@ -45,6 +45,29 @@ 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]) -> Path: + """ + 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")}_signals.pkl' + ) + + file_dump_joblib(filename, candles) + + return filename + + def _get_line_floatfmt(stake_currency: str) -> List[str]: """ Generate floatformat (goes in line with _generate_result_line()) @@ -166,7 +189,7 @@ def generate_tag_metrics(tag_type: str, return [] -def generate_sell_reason_stats(max_open_trades: int, results: DataFrame) -> List[Dict]: +def generate_exit_reason_stats(max_open_trades: int, results: DataFrame) -> List[Dict]: """ Generate small table outlining Backtest results :param max_open_trades: Max_open_trades parameter @@ -175,8 +198,8 @@ def generate_sell_reason_stats(max_open_trades: int, results: DataFrame) -> List """ tabular_data = [] - for reason, count in results['sell_reason'].value_counts().iteritems(): - result = results.loc[results['sell_reason'] == reason] + for reason, count in results['exit_reason'].value_counts().iteritems(): + result = results.loc[results['exit_reason'] == reason] profit_mean = result['profit_ratio'].mean() profit_sum = result['profit_ratio'].sum() @@ -184,7 +207,7 @@ def generate_sell_reason_stats(max_open_trades: int, results: DataFrame) -> List tabular_data.append( { - 'sell_reason': reason, + 'exit_reason': reason, 'trades': count, 'wins': len(result[result['profit_abs'] > 0]), 'draws': len(result[result['profit_abs'] == 0]), @@ -241,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: @@ -382,7 +405,7 @@ def generate_strategy_stats(pairlist: List[str], enter_tag_results = generate_tag_metrics("enter_tag", starting_balance=start_balance, results=results, skip_nan=False) - exit_reason_stats = generate_sell_reason_stats(max_open_trades=max_open_trades, + exit_reason_stats = generate_exit_reason_stats(max_open_trades=max_open_trades, results=results) left_open_results = generate_pair_metrics(pairlist, stake_currency=stake_currency, starting_balance=start_balance, @@ -406,7 +429,7 @@ def generate_strategy_stats(pairlist: List[str], 'worst_pair': worst_pair, 'results_per_pair': pair_results, 'results_per_enter_tag': enter_tag_results, - 'sell_reason_summary': exit_reason_stats, + 'exit_reason_summary': exit_reason_stats, 'left_open_trades': left_open_results, # 'days_breakdown_stats': days_breakdown_stats, @@ -423,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), @@ -460,10 +484,10 @@ def generate_strategy_stats(pairlist: List[str], 'trailing_only_offset_is_reached': config.get('trailing_only_offset_is_reached', False), 'use_custom_stoploss': config.get('use_custom_stoploss', False), 'minimal_roi': config['minimal_roi'], - 'use_sell_signal': config['use_sell_signal'], - 'sell_profit_only': config['sell_profit_only'], - 'sell_profit_offset': config['sell_profit_offset'], - 'ignore_roi_if_buy_signal': config['ignore_roi_if_buy_signal'], + 'use_exit_signal': config['use_exit_signal'], + 'exit_profit_only': config['exit_profit_only'], + 'exit_profit_offset': config['exit_profit_offset'], + 'ignore_roi_if_entry_signal': config['ignore_roi_if_entry_signal'], **daily_stats, **trade_stats } @@ -474,9 +498,12 @@ def generate_strategy_stats(pairlist: List[str], (drawdown_abs, drawdown_start, drawdown_end, high_val, low_val, max_drawdown) = calculate_max_drawdown( results, value_col='profit_abs', starting_balance=start_balance) + (_, _, _, _, _, max_relative_drawdown) = calculate_max_drawdown( + results, value_col='profit_abs', starting_balance=start_balance, relative=True) strat_stats.update({ 'max_drawdown': max_drawdown_legacy, # Deprecated - do not use 'max_drawdown_account': max_drawdown, + 'max_relative_drawdown': max_relative_drawdown, 'max_drawdown_abs': drawdown_abs, 'drawdown_start': drawdown_start.strftime(DATETIME_PRINT_FORMAT), 'drawdown_start_ts': drawdown_start.timestamp() * 1000, @@ -497,6 +524,7 @@ def generate_strategy_stats(pairlist: List[str], strat_stats.update({ 'max_drawdown': 0.0, 'max_drawdown_account': 0.0, + 'max_relative_drawdown': 0.0, 'max_drawdown_abs': 0.0, 'max_drawdown_low': 0.0, 'max_drawdown_high': 0.0, @@ -572,7 +600,7 @@ def text_table_bt_results(pair_results: List[Dict[str, Any]], stake_currency: st floatfmt=floatfmt, tablefmt="orgtbl", stralign="right") -def text_table_exit_reason(sell_reason_stats: List[Dict[str, Any]], stake_currency: str) -> str: +def text_table_exit_reason(exit_reason_stats: List[Dict[str, Any]], stake_currency: str) -> str: """ Generate small table outlining Backtest results :param sell_reason_stats: Exit reason metrics @@ -590,12 +618,12 @@ def text_table_exit_reason(sell_reason_stats: List[Dict[str, Any]], stake_curren ] output = [[ - t['sell_reason'], t['trades'], + t.get('exit_reason', t.get('sell_reason')), t['trades'], _generate_wins_draws_losses(t['wins'], t['draws'], t['losses']), t['profit_mean_pct'], t['profit_sum_pct'], round_coin_value(t['profit_total_abs'], stake_currency, False), t['profit_total_pct'], - ] for t in sell_reason_stats] + ] for t in exit_reason_stats] return tabulate(output, headers=headers, tablefmt="orgtbl", stralign="right") @@ -705,6 +733,26 @@ def text_table_add_metrics(strat_results: Dict) -> str: strat_results['stake_currency'])), ] if strat_results.get('trade_count_short', 0) > 0 else [] + drawdown_metrics = [] + if 'max_relative_drawdown' in strat_results: + # Compatibility to show old hyperopt results + drawdown_metrics.append( + ('Max % of account underwater', f"{strat_results['max_relative_drawdown']:.2%}") + ) + drawdown_metrics.extend([ + ('Absolute Drawdown (Account)', f"{strat_results['max_drawdown_account']:.2%}") + if 'max_drawdown_account' in strat_results else ( + 'Drawdown', f"{strat_results['max_drawdown']:.2%}"), + ('Absolute Drawdown', round_coin_value(strat_results['max_drawdown_abs'], + strat_results['stake_currency'])), + ('Drawdown high', round_coin_value(strat_results['max_drawdown_high'], + strat_results['stake_currency'])), + ('Drawdown low', round_coin_value(strat_results['max_drawdown_low'], + strat_results['stake_currency'])), + ('Drawdown Start', strat_results['drawdown_start']), + ('Drawdown End', strat_results['drawdown_end']), + ]) + # Newly added fields should be ignored if they are missing in strat_results. hyperopt-show # command stores these results and newer version of freqtrade must be able to handle old # results with missing new fields. @@ -723,6 +771,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%}" 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%}"), @@ -759,18 +808,7 @@ def text_table_add_metrics(strat_results: Dict) -> str: ('Max balance', round_coin_value(strat_results['csum_max'], strat_results['stake_currency'])), - # Compatibility to show old hyperopt results - ('Drawdown (Account)', f"{strat_results['max_drawdown_account']:.2%}") - if 'max_drawdown_account' in strat_results else ( - 'Drawdown', f"{strat_results['max_drawdown']:.2%}"), - ('Drawdown', round_coin_value(strat_results['max_drawdown_abs'], - strat_results['stake_currency'])), - ('Drawdown high', round_coin_value(strat_results['max_drawdown_high'], - strat_results['stake_currency'])), - ('Drawdown low', round_coin_value(strat_results['max_drawdown_low'], - strat_results['stake_currency'])), - ('Drawdown Start', strat_results['drawdown_start']), - ('Drawdown End', strat_results['drawdown_end']), + *drawdown_metrics, ('Market change', f"{strat_results['market_change']:.2%}"), ] @@ -813,7 +851,8 @@ def show_backtest_result(strategy: str, results: Dict[str, Any], stake_currency: print(' ENTER TAG STATS '.center(len(table.splitlines()[0]), '=')) print(table) - table = text_table_exit_reason(sell_reason_stats=results['sell_reason_summary'], + exit_reasons = results.get('exit_reason_summary', results.get('sell_reason_summary')) + table = text_table_exit_reason(exit_reason_stats=exit_reasons, stake_currency=stake_currency) if isinstance(table, str) and len(table) > 0: print(' EXIT REASON STATS '.center(len(table.splitlines()[0]), '=')) diff --git a/freqtrade/persistence/__init__.py b/freqtrade/persistence/__init__.py index d1fcac0ba..ab6e2f6a5 100644 --- a/freqtrade/persistence/__init__.py +++ b/freqtrade/persistence/__init__.py @@ -1,5 +1,5 @@ # flake8: noqa: F401 -from freqtrade.persistence.models import (LocalTrade, Order, Trade, clean_dry_run_db, cleanup_db, - init_db) +from freqtrade.persistence.models import clean_dry_run_db, cleanup_db, init_db from freqtrade.persistence.pairlock_middleware import PairLocks +from freqtrade.persistence.trade_model import LocalTrade, Order, Trade diff --git a/freqtrade/persistence/base.py b/freqtrade/persistence/base.py new file mode 100644 index 000000000..fb2d561e1 --- /dev/null +++ b/freqtrade/persistence/base.py @@ -0,0 +1,7 @@ + +from typing import Any + +from sqlalchemy.orm import declarative_base + + +_DECL_BASE: Any = declarative_base() diff --git a/freqtrade/persistence/migrations.py b/freqtrade/persistence/migrations.py index a84503c74..53e35d9da 100644 --- a/freqtrade/persistence/migrations.py +++ b/freqtrade/persistence/migrations.py @@ -3,11 +3,13 @@ from typing import List from sqlalchemy import inspect, text +from freqtrade.exceptions import OperationalException + logger = logging.getLogger(__name__) -def get_table_names_for_table(inspector, tabletype): +def get_table_names_for_table(inspector, tabletype) -> List[str]: return [t for t in inspector.get_table_names() if t.startswith(tabletype)] @@ -19,7 +21,7 @@ def get_column_def(columns: List, column: str, default: str) -> str: return default if not has_column(columns, column) else column -def get_backup_name(tabs, backup_prefix: str): +def get_backup_name(tabs: List[str], backup_prefix: str): table_back_name = backup_prefix for i, table_back_name in enumerate(tabs): table_back_name = f'{backup_prefix}{i}' @@ -44,7 +46,7 @@ def get_last_sequence_ids(engine, trade_back_name, order_back_name): return order_id, trade_id -def set_sequence_ids(engine, order_id, trade_id): +def set_sequence_ids(engine, order_id, trade_id, pairlock_id=None): if engine.name == 'postgresql': with engine.begin() as connection: @@ -52,12 +54,27 @@ def set_sequence_ids(engine, order_id, trade_id): connection.execute(text(f"ALTER SEQUENCE orders_id_seq RESTART WITH {order_id}")) if trade_id: connection.execute(text(f"ALTER SEQUENCE trades_id_seq RESTART WITH {trade_id}")) + if pairlock_id: + connection.execute( + text(f"ALTER SEQUENCE pairlocks_id_seq RESTART WITH {pairlock_id}")) + + +def drop_index_on_table(engine, inspector, table_bak_name): + with engine.begin() as connection: + # drop indexes on backup table in new session + for index in inspector.get_indexes(table_bak_name): + if engine.name == 'mysql': + connection.execute(text(f"drop index {index['name']} on {table_bak_name}")) + else: + connection.execute(text(f"drop index {index['name']}")) def migrate_trades_and_orders_table( decl_base, inspector, engine, trade_back_name: str, cols: List, order_back_name: str, cols_order: List): + base_currency = get_column_def(cols, 'base_currency', 'null') + stake_currency = get_column_def(cols, 'stake_currency', 'null') fee_open = get_column_def(cols, 'fee_open', 'fee') fee_open_cost = get_column_def(cols, 'fee_open_cost', 'null') fee_open_currency = get_column_def(cols, 'fee_open_currency', 'null') @@ -74,7 +91,7 @@ def migrate_trades_and_orders_table( stoploss_last_update = get_column_def(cols, 'stoploss_last_update', 'null') max_rate = get_column_def(cols, 'max_rate', '0.0') min_rate = get_column_def(cols, 'min_rate', 'null') - sell_reason = get_column_def(cols, 'sell_reason', 'null') + exit_reason = get_column_def(cols, 'sell_reason', get_column_def(cols, 'exit_reason', 'null')) strategy = get_column_def(cols, 'strategy', 'null') enter_tag = get_column_def(cols, 'buy_tag', get_column_def(cols, 'enter_tag', 'null')) @@ -85,7 +102,10 @@ def migrate_trades_and_orders_table( liquidation_price = get_column_def(cols, 'liquidation_price', get_column_def(cols, 'isolated_liq', 'null')) # sqlite does not support literals for booleans - is_short = get_column_def(cols, 'is_short', '0') + if engine.name == 'postgresql': + is_short = get_column_def(cols, 'is_short', 'false') + else: + is_short = get_column_def(cols, 'is_short', '0') # Margin Properties interest_rate = get_column_def(cols, 'interest_rate', '0.0') @@ -104,20 +124,15 @@ def migrate_trades_and_orders_table( close_profit_abs = get_column_def( cols, 'close_profit_abs', f"(amount * close_rate * (1 - {fee_close})) - {open_trade_value}") - sell_order_status = get_column_def(cols, 'sell_order_status', 'null') + exit_order_status = get_column_def(cols, 'exit_order_status', + get_column_def(cols, 'sell_order_status', 'null')) amount_requested = get_column_def(cols, 'amount_requested', 'amount') # Schema migration necessary with engine.begin() as connection: connection.execute(text(f"alter table trades rename to {trade_back_name}")) - with engine.begin() as connection: - # drop indexes on backup table in new session - for index in inspector.get_indexes(trade_back_name): - if engine.name == 'mysql': - connection.execute(text(f"drop index {index['name']} on {trade_back_name}")) - else: - connection.execute(text(f"drop index {index['name']}")) + drop_index_on_table(engine, inspector, trade_back_name) order_id, trade_id = get_last_sequence_ids(engine, trade_back_name, order_back_name) @@ -129,19 +144,20 @@ def migrate_trades_and_orders_table( # Copy data back - following the correct schema with engine.begin() as connection: connection.execute(text(f"""insert into trades - (id, exchange, pair, is_open, + (id, exchange, pair, base_currency, stake_currency, is_open, fee_open, fee_open_cost, fee_open_currency, fee_close, fee_close_cost, fee_close_currency, open_rate, open_rate_requested, close_rate, close_rate_requested, close_profit, stake_amount, amount, amount_requested, open_date, close_date, open_order_id, stop_loss, stop_loss_pct, initial_stop_loss, initial_stop_loss_pct, stoploss_order_id, stoploss_last_update, - max_rate, min_rate, sell_reason, sell_order_status, strategy, enter_tag, + max_rate, min_rate, exit_reason, exit_order_status, strategy, enter_tag, timeframe, open_trade_value, close_profit_abs, trading_mode, leverage, liquidation_price, is_short, interest_rate, funding_fees ) - select id, lower(exchange), pair, + select id, lower(exchange), pair, {base_currency} base_currency, + {stake_currency} stake_currency, is_open, {fee_open} fee_open, {fee_open_cost} fee_open_cost, {fee_open_currency} fee_open_currency, {fee_close} fee_close, {fee_close_cost} fee_close_cost, {fee_close_currency} fee_close_currency, @@ -152,8 +168,14 @@ def migrate_trades_and_orders_table( {initial_stop_loss} initial_stop_loss, {initial_stop_loss_pct} initial_stop_loss_pct, {stoploss_order_id} stoploss_order_id, {stoploss_last_update} stoploss_last_update, - {max_rate} max_rate, {min_rate} min_rate, {sell_reason} sell_reason, - {sell_order_status} sell_order_status, + {max_rate} max_rate, {min_rate} min_rate, + case when {exit_reason} = 'sell_signal' then 'exit_signal' + when {exit_reason} = 'custom_sell' then 'custom_exit' + when {exit_reason} = 'force_sell' then 'force_exit' + when {exit_reason} = 'emergency_sell' then 'emergency_exit' + else {exit_reason} + end exit_reason, + {exit_order_status} exit_order_status, {strategy} strategy, {enter_tag} enter_tag, {timeframe} timeframe, {open_trade_value} open_trade_value, {close_profit_abs} close_profit_abs, {trading_mode} trading_mode, {leverage} leverage, {liquidation_price} liquidation_price, @@ -166,23 +188,6 @@ def migrate_trades_and_orders_table( set_sequence_ids(engine, order_id, trade_id) -def migrate_open_orders_to_trades(engine): - with engine.begin() as connection: - connection.execute(text(""" - insert into orders (ft_trade_id, ft_pair, order_id, ft_order_side, ft_is_open) - select id ft_trade_id, pair ft_pair, open_order_id, - case when close_rate_requested is null then 'buy' - else 'sell' end ft_order_side, 1 ft_is_open - from trades - where open_order_id is not null - union all - select id ft_trade_id, pair ft_pair, stoploss_order_id order_id, - 'stoploss' ft_order_side, 1 ft_is_open - from trades - where stoploss_order_id is not null - """)) - - def drop_orders_table(engine, table_back_name: str): # Drop and recreate orders table as backup # This drops foreign keys, too. @@ -200,7 +205,7 @@ def migrate_orders_table(engine, table_back_name: str, cols_order: List): # sqlite does not support literals for booleans with engine.begin() as connection: connection.execute(text(f""" - insert into orders ( id, ft_trade_id, ft_order_side, ft_pair, ft_is_open, order_id, + insert into orders (id, ft_trade_id, ft_order_side, ft_pair, ft_is_open, order_id, status, symbol, order_type, side, price, amount, filled, average, remaining, cost, order_date, order_filled_date, order_update_date, ft_fee_base) select id, ft_trade_id, ft_order_side, ft_pair, ft_is_open, order_id, @@ -210,6 +215,31 @@ def migrate_orders_table(engine, table_back_name: str, cols_order: List): """)) +def migrate_pairlocks_table( + decl_base, inspector, engine, + pairlock_back_name: str, cols: List): + + # Schema migration necessary + with engine.begin() as connection: + connection.execute(text(f"alter table pairlocks rename to {pairlock_back_name}")) + + drop_index_on_table(engine, inspector, pairlock_back_name) + + side = get_column_def(cols, 'side', "'*'") + + # let SQLAlchemy create the schema as required + decl_base.metadata.create_all(engine) + # Copy data back - following the correct schema + with engine.begin() as connection: + connection.execute(text(f"""insert into pairlocks + (id, pair, side, reason, lock_time, + lock_end_time, active) + select id, pair, {side} side, reason, lock_time, + lock_end_time, active + from {pairlock_back_name} + """)) + + def set_sqlite_to_wal(engine): if engine.name == 'sqlite' and str(engine.url) != 'sqlite://': # Set Mode to @@ -223,24 +253,38 @@ def check_migrate(engine, decl_base, previous_tables) -> None: """ inspector = inspect(engine) - cols = inspector.get_columns('trades') + cols_trades = inspector.get_columns('trades') cols_orders = inspector.get_columns('orders') + cols_pairlocks = inspector.get_columns('pairlocks') tabs = get_table_names_for_table(inspector, 'trades') table_back_name = get_backup_name(tabs, 'trades_bak') order_tabs = get_table_names_for_table(inspector, 'orders') order_table_bak_name = get_backup_name(order_tabs, 'orders_bak') + pairlock_tabs = get_table_names_for_table(inspector, 'pairlocks') + pairlock_table_bak_name = get_backup_name(pairlock_tabs, 'pairlocks_bak') # Check if migration necessary # Migrates both trades and orders table! # if ('orders' not in previous_tables # or not has_column(cols_orders, 'leverage')): - if not has_column(cols, 'liquidation_price'): + if not has_column(cols_trades, 'base_currency'): logger.info(f"Running database migration for trades - " f"backup: {table_back_name}, {order_table_bak_name}") migrate_trades_and_orders_table( - decl_base, inspector, engine, table_back_name, cols, order_table_bak_name, cols_orders) + decl_base, inspector, engine, table_back_name, cols_trades, + order_table_bak_name, cols_orders) + if not has_column(cols_pairlocks, 'side'): + logger.info(f"Running database migration for pairlocks - " + f"backup: {pairlock_table_bak_name}") + + migrate_pairlocks_table( + decl_base, inspector, engine, pairlock_table_bak_name, cols_pairlocks + ) if 'orders' not in previous_tables and 'trades' in previous_tables: - logger.info('Moving open orders to Orders table.') - migrate_open_orders_to_trades(engine) + raise OperationalException( + "Your database seems to be very old. " + "Please update to freqtrade 2022.3 to migrate this database or " + "start with a fresh database.") + set_sqlite_to_wal(engine) diff --git a/freqtrade/persistence/models.py b/freqtrade/persistence/models.py index a23c8e43e..c31e50892 100644 --- a/freqtrade/persistence/models.py +++ b/freqtrade/persistence/models.py @@ -2,28 +2,22 @@ This module contains the class to persist trades into SQLite """ import logging -from datetime import datetime, timedelta, timezone -from decimal import Decimal -from typing import Any, Dict, List, Optional -from sqlalchemy import (Boolean, Column, DateTime, Enum, Float, ForeignKey, Integer, String, - create_engine, desc, func, inspect) +from sqlalchemy import create_engine, inspect from sqlalchemy.exc import NoSuchModuleError -from sqlalchemy.orm import Query, declarative_base, relationship, scoped_session, sessionmaker +from sqlalchemy.orm import scoped_session, sessionmaker from sqlalchemy.pool import StaticPool -from sqlalchemy.sql.schema import UniqueConstraint -from freqtrade.constants import DATETIME_PRINT_FORMAT, NON_OPEN_EXCHANGE_STATES -from freqtrade.enums import ExitType, TradingMode -from freqtrade.exceptions import DependencyException, OperationalException -from freqtrade.leverage import interest +from freqtrade.exceptions import OperationalException +from freqtrade.persistence.base import _DECL_BASE from freqtrade.persistence.migrations import check_migrate +from freqtrade.persistence.pairlock import PairLock +from freqtrade.persistence.trade_model import Order, Trade logger = logging.getLogger(__name__) -_DECL_BASE: Any = declarative_base() _SQL_DOCS_URL = 'http://docs.sqlalchemy.org/en/latest/core/engines.html#database-urls' @@ -93,1342 +87,3 @@ def clean_dry_run_db() -> None: if 'dry_run' in trade.open_order_id: trade.open_order_id = None Trade.commit() - - -class Order(_DECL_BASE): - """ - Order database model - Keeps a record of all orders placed on the exchange - - One to many relationship with Trades: - - One trade can have many orders - - One Order can only be associated with one Trade - - Mirrors CCXT Order structure - """ - __tablename__ = 'orders' - # Uniqueness should be ensured over pair, order_id - # its likely that order_id is unique per Pair on some exchanges. - __table_args__ = (UniqueConstraint('ft_pair', 'order_id', name="_order_pair_order_id"),) - - id = Column(Integer, primary_key=True) - ft_trade_id = Column(Integer, ForeignKey('trades.id'), index=True) - - trade = relationship("Trade", back_populates="orders") - - # order_side can only be 'buy', 'sell' or 'stoploss' - ft_order_side: str = Column(String(25), nullable=False) - ft_pair: str = Column(String(25), nullable=False) - ft_is_open = Column(Boolean, nullable=False, default=True, index=True) - - order_id: str = Column(String(255), nullable=False, index=True) - status = Column(String(255), nullable=True) - symbol = Column(String(25), nullable=True) - order_type: str = Column(String(50), nullable=True) - side = Column(String(25), nullable=True) - price = Column(Float, nullable=True) - average = Column(Float, nullable=True) - amount = Column(Float, nullable=True) - filled = Column(Float, nullable=True) - remaining = Column(Float, nullable=True) - cost = Column(Float, nullable=True) - order_date = Column(DateTime, nullable=True, default=datetime.utcnow) - order_filled_date = Column(DateTime, nullable=True) - order_update_date = Column(DateTime, nullable=True) - - ft_fee_base = Column(Float, nullable=True) - - @property - def order_date_utc(self) -> datetime: - """ Order-date with UTC timezoneinfo""" - return self.order_date.replace(tzinfo=timezone.utc) - - @property - def safe_price(self) -> float: - return self.average or self.price - - @property - def safe_filled(self) -> float: - return self.filled or self.amount or 0.0 - - @property - def safe_fee_base(self) -> float: - return self.ft_fee_base or 0.0 - - @property - def safe_amount_after_fee(self) -> float: - return self.safe_filled - self.safe_fee_base - - def __repr__(self): - - return (f'Order(id={self.id}, order_id={self.order_id}, trade_id={self.ft_trade_id}, ' - f'side={self.side}, order_type={self.order_type}, status={self.status})') - - def update_from_ccxt_object(self, order): - """ - Update Order from ccxt response - Only updates if fields are available from ccxt - - """ - if self.order_id != str(order['id']): - raise DependencyException("Order-id's don't match") - - self.status = order.get('status', self.status) - self.symbol = order.get('symbol', self.symbol) - self.order_type = order.get('type', self.order_type) - self.side = order.get('side', self.side) - self.price = order.get('price', self.price) - self.amount = order.get('amount', self.amount) - self.filled = order.get('filled', self.filled) - self.average = order.get('average', self.average) - self.remaining = order.get('remaining', self.remaining) - self.cost = order.get('cost', self.cost) - - if 'timestamp' in order and order['timestamp'] is not None: - self.order_date = datetime.fromtimestamp(order['timestamp'] / 1000, tz=timezone.utc) - - self.ft_is_open = True - if self.status in NON_OPEN_EXCHANGE_STATES: - self.ft_is_open = False - if (order.get('filled', 0.0) or 0.0) > 0: - self.order_filled_date = datetime.now(timezone.utc) - self.order_update_date = datetime.now(timezone.utc) - - def to_json(self, entry_side: str) -> Dict[str, Any]: - return { - 'pair': self.ft_pair, - 'order_id': self.order_id, - 'status': self.status, - 'amount': self.amount, - 'average': round(self.average, 8) if self.average else 0, - 'safe_price': self.safe_price, - 'cost': self.cost if self.cost else 0, - 'filled': self.filled, - 'ft_order_side': self.ft_order_side, - 'is_open': self.ft_is_open, - 'order_date': self.order_date.strftime(DATETIME_PRINT_FORMAT) - if self.order_date else None, - 'order_timestamp': int(self.order_date.replace( - tzinfo=timezone.utc).timestamp() * 1000) if self.order_date else None, - 'order_filled_date': self.order_filled_date.strftime(DATETIME_PRINT_FORMAT) - if self.order_filled_date else None, - 'order_filled_timestamp': int(self.order_filled_date.replace( - tzinfo=timezone.utc).timestamp() * 1000) if self.order_filled_date else None, - 'order_type': self.order_type, - 'price': self.price, - 'ft_is_entry': self.ft_order_side == entry_side, - 'remaining': self.remaining, - } - - def close_bt_order(self, close_date: datetime): - self.order_filled_date = close_date - self.filled = self.amount - self.status = 'closed' - self.ft_is_open = False - - @staticmethod - def update_orders(orders: List['Order'], order: Dict[str, Any]): - """ - Get all non-closed orders - useful when trying to batch-update orders - """ - if not isinstance(order, dict): - logger.warning(f"{order} is not a valid response object.") - return - - filtered_orders = [o for o in orders if o.order_id == order.get('id')] - if filtered_orders: - oobj = filtered_orders[0] - oobj.update_from_ccxt_object(order) - Order.query.session.commit() - else: - logger.warning(f"Did not find order for {order}.") - - @staticmethod - def parse_from_ccxt_object(order: Dict[str, Any], pair: str, side: str) -> 'Order': - """ - Parse an order from a ccxt object and return a new order Object. - """ - o = Order(order_id=str(order['id']), ft_order_side=side, ft_pair=pair) - - o.update_from_ccxt_object(order) - return o - - @staticmethod - def get_open_orders() -> List['Order']: - """ - Retrieve open orders from the database - :return: List of open orders - """ - return Order.query.filter(Order.ft_is_open.is_(True)).all() - - -class LocalTrade(): - """ - Trade database model. - Used in backtesting - must be aligned to Trade model! - - """ - use_db: bool = False - # Trades container for backtesting - trades: List['LocalTrade'] = [] - trades_open: List['LocalTrade'] = [] - total_profit: float = 0 - - id: int = 0 - - orders: List[Order] = [] - - exchange: str = '' - pair: str = '' - is_open: bool = True - fee_open: float = 0.0 - fee_open_cost: Optional[float] = None - fee_open_currency: str = '' - fee_close: float = 0.0 - fee_close_cost: Optional[float] = None - fee_close_currency: str = '' - open_rate: float = 0.0 - open_rate_requested: Optional[float] = None - # open_trade_value - calculated via _calc_open_trade_value - open_trade_value: float = 0.0 - close_rate: Optional[float] = None - close_rate_requested: Optional[float] = None - close_profit: Optional[float] = None - close_profit_abs: Optional[float] = None - stake_amount: float = 0.0 - amount: float = 0.0 - amount_requested: Optional[float] = None - open_date: datetime - close_date: Optional[datetime] = None - open_order_id: Optional[str] = None - # absolute value of the stop loss - stop_loss: float = 0.0 - # percentage value of the stop loss - stop_loss_pct: float = 0.0 - # absolute value of the initial stop loss - initial_stop_loss: float = 0.0 - # percentage value of the initial stop loss - initial_stop_loss_pct: Optional[float] = None - # stoploss order id which is on exchange - stoploss_order_id: Optional[str] = None - # last update time of the stoploss order on exchange - stoploss_last_update: Optional[datetime] = None - # absolute value of the highest reached price - max_rate: float = 0.0 - # Lowest price reached - min_rate: float = 0.0 - sell_reason: str = '' - sell_order_status: str = '' - strategy: str = '' - enter_tag: Optional[str] = None - timeframe: Optional[int] = None - - trading_mode: TradingMode = TradingMode.SPOT - - # Leverage trading properties - liquidation_price: Optional[float] = None - is_short: bool = False - leverage: float = 1.0 - - # Margin trading properties - interest_rate: float = 0.0 - - # Futures properties - funding_fees: Optional[float] = None - - @property - def buy_tag(self) -> Optional[str]: - """ - Compatibility between buy_tag (old) and enter_tag (new) - Consider buy_tag deprecated - """ - return self.enter_tag - - @property - def has_no_leverage(self) -> bool: - """Returns true if this is a non-leverage, non-short trade""" - return ((self.leverage == 1.0 or self.leverage is None) and not self.is_short) - - @property - def borrowed(self) -> float: - """ - The amount of currency borrowed from the exchange for leverage trades - If a long trade, the amount is in base currency - If a short trade, the amount is in the other currency being traded - """ - if self.has_no_leverage: - return 0.0 - elif not self.is_short: - return (self.amount * self.open_rate) * ((self.leverage-1)/self.leverage) - else: - return self.amount - - @property - def open_date_utc(self): - return self.open_date.replace(tzinfo=timezone.utc) - - @property - def close_date_utc(self): - return self.close_date.replace(tzinfo=timezone.utc) - - @property - def enter_side(self) -> str: - if self.is_short: - return "sell" - else: - return "buy" - - @property - def exit_side(self) -> str: - if self.is_short: - return "buy" - else: - return "sell" - - @property - def trade_direction(self) -> str: - if self.is_short: - return "short" - else: - return "long" - - def __init__(self, **kwargs): - for key in kwargs: - setattr(self, key, kwargs[key]) - self.recalc_open_trade_value() - if self.trading_mode == TradingMode.MARGIN and self.interest_rate is None: - raise OperationalException( - f"{self.trading_mode.value} trading requires param interest_rate on trades") - - 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'open_rate={self.open_rate:.8f}, open_since={open_since})' - ) - - def to_json(self) -> Dict[str, Any]: - filled_orders = self.select_filled_orders() - orders = [order.to_json(self.enter_side) for order in filled_orders] - - return { - 'trade_id': self.id, - 'pair': self.pair, - 'is_open': self.is_open, - 'exchange': self.exchange, - 'amount': round(self.amount, 8), - 'amount_requested': round(self.amount_requested, 8) if self.amount_requested else None, - 'stake_amount': round(self.stake_amount, 8), - 'strategy': self.strategy, - 'buy_tag': self.enter_tag, - 'enter_tag': self.enter_tag, - 'timeframe': self.timeframe, - - 'fee_open': self.fee_open, - 'fee_open_cost': self.fee_open_cost, - 'fee_open_currency': self.fee_open_currency, - 'fee_close': self.fee_close, - 'fee_close_cost': self.fee_close_cost, - 'fee_close_currency': self.fee_close_currency, - - 'open_date': self.open_date.strftime(DATETIME_PRINT_FORMAT), - 'open_timestamp': int(self.open_date.replace(tzinfo=timezone.utc).timestamp() * 1000), - 'open_rate': self.open_rate, - 'open_rate_requested': self.open_rate_requested, - 'open_trade_value': round(self.open_trade_value, 8), - - 'close_date': (self.close_date.strftime(DATETIME_PRINT_FORMAT) - if self.close_date else None), - 'close_timestamp': int(self.close_date.replace( - tzinfo=timezone.utc).timestamp() * 1000) if self.close_date else None, - 'close_rate': self.close_rate, - 'close_rate_requested': self.close_rate_requested, - 'close_profit': self.close_profit, # Deprecated - 'close_profit_pct': round(self.close_profit * 100, 2) if self.close_profit else None, - 'close_profit_abs': self.close_profit_abs, # Deprecated - - 'trade_duration_s': (int((self.close_date_utc - self.open_date_utc).total_seconds()) - if self.close_date else None), - 'trade_duration': (int((self.close_date_utc - self.open_date_utc).total_seconds() // 60) - if self.close_date else None), - - 'profit_ratio': self.close_profit, - 'profit_pct': round(self.close_profit * 100, 2) if self.close_profit else None, - 'profit_abs': self.close_profit_abs, - - 'sell_reason': self.sell_reason, - 'sell_order_status': self.sell_order_status, - 'stop_loss_abs': self.stop_loss, - 'stop_loss_ratio': self.stop_loss_pct if self.stop_loss_pct else None, - 'stop_loss_pct': (self.stop_loss_pct * 100) if self.stop_loss_pct else None, - 'stoploss_order_id': self.stoploss_order_id, - 'stoploss_last_update': (self.stoploss_last_update.strftime(DATETIME_PRINT_FORMAT) - if self.stoploss_last_update else None), - 'stoploss_last_update_timestamp': int(self.stoploss_last_update.replace( - tzinfo=timezone.utc).timestamp() * 1000) if self.stoploss_last_update else None, - 'initial_stop_loss_abs': self.initial_stop_loss, - 'initial_stop_loss_ratio': (self.initial_stop_loss_pct - if self.initial_stop_loss_pct else None), - 'initial_stop_loss_pct': (self.initial_stop_loss_pct * 100 - if self.initial_stop_loss_pct else None), - 'min_rate': self.min_rate, - 'max_rate': self.max_rate, - - 'leverage': self.leverage, - 'interest_rate': self.interest_rate, - 'liquidation_price': self.liquidation_price, - 'is_short': self.is_short, - 'trading_mode': self.trading_mode, - 'funding_fees': self.funding_fees, - 'open_order_id': self.open_order_id, - 'orders': orders, - } - - @staticmethod - def reset_trades() -> None: - """ - Resets all trades. Only active for backtesting mode. - """ - LocalTrade.trades = [] - LocalTrade.trades_open = [] - LocalTrade.total_profit = 0 - - def adjust_min_max_rates(self, current_price: float, current_price_low: float) -> None: - """ - Adjust the max_rate and min_rate. - """ - self.max_rate = max(current_price, self.max_rate or self.open_rate) - self.min_rate = min(current_price_low, self.min_rate or self.open_rate) - - def set_isolated_liq(self, liquidation_price: Optional[float]): - """ - Method you should use to set self.liquidation price. - Assures stop_loss is not passed the liquidation price - """ - if not liquidation_price: - return - self.liquidation_price = liquidation_price - - def _set_stop_loss(self, stop_loss: float, percent: float): - """ - Method you should use to set self.stop_loss. - Assures stop_loss is not passed the liquidation price - """ - if self.liquidation_price is not None: - if self.is_short: - sl = min(stop_loss, self.liquidation_price) - else: - sl = max(stop_loss, self.liquidation_price) - else: - sl = stop_loss - - if not self.stop_loss: - self.initial_stop_loss = sl - self.stop_loss = sl - - self.stop_loss_pct = -1 * abs(percent) - self.stoploss_last_update = datetime.utcnow() - - def adjust_stop_loss(self, current_price: float, stoploss: float, - initial: bool = False) -> None: - """ - This adjusts the stop loss to it's most recently observed setting - :param current_price: Current rate the asset is traded - :param stoploss: Stoploss as factor (sample -0.05 -> -5% below current price). - :param initial: Called to initiate stop_loss. - Skips everything if self.stop_loss is already set. - """ - if initial and not (self.stop_loss is None or self.stop_loss == 0): - # Don't modify if called with initial and nothing to do - return - - leverage = self.leverage or 1.0 - if self.is_short: - new_loss = float(current_price * (1 + abs(stoploss / leverage))) - # If trading with leverage, don't set the stoploss below the liquidation price - if self.liquidation_price: - new_loss = min(self.liquidation_price, new_loss) - else: - new_loss = float(current_price * (1 - abs(stoploss / leverage))) - # If trading with leverage, don't set the stoploss below the liquidation price - if self.liquidation_price: - new_loss = max(self.liquidation_price, new_loss) - - # no stop loss assigned yet - if self.initial_stop_loss_pct is None: - logger.debug(f"{self.pair} - Assigning new stoploss...") - self._set_stop_loss(new_loss, stoploss) - self.initial_stop_loss = new_loss - self.initial_stop_loss_pct = -1 * abs(stoploss) - - # evaluate if the stop loss needs to be updated - else: - - higher_stop = new_loss > self.stop_loss - lower_stop = new_loss < self.stop_loss - - # stop losses only walk up, never down!, - # ? But adding more to a leveraged trade would create a lower liquidation price, - # ? decreasing the minimum stoploss - if (higher_stop and not self.is_short) or (lower_stop and self.is_short): - logger.debug(f"{self.pair} - Adjusting stoploss...") - self._set_stop_loss(new_loss, stoploss) - else: - logger.debug(f"{self.pair} - Keeping current stoploss...") - - logger.debug( - f"{self.pair} - Stoploss adjusted. current_price={current_price:.8f}, " - f"open_rate={self.open_rate:.8f}, max_rate={self.max_rate or self.open_rate:.8f}, " - f"initial_stop_loss={self.initial_stop_loss:.8f}, " - f"stop_loss={self.stop_loss:.8f}. " - f"Trailing stoploss saved us: " - f"{float(self.stop_loss) - float(self.initial_stop_loss):.8f}.") - - def update_trade(self, order: Order) -> None: - """ - Updates this entity with amount and actual open/close rates. - :param order: order retrieved by exchange.fetch_order() - :return: None - """ - - # Ignore open and cancelled orders - if order.status == 'open' or order.safe_price is None: - return - - logger.info(f'Updating trade (id={self.id}) ...') - - if order.ft_order_side == self.enter_side: - # Update open rate and actual amount - self.open_rate = order.safe_price - self.amount = order.safe_amount_after_fee - if self.is_open: - payment = "SELL" if self.is_short else "BUY" - logger.info(f'{order.order_type.upper()}_{payment} has been fulfilled for {self}.') - self.open_order_id = None - self.recalc_trade_from_orders() - elif order.ft_order_side == self.exit_side: - if self.is_open: - payment = "BUY" if self.is_short else "SELL" - # * On margin shorts, you buy a little bit more than the amount (amount + interest) - logger.info(f'{order.order_type.upper()}_{payment} has been fulfilled for {self}.') - self.close(order.safe_price) - elif order.ft_order_side == 'stoploss': - self.stoploss_order_id = None - self.close_rate_requested = self.stop_loss - self.sell_reason = ExitType.STOPLOSS_ON_EXCHANGE.value - if self.is_open: - logger.info(f'{order.order_type.upper()} is hit for {self}.') - self.close(order.safe_price) - else: - raise ValueError(f'Unknown order type: {order.order_type}') - Trade.commit() - - def close(self, rate: float, *, show_msg: bool = True) -> None: - """ - Sets close_rate to the given rate, calculates total profit - and marks trade as closed - """ - self.close_rate = rate - self.close_date = self.close_date or datetime.utcnow() - self.close_profit = self.calc_profit_ratio() - self.close_profit_abs = self.calc_profit() - self.is_open = False - self.sell_order_status = 'closed' - self.open_order_id = None - if show_msg: - logger.info( - 'Marking %s as closed as the trade is fulfilled and found no open orders for it.', - self - ) - - def update_fee(self, fee_cost: float, fee_currency: Optional[str], fee_rate: Optional[float], - side: str) -> None: - """ - Update Fee parameters. Only acts once per side - """ - if self.enter_side == side and self.fee_open_currency is None: - self.fee_open_cost = fee_cost - self.fee_open_currency = fee_currency - if fee_rate is not None: - self.fee_open = fee_rate - # Assume close-fee will fall into the same fee category and take an educated guess - self.fee_close = fee_rate - elif self.exit_side == side and self.fee_close_currency is None: - self.fee_close_cost = fee_cost - self.fee_close_currency = fee_currency - if fee_rate is not None: - self.fee_close = fee_rate - - def fee_updated(self, side: str) -> bool: - """ - Verify if this side (buy / sell) has already been updated - """ - if self.enter_side == side: - return self.fee_open_currency is not None - elif self.exit_side == side: - return self.fee_close_currency is not None - else: - return False - - def update_order(self, order: Dict) -> None: - Order.update_orders(self.orders, order) - - def get_exit_order_count(self) -> int: - """ - Get amount of failed exiting orders - assumes full exits. - """ - return len([o for o in self.orders if o.ft_order_side == self.exit_side]) - - def _calc_open_trade_value(self) -> float: - """ - Calculate the open_rate including open_fee. - :return: Price in of the open trade incl. Fees - """ - open_trade = Decimal(self.amount) * Decimal(self.open_rate) - fees = open_trade * Decimal(self.fee_open) - if self.is_short: - return float(open_trade - fees) - else: - return float(open_trade + fees) - - def recalc_open_trade_value(self) -> None: - """ - Recalculate open_trade_value. - Must be called whenever open_rate, fee_open or is_short is changed. - """ - self.open_trade_value = self._calc_open_trade_value() - - def calculate_interest(self, interest_rate: Optional[float] = None) -> Decimal: - """ - :param interest_rate: interest_charge for borrowing this coin(optional). - If interest_rate is not set self.interest_rate will be used - """ - zero = Decimal(0.0) - # If nothing was borrowed - if self.trading_mode != TradingMode.MARGIN or self.has_no_leverage: - return zero - - open_date = self.open_date.replace(tzinfo=None) - now = (self.close_date or datetime.now(timezone.utc)).replace(tzinfo=None) - sec_per_hour = Decimal(3600) - total_seconds = Decimal((now - open_date).total_seconds()) - hours = total_seconds/sec_per_hour or zero - - rate = Decimal(interest_rate or self.interest_rate) - borrowed = Decimal(self.borrowed) - - return interest(exchange_name=self.exchange, borrowed=borrowed, rate=rate, hours=hours) - - def _calc_base_close(self, amount: Decimal, rate: Optional[float] = None, - fee: Optional[float] = None) -> Decimal: - - close_trade = Decimal(amount) * Decimal(rate or self.close_rate) # type: ignore - fees = close_trade * Decimal(fee or self.fee_close) - - if self.is_short: - return close_trade + fees - else: - return close_trade - fees - - def calc_close_trade_value(self, rate: Optional[float] = None, - fee: Optional[float] = None, - interest_rate: Optional[float] = None) -> float: - """ - Calculate the close_rate including fee - :param fee: fee to use on the close rate (optional). - If rate is not set self.fee will be used - :param rate: rate to compare with (optional). - If rate is not set self.close_rate will be used - :param interest_rate: interest_charge for borrowing this coin (optional). - If interest_rate is not set self.interest_rate will be used - :return: Price in BTC of the open trade - """ - if rate is None and not self.close_rate: - return 0.0 - - amount = Decimal(self.amount) - trading_mode = self.trading_mode or TradingMode.SPOT - - if trading_mode == TradingMode.SPOT: - return float(self._calc_base_close(amount, rate, fee)) - - elif (trading_mode == TradingMode.MARGIN): - - total_interest = self.calculate_interest(interest_rate) - - if self.is_short: - amount = amount + total_interest - return float(self._calc_base_close(amount, rate, fee)) - else: - # Currency already owned for longs, no need to purchase - return float(self._calc_base_close(amount, rate, fee) - total_interest) - - elif (trading_mode == TradingMode.FUTURES): - funding_fees = self.funding_fees or 0.0 - # Positive funding_fees -> Trade has gained from fees. - # Negative funding_fees -> Trade had to pay the fees. - if self.is_short: - return float(self._calc_base_close(amount, rate, fee)) - funding_fees - else: - return float(self._calc_base_close(amount, rate, fee)) + funding_fees - else: - raise OperationalException( - f"{self.trading_mode.value} trading is not yet available using freqtrade") - - def calc_profit(self, rate: Optional[float] = None, - fee: Optional[float] = None, - interest_rate: Optional[float] = None) -> float: - """ - Calculate the absolute profit in stake currency between Close and Open trade - :param fee: fee to use on the close rate (optional). - If fee is not set self.fee will be used - :param rate: close rate to compare with (optional). - If rate is not set self.close_rate will be used - :param interest_rate: interest_charge for borrowing this coin (optional). - If interest_rate is not set self.interest_rate will be used - :return: profit in stake currency as float - """ - close_trade_value = self.calc_close_trade_value( - rate=(rate or self.close_rate), - fee=(fee or self.fee_close), - interest_rate=(interest_rate or self.interest_rate) - ) - - if self.is_short: - profit = self.open_trade_value - close_trade_value - else: - profit = close_trade_value - self.open_trade_value - return float(f"{profit:.8f}") - - def calc_profit_ratio(self, rate: Optional[float] = None, - fee: Optional[float] = None, - interest_rate: Optional[float] = None) -> float: - """ - Calculates the profit as ratio (including fee). - :param rate: rate to compare with (optional). - If rate is not set self.close_rate will be used - :param fee: fee to use on the close rate (optional). - :param interest_rate: interest_charge for borrowing this coin (optional). - If interest_rate is not set self.interest_rate will be used - :return: profit ratio as float - """ - close_trade_value = self.calc_close_trade_value( - rate=(rate or self.close_rate), - fee=(fee or self.fee_close), - interest_rate=(interest_rate or self.interest_rate) - ) - - short_close_zero = (self.is_short and close_trade_value == 0.0) - long_close_zero = (not self.is_short and self.open_trade_value == 0.0) - leverage = self.leverage or 1.0 - - if (short_close_zero or long_close_zero): - return 0.0 - else: - if self.is_short: - profit_ratio = (1 - (close_trade_value/self.open_trade_value)) * leverage - else: - profit_ratio = ((close_trade_value/self.open_trade_value) - 1) * leverage - - return float(f"{profit_ratio:.8f}") - - def recalc_trade_from_orders(self): - # We need at least 2 entry orders for averaging amounts and rates. - # TODO: this condition could probably be removed - if len(self.select_filled_orders(self.enter_side)) < 2: - self.stake_amount = self.amount * self.open_rate / self.leverage - - # Just in case, still recalc open trade value - self.recalc_open_trade_value() - return - - total_amount = 0.0 - total_stake = 0.0 - for o in self.orders: - if (o.ft_is_open or - (o.ft_order_side != self.enter_side) or - (o.status not in NON_OPEN_EXCHANGE_STATES)): - continue - - tmp_amount = o.safe_amount_after_fee - tmp_price = o.average or o.price - if o.filled is not None: - tmp_amount = o.filled - if tmp_amount > 0.0 and tmp_price is not None: - total_amount += tmp_amount - total_stake += tmp_price * tmp_amount - - if total_amount > 0: - # Leverage not updated, as we don't allow changing leverage through DCA at the moment. - self.open_rate = total_stake / total_amount - self.stake_amount = total_stake / (self.leverage or 1.0) - self.amount = total_amount - self.fee_open_cost = self.fee_open * self.stake_amount - self.recalc_open_trade_value() - if self.stop_loss_pct is not None and self.open_rate is not None: - self.adjust_stop_loss(self.open_rate, self.stop_loss_pct) - - def select_order_by_order_id(self, order_id: str) -> Optional[Order]: - """ - Finds order object by Order id. - :param order_id: Exchange order id - """ - for o in self.orders: - if o.order_id == order_id: - return o - return None - - def select_order( - self, order_side: str = None, is_open: Optional[bool] = None) -> Optional[Order]: - """ - Finds latest order for this orderside and status - :param order_side: ft_order_side of the order (either 'buy', 'sell' or 'stoploss') - :param is_open: Only search for open orders? - :return: latest Order object if it exists, else None - """ - orders = self.orders - if order_side: - orders = [o for o in self.orders if o.ft_order_side == order_side] - if is_open is not None: - orders = [o for o in orders if o.ft_is_open == is_open] - if len(orders) > 0: - return orders[-1] - else: - return None - - def select_filled_orders(self, order_side: Optional[str] = None) -> List['Order']: - """ - Finds filled orders for this orderside. - :param order_side: Side of the order (either 'buy', 'sell', or None) - :return: array of Order objects - """ - return [o for o in self.orders if ((o.ft_order_side == order_side) or (order_side is None)) - and o.ft_is_open is False and - (o.filled or 0) > 0 and - o.status in NON_OPEN_EXCHANGE_STATES] - - @property - def nr_of_successful_entries(self) -> int: - """ - Helper function to count the number of entry orders that have been filled. - :return: int count of entry orders that have been filled for this trade. - """ - - return len(self.select_filled_orders(self.enter_side)) - - @property - def nr_of_successful_exits(self) -> int: - """ - Helper function to count the number of exit orders that have been filled. - :return: int count of exit orders that have been filled for this trade. - """ - return len(self.select_filled_orders(self.exit_side)) - - @property - def nr_of_successful_buys(self) -> int: - """ - Helper function to count the number of buy orders that have been filled. - WARNING: Please use nr_of_successful_entries for short support. - :return: int count of buy orders that have been filled for this trade. - """ - - return len(self.select_filled_orders('buy')) - - @property - def nr_of_successful_sells(self) -> int: - """ - Helper function to count the number of sell orders that have been filled. - WARNING: Please use nr_of_successful_exits for short support. - :return: int count of sell orders that have been filled for this trade. - """ - return len(self.select_filled_orders('sell')) - - @staticmethod - def get_trades_proxy(*, pair: str = None, is_open: bool = None, - open_date: datetime = None, close_date: datetime = None, - ) -> List['LocalTrade']: - """ - Helper function to query Trades. - Returns a List of trades, filtered on the parameters given. - In live mode, converts the filter to a database query and returns all rows - In Backtest mode, uses filters on Trade.trades to get the result. - - :return: unsorted List[Trade] - """ - - # Offline mode - without database - if is_open is not None: - if is_open: - sel_trades = LocalTrade.trades_open - else: - sel_trades = LocalTrade.trades - - else: - # Not used during backtesting, but might be used by a strategy - sel_trades = list(LocalTrade.trades + LocalTrade.trades_open) - - if pair: - sel_trades = [trade for trade in sel_trades if trade.pair == pair] - if open_date: - sel_trades = [trade for trade in sel_trades if trade.open_date > open_date] - if close_date: - sel_trades = [trade for trade in sel_trades if trade.close_date - and trade.close_date > close_date] - - return sel_trades - - @staticmethod - def close_bt_trade(trade): - LocalTrade.trades_open.remove(trade) - LocalTrade.trades.append(trade) - LocalTrade.total_profit += trade.close_profit_abs - - @staticmethod - def add_bt_trade(trade): - if trade.is_open: - LocalTrade.trades_open.append(trade) - else: - LocalTrade.trades.append(trade) - - @staticmethod - def get_open_trades() -> List[Any]: - """ - Query trades from persistence layer - """ - return Trade.get_trades_proxy(is_open=True) - - @staticmethod - def stoploss_reinitialization(desired_stoploss): - """ - Adjust initial Stoploss to desired stoploss for all open trades. - """ - for trade in Trade.get_open_trades(): - logger.info("Found open trade: %s", trade) - - # skip case if trailing-stop changed the stoploss already. - if (trade.stop_loss == trade.initial_stop_loss - and trade.initial_stop_loss_pct != desired_stoploss): - # Stoploss value got changed - - logger.info(f"Stoploss for {trade} needs adjustment...") - # Force reset of stoploss - trade.stop_loss = None - trade.initial_stop_loss_pct = None - trade.adjust_stop_loss(trade.open_rate, desired_stoploss) - logger.info(f"New stoploss: {trade.stop_loss}.") - - -class Trade(_DECL_BASE, LocalTrade): - """ - Trade database model. - Also handles updating and querying trades - - Note: Fields must be aligned with LocalTrade class - """ - __tablename__ = 'trades' - - use_db: bool = True - - id = Column(Integer, primary_key=True) - - orders = relationship("Order", order_by="Order.id", cascade="all, delete-orphan", lazy="joined") - - exchange = Column(String(25), nullable=False) - pair = Column(String(25), nullable=False, index=True) - is_open = Column(Boolean, nullable=False, default=True, index=True) - fee_open = Column(Float, nullable=False, default=0.0) - fee_open_cost = Column(Float, nullable=True) - fee_open_currency = Column(String(25), nullable=True) - fee_close = Column(Float, nullable=False, default=0.0) - fee_close_cost = Column(Float, nullable=True) - fee_close_currency = Column(String(25), nullable=True) - open_rate: float = Column(Float) - open_rate_requested = Column(Float) - # open_trade_value - calculated via _calc_open_trade_value - open_trade_value = Column(Float) - close_rate: Optional[float] = Column(Float) - close_rate_requested = Column(Float) - close_profit = Column(Float) - close_profit_abs = Column(Float) - stake_amount = Column(Float, nullable=False) - amount = Column(Float) - amount_requested = Column(Float) - open_date = Column(DateTime, nullable=False, default=datetime.utcnow) - close_date = Column(DateTime) - open_order_id = Column(String(255)) - # absolute value of the stop loss - stop_loss = Column(Float, nullable=True, default=0.0) - # percentage value of the stop loss - stop_loss_pct = Column(Float, nullable=True) - # absolute value of the initial stop loss - initial_stop_loss = Column(Float, nullable=True, default=0.0) - # percentage value of the initial stop loss - initial_stop_loss_pct = Column(Float, nullable=True) - # stoploss order id which is on exchange - stoploss_order_id = Column(String(255), nullable=True, index=True) - # last update time of the stoploss order on exchange - stoploss_last_update = Column(DateTime, nullable=True) - # absolute value of the highest reached price - max_rate = Column(Float, nullable=True, default=0.0) - # Lowest price reached - min_rate = Column(Float, nullable=True) - sell_reason = Column(String(100), nullable=True) - sell_order_status = Column(String(100), nullable=True) - strategy = Column(String(100), nullable=True) - enter_tag = Column(String(100), nullable=True) - timeframe = Column(Integer, nullable=True) - - trading_mode = Column(Enum(TradingMode), nullable=True) - - # Leverage trading properties - leverage = Column(Float, nullable=True, default=1.0) - is_short = Column(Boolean, nullable=False, default=False) - liquidation_price = Column(Float, nullable=True) - - # Margin Trading Properties - interest_rate = Column(Float, nullable=False, default=0.0) - - # Futures properties - funding_fees = Column(Float, nullable=True, default=None) - - def __init__(self, **kwargs): - super().__init__(**kwargs) - self.recalc_open_trade_value() - - def delete(self) -> None: - - for order in self.orders: - Order.query.session.delete(order) - - Trade.query.session.delete(self) - Trade.commit() - - @staticmethod - def commit(): - Trade.query.session.commit() - - @staticmethod - def get_trades_proxy(*, pair: str = None, is_open: bool = None, - open_date: datetime = None, close_date: datetime = None, - ) -> List['LocalTrade']: - """ - Helper function to query Trades.j - Returns a List of trades, filtered on the parameters given. - In live mode, converts the filter to a database query and returns all rows - In Backtest mode, uses filters on Trade.trades to get the result. - - :return: unsorted List[Trade] - """ - if Trade.use_db: - trade_filter = [] - if pair: - trade_filter.append(Trade.pair == pair) - if open_date: - trade_filter.append(Trade.open_date > open_date) - if close_date: - trade_filter.append(Trade.close_date > close_date) - if is_open is not None: - trade_filter.append(Trade.is_open.is_(is_open)) - return Trade.get_trades(trade_filter).all() - else: - return LocalTrade.get_trades_proxy( - pair=pair, is_open=is_open, - open_date=open_date, - close_date=close_date - ) - - @staticmethod - def get_trades(trade_filter=None) -> Query: - """ - Helper function to query Trades using filters. - NOTE: Not supported in Backtesting. - :param trade_filter: Optional filter to apply to trades - Can be either a Filter object, or a List of filters - e.g. `(trade_filter=[Trade.id == trade_id, Trade.is_open.is_(True),])` - e.g. `(trade_filter=Trade.id == trade_id)` - :return: unsorted query object - """ - if not Trade.use_db: - raise NotImplementedError('`Trade.get_trades()` not supported in backtesting mode.') - if trade_filter is not None: - if not isinstance(trade_filter, list): - trade_filter = [trade_filter] - return Trade.query.filter(*trade_filter) - else: - return Trade.query - - @staticmethod - def get_open_order_trades() -> List['Trade']: - """ - Returns all open trades - NOTE: Not supported in Backtesting. - """ - return Trade.get_trades(Trade.open_order_id.isnot(None)).all() - - @staticmethod - def get_open_trades_without_assigned_fees(): - """ - Returns all open trades which don't have open fees set correctly - NOTE: Not supported in Backtesting. - """ - return Trade.get_trades([Trade.fee_open_currency.is_(None), - Trade.orders.any(), - Trade.is_open.is_(True), - ]).all() - - @staticmethod - def get_closed_trades_without_assigned_fees(): - """ - Returns all closed trades which don't have fees set correctly - NOTE: Not supported in Backtesting. - """ - return Trade.get_trades([Trade.fee_close_currency.is_(None), - Trade.orders.any(), - Trade.is_open.is_(False), - ]).all() - - @staticmethod - def get_total_closed_profit() -> float: - """ - Retrieves total realized profit - """ - if Trade.use_db: - total_profit = Trade.query.with_entities( - func.sum(Trade.close_profit_abs)).filter(Trade.is_open.is_(False)).scalar() - else: - total_profit = sum( - t.close_profit_abs for t in LocalTrade.get_trades_proxy(is_open=False)) - return total_profit or 0 - - @staticmethod - def total_open_trades_stakes() -> float: - """ - Calculates total invested amount in open trades - in stake currency - """ - if Trade.use_db: - total_open_stake_amount = Trade.query.with_entities( - func.sum(Trade.stake_amount)).filter(Trade.is_open.is_(True)).scalar() - else: - total_open_stake_amount = sum( - t.stake_amount for t in LocalTrade.get_trades_proxy(is_open=True)) - return total_open_stake_amount or 0 - - @staticmethod - def get_overall_performance(minutes=None) -> List[Dict[str, Any]]: - """ - Returns List of dicts containing all Trades, including profit and trade count - NOTE: Not supported in Backtesting. - """ - filters = [Trade.is_open.is_(False)] - if minutes: - start_date = datetime.now(timezone.utc) - timedelta(minutes=minutes) - filters.append(Trade.close_date >= start_date) - pair_rates = Trade.query.with_entities( - Trade.pair, - func.sum(Trade.close_profit).label('profit_sum'), - func.sum(Trade.close_profit_abs).label('profit_sum_abs'), - func.count(Trade.pair).label('count') - ).filter(*filters)\ - .group_by(Trade.pair) \ - .order_by(desc('profit_sum_abs')) \ - .all() - return [ - { - 'pair': pair, - 'profit_ratio': profit, - 'profit': round(profit * 100, 2), # Compatibility mode - 'profit_pct': round(profit * 100, 2), - 'profit_abs': profit_abs, - 'count': count - } - for pair, profit, profit_abs, count in pair_rates - ] - - @staticmethod - def get_enter_tag_performance(pair: Optional[str]) -> List[Dict[str, Any]]: - """ - Returns List of dicts containing all Trades, based on buy tag performance - Can either be average for all pairs or a specific pair provided - NOTE: Not supported in Backtesting. - """ - - filters = [Trade.is_open.is_(False)] - if(pair is not None): - filters.append(Trade.pair == pair) - - enter_tag_perf = Trade.query.with_entities( - Trade.enter_tag, - func.sum(Trade.close_profit).label('profit_sum'), - func.sum(Trade.close_profit_abs).label('profit_sum_abs'), - func.count(Trade.pair).label('count') - ).filter(*filters)\ - .group_by(Trade.enter_tag) \ - .order_by(desc('profit_sum_abs')) \ - .all() - - return [ - { - 'enter_tag': enter_tag if enter_tag is not None else "Other", - 'profit_ratio': profit, - 'profit_pct': round(profit * 100, 2), - 'profit_abs': profit_abs, - 'count': count - } - for enter_tag, profit, profit_abs, count in enter_tag_perf - ] - - @staticmethod - def get_sell_reason_performance(pair: Optional[str]) -> List[Dict[str, Any]]: - """ - Returns List of dicts containing all Trades, based on sell reason performance - Can either be average for all pairs or a specific pair provided - NOTE: Not supported in Backtesting. - """ - - filters = [Trade.is_open.is_(False)] - if(pair is not None): - filters.append(Trade.pair == pair) - - sell_tag_perf = Trade.query.with_entities( - Trade.sell_reason, - func.sum(Trade.close_profit).label('profit_sum'), - func.sum(Trade.close_profit_abs).label('profit_sum_abs'), - func.count(Trade.pair).label('count') - ).filter(*filters)\ - .group_by(Trade.sell_reason) \ - .order_by(desc('profit_sum_abs')) \ - .all() - - return [ - { - 'sell_reason': sell_reason if sell_reason is not None else "Other", - 'profit_ratio': profit, - 'profit_pct': round(profit * 100, 2), - 'profit_abs': profit_abs, - 'count': count - } - for sell_reason, profit, profit_abs, count in sell_tag_perf - ] - - @staticmethod - def get_mix_tag_performance(pair: Optional[str]) -> List[Dict[str, Any]]: - """ - Returns List of dicts containing all Trades, based on buy_tag + sell_reason performance - Can either be average for all pairs or a specific pair provided - NOTE: Not supported in Backtesting. - """ - - filters = [Trade.is_open.is_(False)] - if(pair is not None): - filters.append(Trade.pair == pair) - - mix_tag_perf = Trade.query.with_entities( - Trade.id, - Trade.enter_tag, - Trade.sell_reason, - func.sum(Trade.close_profit).label('profit_sum'), - func.sum(Trade.close_profit_abs).label('profit_sum_abs'), - func.count(Trade.pair).label('count') - ).filter(*filters)\ - .group_by(Trade.id) \ - .order_by(desc('profit_sum_abs')) \ - .all() - - return_list: List[Dict] = [] - for id, enter_tag, sell_reason, profit, profit_abs, count in mix_tag_perf: - enter_tag = enter_tag if enter_tag is not None else "Other" - sell_reason = sell_reason if sell_reason is not None else "Other" - - if(sell_reason is not None and enter_tag is not None): - mix_tag = enter_tag + " " + sell_reason - i = 0 - if not any(item["mix_tag"] == mix_tag for item in return_list): - return_list.append({'mix_tag': mix_tag, - 'profit': profit, - 'profit_pct': round(profit * 100, 2), - 'profit_abs': profit_abs, - 'count': count}) - else: - while i < len(return_list): - if return_list[i]["mix_tag"] == mix_tag: - return_list[i] = { - 'mix_tag': mix_tag, - 'profit': profit + return_list[i]["profit"], - 'profit_pct': round(profit + return_list[i]["profit"] * 100, 2), - 'profit_abs': profit_abs + return_list[i]["profit_abs"], - 'count': 1 + return_list[i]["count"]} - i += 1 - - return return_list - - @staticmethod - def get_best_pair(start_date: datetime = datetime.fromtimestamp(0)): - """ - Get best pair with closed trade. - NOTE: Not supported in Backtesting. - :returns: Tuple containing (pair, profit_sum) - """ - best_pair = Trade.query.with_entities( - Trade.pair, func.sum(Trade.close_profit).label('profit_sum') - ).filter(Trade.is_open.is_(False) & (Trade.close_date >= start_date)) \ - .group_by(Trade.pair) \ - .order_by(desc('profit_sum')).first() - return best_pair - - -class PairLock(_DECL_BASE): - """ - Pair Locks database model. - """ - __tablename__ = 'pairlocks' - - id = Column(Integer, primary_key=True) - - pair = Column(String(25), nullable=False, index=True) - reason = Column(String(255), nullable=True) - # Time the pair was locked (start time) - lock_time = Column(DateTime, nullable=False) - # Time until the pair is locked (end time) - lock_end_time = Column(DateTime, nullable=False, index=True) - - active = Column(Boolean, nullable=False, default=True, index=True) - - def __repr__(self): - lock_time = self.lock_time.strftime(DATETIME_PRINT_FORMAT) - lock_end_time = self.lock_end_time.strftime(DATETIME_PRINT_FORMAT) - return (f'PairLock(id={self.id}, pair={self.pair}, lock_time={lock_time}, ' - f'lock_end_time={lock_end_time}, reason={self.reason}, active={self.active})') - - @staticmethod - def query_pair_locks(pair: Optional[str], now: datetime) -> Query: - """ - Get all currently active locks for this pair - :param pair: Pair to check for. Returns all current locks if pair is empty - :param now: Datetime object (generated via datetime.now(timezone.utc)). - """ - filters = [PairLock.lock_end_time > now, - # Only active locks - PairLock.active.is_(True), ] - if pair: - filters.append(PairLock.pair == pair) - return PairLock.query.filter( - *filters - ) - - def to_json(self) -> Dict[str, Any]: - return { - 'id': self.id, - 'pair': self.pair, - 'lock_time': self.lock_time.strftime(DATETIME_PRINT_FORMAT), - 'lock_timestamp': int(self.lock_time.replace(tzinfo=timezone.utc).timestamp() * 1000), - 'lock_end_time': self.lock_end_time.strftime(DATETIME_PRINT_FORMAT), - 'lock_end_timestamp': int(self.lock_end_time.replace(tzinfo=timezone.utc - ).timestamp() * 1000), - 'reason': self.reason, - 'active': self.active, - } diff --git a/freqtrade/persistence/pairlock.py b/freqtrade/persistence/pairlock.py new file mode 100644 index 000000000..926c641b0 --- /dev/null +++ b/freqtrade/persistence/pairlock.py @@ -0,0 +1,70 @@ +from datetime import datetime, timezone +from typing import Any, Dict, Optional + +from sqlalchemy import Boolean, Column, DateTime, Integer, String, or_ +from sqlalchemy.orm import Query + +from freqtrade.constants import DATETIME_PRINT_FORMAT +from freqtrade.persistence.base import _DECL_BASE + + +class PairLock(_DECL_BASE): + """ + Pair Locks database model. + """ + __tablename__ = 'pairlocks' + + id = Column(Integer, primary_key=True) + + pair = Column(String(25), nullable=False, index=True) + # lock direction - long, short or * (for both) + side = Column(String(25), nullable=False, default="*") + reason = Column(String(255), nullable=True) + # Time the pair was locked (start time) + lock_time = Column(DateTime, nullable=False) + # Time until the pair is locked (end time) + lock_end_time = Column(DateTime, nullable=False, index=True) + + active = Column(Boolean, nullable=False, default=True, index=True) + + def __repr__(self): + lock_time = self.lock_time.strftime(DATETIME_PRINT_FORMAT) + lock_end_time = self.lock_end_time.strftime(DATETIME_PRINT_FORMAT) + return ( + f'PairLock(id={self.id}, pair={self.pair}, side={self.side}, lock_time={lock_time}, ' + f'lock_end_time={lock_end_time}, reason={self.reason}, active={self.active})') + + @staticmethod + def query_pair_locks(pair: Optional[str], now: datetime, side: str = '*') -> Query: + """ + Get all currently active locks for this pair + :param pair: Pair to check for. Returns all current locks if pair is empty + :param now: Datetime object (generated via datetime.now(timezone.utc)). + """ + filters = [PairLock.lock_end_time > now, + # Only active locks + PairLock.active.is_(True), ] + if pair: + filters.append(PairLock.pair == pair) + if side != '*': + filters.append(or_(PairLock.side == side, PairLock.side == '*')) + else: + filters.append(PairLock.side == '*') + + return PairLock.query.filter( + *filters + ) + + def to_json(self) -> Dict[str, Any]: + return { + 'id': self.id, + 'pair': self.pair, + 'lock_time': self.lock_time.strftime(DATETIME_PRINT_FORMAT), + 'lock_timestamp': int(self.lock_time.replace(tzinfo=timezone.utc).timestamp() * 1000), + 'lock_end_time': self.lock_end_time.strftime(DATETIME_PRINT_FORMAT), + 'lock_end_timestamp': int(self.lock_end_time.replace(tzinfo=timezone.utc + ).timestamp() * 1000), + 'reason': self.reason, + 'side': self.side, + 'active': self.active, + } diff --git a/freqtrade/persistence/pairlock_middleware.py b/freqtrade/persistence/pairlock_middleware.py index afbd9781b..ec57e91fc 100644 --- a/freqtrade/persistence/pairlock_middleware.py +++ b/freqtrade/persistence/pairlock_middleware.py @@ -31,7 +31,7 @@ class PairLocks(): @staticmethod def lock_pair(pair: str, until: datetime, reason: str = None, *, - now: datetime = None) -> PairLock: + now: datetime = None, side: str = '*') -> PairLock: """ Create PairLock from now to "until". Uses database by default, unless PairLocks.use_db is set to False, @@ -40,12 +40,14 @@ class PairLocks(): :param until: End time of the lock. Will be rounded up to the next candle. :param reason: Reason string that will be shown as reason for the lock :param now: Current timestamp. Used to determine lock start time. + :param side: Side to lock pair, can be 'long', 'short' or '*' """ lock = PairLock( pair=pair, lock_time=now or datetime.now(timezone.utc), lock_end_time=timeframe_to_next_date(PairLocks.timeframe, until), reason=reason, + side=side, active=True ) if PairLocks.use_db: @@ -56,7 +58,8 @@ class PairLocks(): return lock @staticmethod - def get_pair_locks(pair: Optional[str], now: Optional[datetime] = None) -> List[PairLock]: + def get_pair_locks( + pair: Optional[str], now: Optional[datetime] = None, side: str = '*') -> List[PairLock]: """ Get all currently active locks for this pair :param pair: Pair to check for. Returns all current locks if pair is empty @@ -67,26 +70,28 @@ class PairLocks(): now = datetime.now(timezone.utc) if PairLocks.use_db: - return PairLock.query_pair_locks(pair, now).all() + return PairLock.query_pair_locks(pair, now, side).all() else: locks = [lock for lock in PairLocks.locks if ( lock.lock_end_time >= now and lock.active is True and (pair is None or lock.pair == pair) + and (lock.side == '*' or lock.side == side) )] return locks @staticmethod - def get_pair_longest_lock(pair: str, now: Optional[datetime] = None) -> Optional[PairLock]: + def get_pair_longest_lock( + pair: str, now: Optional[datetime] = None, side: str = '*') -> Optional[PairLock]: """ Get the lock that expires the latest for the pair given. """ - locks = PairLocks.get_pair_locks(pair, now) + locks = PairLocks.get_pair_locks(pair, now, side=side) locks = sorted(locks, key=lambda l: l.lock_end_time, reverse=True) return locks[0] if locks else None @staticmethod - def unlock_pair(pair: str, now: Optional[datetime] = None) -> None: + def unlock_pair(pair: str, now: Optional[datetime] = None, side: str = '*') -> None: """ Release all locks for this pair. :param pair: Pair to unlock @@ -97,7 +102,7 @@ class PairLocks(): now = datetime.now(timezone.utc) logger.info(f"Releasing all locks for {pair}.") - locks = PairLocks.get_pair_locks(pair, now) + locks = PairLocks.get_pair_locks(pair, now, side=side) for lock in locks: lock.active = False if PairLocks.use_db: @@ -134,7 +139,7 @@ class PairLocks(): lock.active = False @staticmethod - def is_global_lock(now: Optional[datetime] = None) -> bool: + def is_global_lock(now: Optional[datetime] = None, side: str = '*') -> bool: """ :param now: Datetime object (generated via datetime.now(timezone.utc)). defaults to datetime.now(timezone.utc) @@ -142,10 +147,10 @@ class PairLocks(): if not now: now = datetime.now(timezone.utc) - return len(PairLocks.get_pair_locks('*', now)) > 0 + return len(PairLocks.get_pair_locks('*', now, side)) > 0 @staticmethod - def is_pair_locked(pair: str, now: Optional[datetime] = None) -> bool: + def is_pair_locked(pair: str, now: Optional[datetime] = None, side: str = '*') -> bool: """ :param pair: Pair to check for :param now: Datetime object (generated via datetime.now(timezone.utc)). @@ -154,7 +159,10 @@ class PairLocks(): if not now: now = datetime.now(timezone.utc) - return len(PairLocks.get_pair_locks(pair, now)) > 0 or PairLocks.is_global_lock(now) + return ( + len(PairLocks.get_pair_locks(pair, now, side)) > 0 + or PairLocks.is_global_lock(now, side) + ) @staticmethod def get_all_locks() -> List[PairLock]: diff --git a/freqtrade/persistence/trade_model.py b/freqtrade/persistence/trade_model.py new file mode 100644 index 000000000..358e776e3 --- /dev/null +++ b/freqtrade/persistence/trade_model.py @@ -0,0 +1,1347 @@ +""" +This module contains the class to persist trades into SQLite +""" +import logging +from datetime import datetime, timedelta, timezone +from decimal import Decimal +from typing import Any, Dict, List, Optional + +from sqlalchemy import (Boolean, Column, DateTime, Enum, Float, ForeignKey, Integer, String, + UniqueConstraint, desc, func) +from sqlalchemy.orm import Query, relationship + +from freqtrade.constants import DATETIME_PRINT_FORMAT, NON_OPEN_EXCHANGE_STATES, BuySell, LongShort +from freqtrade.enums import ExitType, TradingMode +from freqtrade.exceptions import DependencyException, OperationalException +from freqtrade.leverage import interest +from freqtrade.persistence.base import _DECL_BASE + + +logger = logging.getLogger(__name__) + + +class Order(_DECL_BASE): + """ + Order database model + Keeps a record of all orders placed on the exchange + + One to many relationship with Trades: + - One trade can have many orders + - One Order can only be associated with one Trade + + Mirrors CCXT Order structure + """ + __tablename__ = 'orders' + # Uniqueness should be ensured over pair, order_id + # its likely that order_id is unique per Pair on some exchanges. + __table_args__ = (UniqueConstraint('ft_pair', 'order_id', name="_order_pair_order_id"),) + + id = Column(Integer, primary_key=True) + ft_trade_id = Column(Integer, ForeignKey('trades.id'), index=True) + + trade = relationship("Trade", back_populates="orders") + + # order_side can only be 'buy', 'sell' or 'stoploss' + ft_order_side: str = Column(String(25), nullable=False) + ft_pair: str = Column(String(25), nullable=False) + ft_is_open = Column(Boolean, nullable=False, default=True, index=True) + + order_id: str = Column(String(255), nullable=False, index=True) + status = Column(String(255), nullable=True) + symbol = Column(String(25), nullable=True) + order_type: str = Column(String(50), nullable=True) + side = Column(String(25), nullable=True) + price = Column(Float, nullable=True) + average = Column(Float, nullable=True) + amount = Column(Float, nullable=True) + filled = Column(Float, nullable=True) + remaining = Column(Float, nullable=True) + cost = Column(Float, nullable=True) + order_date = Column(DateTime, nullable=True, default=datetime.utcnow) + order_filled_date = Column(DateTime, nullable=True) + order_update_date = Column(DateTime, nullable=True) + + ft_fee_base = Column(Float, nullable=True) + + @property + def order_date_utc(self) -> datetime: + """ Order-date with UTC timezoneinfo""" + return self.order_date.replace(tzinfo=timezone.utc) + + @property + def safe_price(self) -> float: + return self.average or self.price + + @property + def safe_filled(self) -> float: + return self.filled or self.amount or 0.0 + + @property + def safe_fee_base(self) -> float: + return self.ft_fee_base or 0.0 + + @property + def safe_amount_after_fee(self) -> float: + return self.safe_filled - self.safe_fee_base + + def __repr__(self): + + return (f'Order(id={self.id}, order_id={self.order_id}, trade_id={self.ft_trade_id}, ' + f'side={self.side}, order_type={self.order_type}, status={self.status})') + + def update_from_ccxt_object(self, order): + """ + Update Order from ccxt response + Only updates if fields are available from ccxt - + """ + if self.order_id != str(order['id']): + raise DependencyException("Order-id's don't match") + + self.status = order.get('status', self.status) + self.symbol = order.get('symbol', self.symbol) + self.order_type = order.get('type', self.order_type) + self.side = order.get('side', self.side) + self.price = order.get('price', self.price) + self.amount = order.get('amount', self.amount) + self.filled = order.get('filled', self.filled) + self.average = order.get('average', self.average) + self.remaining = order.get('remaining', self.remaining) + self.cost = order.get('cost', self.cost) + + if 'timestamp' in order and order['timestamp'] is not None: + self.order_date = datetime.fromtimestamp(order['timestamp'] / 1000, tz=timezone.utc) + + self.ft_is_open = True + if self.status in NON_OPEN_EXCHANGE_STATES: + self.ft_is_open = False + if (order.get('filled', 0.0) or 0.0) > 0: + self.order_filled_date = datetime.now(timezone.utc) + self.order_update_date = datetime.now(timezone.utc) + + def to_json(self, entry_side: str) -> Dict[str, Any]: + return { + 'pair': self.ft_pair, + 'order_id': self.order_id, + 'status': self.status, + 'amount': self.amount, + 'average': round(self.average, 8) if self.average else 0, + 'safe_price': self.safe_price, + 'cost': self.cost if self.cost else 0, + 'filled': self.filled, + 'ft_order_side': self.ft_order_side, + 'is_open': self.ft_is_open, + 'order_date': self.order_date.strftime(DATETIME_PRINT_FORMAT) + if self.order_date else None, + 'order_timestamp': int(self.order_date.replace( + tzinfo=timezone.utc).timestamp() * 1000) if self.order_date else None, + 'order_filled_date': self.order_filled_date.strftime(DATETIME_PRINT_FORMAT) + if self.order_filled_date else None, + 'order_filled_timestamp': int(self.order_filled_date.replace( + tzinfo=timezone.utc).timestamp() * 1000) if self.order_filled_date else None, + 'order_type': self.order_type, + 'price': self.price, + 'ft_is_entry': self.ft_order_side == entry_side, + 'remaining': self.remaining, + } + + def close_bt_order(self, close_date: datetime, trade: 'LocalTrade'): + self.order_filled_date = close_date + self.filled = self.amount + self.status = 'closed' + self.ft_is_open = False + if (self.ft_order_side == trade.entry_side + and len(trade.select_filled_orders(trade.entry_side)) == 1): + trade.open_rate = self.price + trade.recalc_open_trade_value() + trade.adjust_stop_loss(trade.open_rate, trade.stop_loss_pct, refresh=True) + + @staticmethod + def update_orders(orders: List['Order'], order: Dict[str, Any]): + """ + Get all non-closed orders - useful when trying to batch-update orders + """ + if not isinstance(order, dict): + logger.warning(f"{order} is not a valid response object.") + return + + filtered_orders = [o for o in orders if o.order_id == order.get('id')] + if filtered_orders: + oobj = filtered_orders[0] + oobj.update_from_ccxt_object(order) + Order.query.session.commit() + else: + logger.warning(f"Did not find order for {order}.") + + @staticmethod + def parse_from_ccxt_object(order: Dict[str, Any], pair: str, side: str) -> 'Order': + """ + Parse an order from a ccxt object and return a new order Object. + """ + o = Order(order_id=str(order['id']), ft_order_side=side, ft_pair=pair) + + o.update_from_ccxt_object(order) + return o + + @staticmethod + def get_open_orders() -> List['Order']: + """ + Retrieve open orders from the database + :return: List of open orders + """ + return Order.query.filter(Order.ft_is_open.is_(True)).all() + + +class LocalTrade(): + """ + Trade database model. + Used in backtesting - must be aligned to Trade model! + + """ + use_db: bool = False + # Trades container for backtesting + trades: List['LocalTrade'] = [] + trades_open: List['LocalTrade'] = [] + total_profit: float = 0 + + id: int = 0 + + orders: List[Order] = [] + + exchange: str = '' + pair: str = '' + base_currency: str = '' + stake_currency: str = '' + is_open: bool = True + fee_open: float = 0.0 + fee_open_cost: Optional[float] = None + fee_open_currency: str = '' + fee_close: float = 0.0 + fee_close_cost: Optional[float] = None + fee_close_currency: str = '' + open_rate: float = 0.0 + open_rate_requested: Optional[float] = None + # open_trade_value - calculated via _calc_open_trade_value + open_trade_value: float = 0.0 + close_rate: Optional[float] = None + close_rate_requested: Optional[float] = None + close_profit: Optional[float] = None + close_profit_abs: Optional[float] = None + stake_amount: float = 0.0 + amount: float = 0.0 + amount_requested: Optional[float] = None + open_date: datetime + close_date: Optional[datetime] = None + open_order_id: Optional[str] = None + # absolute value of the stop loss + stop_loss: float = 0.0 + # percentage value of the stop loss + stop_loss_pct: float = 0.0 + # absolute value of the initial stop loss + initial_stop_loss: float = 0.0 + # percentage value of the initial stop loss + initial_stop_loss_pct: Optional[float] = None + # stoploss order id which is on exchange + stoploss_order_id: Optional[str] = None + # last update time of the stoploss order on exchange + stoploss_last_update: Optional[datetime] = None + # absolute value of the highest reached price + max_rate: float = 0.0 + # Lowest price reached + min_rate: float = 0.0 + exit_reason: str = '' + exit_order_status: str = '' + strategy: str = '' + enter_tag: Optional[str] = None + timeframe: Optional[int] = None + + trading_mode: TradingMode = TradingMode.SPOT + + # Leverage trading properties + liquidation_price: Optional[float] = None + is_short: bool = False + leverage: float = 1.0 + + # Margin trading properties + interest_rate: float = 0.0 + + # Futures properties + funding_fees: Optional[float] = None + + @property + def buy_tag(self) -> Optional[str]: + """ + Compatibility between buy_tag (old) and enter_tag (new) + Consider buy_tag deprecated + """ + return self.enter_tag + + @property + def has_no_leverage(self) -> bool: + """Returns true if this is a non-leverage, non-short trade""" + return ((self.leverage == 1.0 or self.leverage is None) and not self.is_short) + + @property + def borrowed(self) -> float: + """ + The amount of currency borrowed from the exchange for leverage trades + If a long trade, the amount is in base currency + If a short trade, the amount is in the other currency being traded + """ + if self.has_no_leverage: + return 0.0 + elif not self.is_short: + return (self.amount * self.open_rate) * ((self.leverage - 1) / self.leverage) + else: + return self.amount + + @property + def open_date_utc(self): + return self.open_date.replace(tzinfo=timezone.utc) + + @property + def close_date_utc(self): + return self.close_date.replace(tzinfo=timezone.utc) + + @property + def enter_side(self) -> str: + """ DEPRECATED, please use entry_side instead""" + # TODO: Please remove me after 2022.5 + return self.entry_side + + @property + def entry_side(self) -> str: + if self.is_short: + return "sell" + else: + return "buy" + + @property + def exit_side(self) -> BuySell: + if self.is_short: + return "buy" + else: + return "sell" + + @property + def trade_direction(self) -> LongShort: + if self.is_short: + return "short" + else: + return "long" + + @property + def safe_base_currency(self) -> str: + """ + Compatibility layer for asset - which can be empty for old trades. + """ + try: + return self.base_currency or self.pair.split('/')[0] + except IndexError: + return '' + + @property + def safe_quote_currency(self) -> str: + """ + Compatibility layer for asset - which can be empty for old trades. + """ + try: + return self.stake_currency or self.pair.split('/')[1].split(':')[0] + except IndexError: + return '' + + def __init__(self, **kwargs): + for key in kwargs: + setattr(self, key, kwargs[key]) + self.recalc_open_trade_value() + if self.trading_mode == TradingMode.MARGIN and self.interest_rate is None: + raise OperationalException( + f"{self.trading_mode.value} trading requires param interest_rate on trades") + + def __repr__(self): + open_since = self.open_date.strftime(DATETIME_PRINT_FORMAT) if self.is_open else 'closed' + + return ( + f'Trade(id={self.id}, pair={self.pair}, amount={self.amount:.8f}, ' + 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})' + ) + + def to_json(self) -> Dict[str, Any]: + filled_orders = self.select_filled_orders() + orders = [order.to_json(self.entry_side) for order in filled_orders] + + return { + 'trade_id': self.id, + 'pair': self.pair, + 'base_currency': self.safe_base_currency, + 'quote_currency': self.safe_quote_currency, + 'is_open': self.is_open, + 'exchange': self.exchange, + 'amount': round(self.amount, 8), + 'amount_requested': round(self.amount_requested, 8) if self.amount_requested else None, + 'stake_amount': round(self.stake_amount, 8), + 'strategy': self.strategy, + 'buy_tag': self.enter_tag, + 'enter_tag': self.enter_tag, + 'timeframe': self.timeframe, + + 'fee_open': self.fee_open, + 'fee_open_cost': self.fee_open_cost, + 'fee_open_currency': self.fee_open_currency, + 'fee_close': self.fee_close, + 'fee_close_cost': self.fee_close_cost, + 'fee_close_currency': self.fee_close_currency, + + 'open_date': self.open_date.strftime(DATETIME_PRINT_FORMAT), + 'open_timestamp': int(self.open_date.replace(tzinfo=timezone.utc).timestamp() * 1000), + 'open_rate': self.open_rate, + 'open_rate_requested': self.open_rate_requested, + 'open_trade_value': round(self.open_trade_value, 8), + + 'close_date': (self.close_date.strftime(DATETIME_PRINT_FORMAT) + if self.close_date else None), + 'close_timestamp': int(self.close_date.replace( + tzinfo=timezone.utc).timestamp() * 1000) if self.close_date else None, + 'close_rate': self.close_rate, + 'close_rate_requested': self.close_rate_requested, + 'close_profit': self.close_profit, # Deprecated + 'close_profit_pct': round(self.close_profit * 100, 2) if self.close_profit else None, + 'close_profit_abs': self.close_profit_abs, # Deprecated + + 'trade_duration_s': (int((self.close_date_utc - self.open_date_utc).total_seconds()) + if self.close_date else None), + 'trade_duration': (int((self.close_date_utc - self.open_date_utc).total_seconds() // 60) + if self.close_date else None), + + 'profit_ratio': self.close_profit, + 'profit_pct': round(self.close_profit * 100, 2) if self.close_profit else None, + 'profit_abs': self.close_profit_abs, + + 'sell_reason': self.exit_reason, # Deprecated + 'exit_reason': self.exit_reason, + 'exit_order_status': self.exit_order_status, + 'stop_loss_abs': self.stop_loss, + 'stop_loss_ratio': self.stop_loss_pct if self.stop_loss_pct else None, + 'stop_loss_pct': (self.stop_loss_pct * 100) if self.stop_loss_pct else None, + 'stoploss_order_id': self.stoploss_order_id, + 'stoploss_last_update': (self.stoploss_last_update.strftime(DATETIME_PRINT_FORMAT) + if self.stoploss_last_update else None), + 'stoploss_last_update_timestamp': int(self.stoploss_last_update.replace( + tzinfo=timezone.utc).timestamp() * 1000) if self.stoploss_last_update else None, + 'initial_stop_loss_abs': self.initial_stop_loss, + 'initial_stop_loss_ratio': (self.initial_stop_loss_pct + if self.initial_stop_loss_pct else None), + 'initial_stop_loss_pct': (self.initial_stop_loss_pct * 100 + if self.initial_stop_loss_pct else None), + 'min_rate': self.min_rate, + 'max_rate': self.max_rate, + + 'leverage': self.leverage, + 'interest_rate': self.interest_rate, + 'liquidation_price': self.liquidation_price, + 'is_short': self.is_short, + 'trading_mode': self.trading_mode, + 'funding_fees': self.funding_fees, + 'open_order_id': self.open_order_id, + 'orders': orders, + } + + @staticmethod + def reset_trades() -> None: + """ + Resets all trades. Only active for backtesting mode. + """ + LocalTrade.trades = [] + LocalTrade.trades_open = [] + LocalTrade.total_profit = 0 + + def adjust_min_max_rates(self, current_price: float, current_price_low: float) -> None: + """ + Adjust the max_rate and min_rate. + """ + self.max_rate = max(current_price, self.max_rate or self.open_rate) + self.min_rate = min(current_price_low, self.min_rate or self.open_rate) + + def set_isolated_liq(self, liquidation_price: Optional[float]): + """ + Method you should use to set self.liquidation price. + Assures stop_loss is not passed the liquidation price + """ + if not liquidation_price: + return + self.liquidation_price = liquidation_price + + def _set_stop_loss(self, stop_loss: float, percent: float): + """ + Method you should use to set self.stop_loss. + Assures stop_loss is not passed the liquidation price + """ + if self.liquidation_price is not None: + if self.is_short: + sl = min(stop_loss, self.liquidation_price) + else: + sl = max(stop_loss, self.liquidation_price) + else: + sl = stop_loss + + if not self.stop_loss: + self.initial_stop_loss = sl + self.stop_loss = sl + + self.stop_loss_pct = -1 * abs(percent) + self.stoploss_last_update = datetime.utcnow() + + def adjust_stop_loss(self, current_price: float, stoploss: float, + initial: bool = False, refresh: bool = False) -> None: + """ + This adjusts the stop loss to it's most recently observed setting + :param current_price: Current rate the asset is traded + :param stoploss: Stoploss as factor (sample -0.05 -> -5% below current price). + :param initial: Called to initiate stop_loss. + Skips everything if self.stop_loss is already set. + """ + if initial and not (self.stop_loss is None or self.stop_loss == 0): + # Don't modify if called with initial and nothing to do + return + refresh = True if refresh and self.nr_of_successful_entries == 1 else False + + leverage = self.leverage or 1.0 + if self.is_short: + new_loss = float(current_price * (1 + abs(stoploss / leverage))) + # If trading with leverage, don't set the stoploss below the liquidation price + if self.liquidation_price: + new_loss = min(self.liquidation_price, new_loss) + else: + new_loss = float(current_price * (1 - abs(stoploss / leverage))) + # If trading with leverage, don't set the stoploss below the liquidation price + if self.liquidation_price: + new_loss = max(self.liquidation_price, new_loss) + + # no stop loss assigned yet + if self.initial_stop_loss_pct is None or refresh: + self._set_stop_loss(new_loss, stoploss) + self.initial_stop_loss = new_loss + self.initial_stop_loss_pct = -1 * abs(stoploss) + + # evaluate if the stop loss needs to be updated + else: + + higher_stop = new_loss > self.stop_loss + lower_stop = new_loss < self.stop_loss + + # stop losses only walk up, never down!, + # ? But adding more to a leveraged trade would create a lower liquidation price, + # ? decreasing the minimum stoploss + if (higher_stop and not self.is_short) or (lower_stop and self.is_short): + logger.debug(f"{self.pair} - Adjusting stoploss...") + self._set_stop_loss(new_loss, stoploss) + else: + logger.debug(f"{self.pair} - Keeping current stoploss...") + + logger.debug( + f"{self.pair} - Stoploss adjusted. current_price={current_price:.8f}, " + f"open_rate={self.open_rate:.8f}, max_rate={self.max_rate or self.open_rate:.8f}, " + f"initial_stop_loss={self.initial_stop_loss:.8f}, " + f"stop_loss={self.stop_loss:.8f}. " + f"Trailing stoploss saved us: " + f"{float(self.stop_loss) - float(self.initial_stop_loss):.8f}.") + + def update_trade(self, order: Order) -> None: + """ + Updates this entity with amount and actual open/close rates. + :param order: order retrieved by exchange.fetch_order() + :return: None + """ + + # Ignore open and cancelled orders + if order.status == 'open' or order.safe_price is None: + return + + logger.info(f'Updating trade (id={self.id}) ...') + + if order.ft_order_side == self.entry_side: + # Update open rate and actual amount + self.open_rate = order.safe_price + self.amount = order.safe_amount_after_fee + if self.is_open: + payment = "SELL" if self.is_short else "BUY" + logger.info(f'{order.order_type.upper()}_{payment} has been fulfilled for {self}.') + self.open_order_id = None + self.recalc_trade_from_orders() + elif order.ft_order_side == self.exit_side: + if self.is_open: + payment = "BUY" if self.is_short else "SELL" + # * On margin shorts, you buy a little bit more than the amount (amount + interest) + logger.info(f'{order.order_type.upper()}_{payment} has been fulfilled for {self}.') + self.close(order.safe_price) + elif order.ft_order_side == 'stoploss': + self.stoploss_order_id = None + self.close_rate_requested = self.stop_loss + self.exit_reason = ExitType.STOPLOSS_ON_EXCHANGE.value + if self.is_open: + logger.info(f'{order.order_type.upper()} is hit for {self}.') + self.close(order.safe_price) + else: + raise ValueError(f'Unknown order type: {order.order_type}') + Trade.commit() + + def close(self, rate: float, *, show_msg: bool = True) -> None: + """ + Sets close_rate to the given rate, calculates total profit + and marks trade as closed + """ + self.close_rate = rate + self.close_date = self.close_date or datetime.utcnow() + self.close_profit = self.calc_profit_ratio() + self.close_profit_abs = self.calc_profit() + self.is_open = False + self.exit_order_status = 'closed' + self.open_order_id = None + if show_msg: + logger.info( + 'Marking %s as closed as the trade is fulfilled and found no open orders for it.', + self + ) + + def update_fee(self, fee_cost: float, fee_currency: Optional[str], fee_rate: Optional[float], + side: str) -> None: + """ + Update Fee parameters. Only acts once per side + """ + if self.entry_side == side and self.fee_open_currency is None: + self.fee_open_cost = fee_cost + self.fee_open_currency = fee_currency + if fee_rate is not None: + self.fee_open = fee_rate + # Assume close-fee will fall into the same fee category and take an educated guess + self.fee_close = fee_rate + elif self.exit_side == side and self.fee_close_currency is None: + self.fee_close_cost = fee_cost + self.fee_close_currency = fee_currency + if fee_rate is not None: + self.fee_close = fee_rate + + def fee_updated(self, side: str) -> bool: + """ + Verify if this side (buy / sell) has already been updated + """ + if self.entry_side == side: + return self.fee_open_currency is not None + elif self.exit_side == side: + return self.fee_close_currency is not None + else: + return False + + def update_order(self, order: Dict) -> None: + Order.update_orders(self.orders, order) + + def get_exit_order_count(self) -> int: + """ + Get amount of failed exiting orders + assumes full exits. + """ + return len([o for o in self.orders if o.ft_order_side == self.exit_side]) + + def _calc_open_trade_value(self) -> float: + """ + Calculate the open_rate including open_fee. + :return: Price in of the open trade incl. Fees + """ + open_trade = Decimal(self.amount) * Decimal(self.open_rate) + fees = open_trade * Decimal(self.fee_open) + if self.is_short: + return float(open_trade - fees) + else: + return float(open_trade + fees) + + def recalc_open_trade_value(self) -> None: + """ + Recalculate open_trade_value. + Must be called whenever open_rate, fee_open is changed. + """ + self.open_trade_value = self._calc_open_trade_value() + + def calculate_interest(self, interest_rate: Optional[float] = None) -> Decimal: + """ + :param interest_rate: interest_charge for borrowing this coin(optional). + If interest_rate is not set self.interest_rate will be used + """ + zero = Decimal(0.0) + # If nothing was borrowed + if self.trading_mode != TradingMode.MARGIN or self.has_no_leverage: + return zero + + open_date = self.open_date.replace(tzinfo=None) + now = (self.close_date or datetime.now(timezone.utc)).replace(tzinfo=None) + sec_per_hour = Decimal(3600) + total_seconds = Decimal((now - open_date).total_seconds()) + hours = total_seconds / sec_per_hour or zero + + rate = Decimal(interest_rate or self.interest_rate) + borrowed = Decimal(self.borrowed) + + return interest(exchange_name=self.exchange, borrowed=borrowed, rate=rate, hours=hours) + + def _calc_base_close(self, amount: Decimal, rate: Optional[float] = None, + fee: Optional[float] = None) -> Decimal: + + close_trade = Decimal(amount) * Decimal(rate or self.close_rate) # type: ignore + fees = close_trade * Decimal(fee or self.fee_close) + + if self.is_short: + return close_trade + fees + else: + return close_trade - fees + + def calc_close_trade_value(self, rate: Optional[float] = None, + fee: Optional[float] = None, + interest_rate: Optional[float] = None) -> float: + """ + Calculate the close_rate including fee + :param fee: fee to use on the close rate (optional). + If rate is not set self.fee will be used + :param rate: rate to compare with (optional). + If rate is not set self.close_rate will be used + :param interest_rate: interest_charge for borrowing this coin (optional). + If interest_rate is not set self.interest_rate will be used + :return: Price in BTC of the open trade + """ + if rate is None and not self.close_rate: + return 0.0 + + amount = Decimal(self.amount) + trading_mode = self.trading_mode or TradingMode.SPOT + + if trading_mode == TradingMode.SPOT: + return float(self._calc_base_close(amount, rate, fee)) + + elif (trading_mode == TradingMode.MARGIN): + + total_interest = self.calculate_interest(interest_rate) + + if self.is_short: + amount = amount + total_interest + return float(self._calc_base_close(amount, rate, fee)) + else: + # Currency already owned for longs, no need to purchase + return float(self._calc_base_close(amount, rate, fee) - total_interest) + + elif (trading_mode == TradingMode.FUTURES): + funding_fees = self.funding_fees or 0.0 + # Positive funding_fees -> Trade has gained from fees. + # Negative funding_fees -> Trade had to pay the fees. + if self.is_short: + return float(self._calc_base_close(amount, rate, fee)) - funding_fees + else: + return float(self._calc_base_close(amount, rate, fee)) + funding_fees + else: + raise OperationalException( + f"{self.trading_mode.value} trading is not yet available using freqtrade") + + def calc_profit(self, rate: Optional[float] = None, + fee: Optional[float] = None, + interest_rate: Optional[float] = None) -> float: + """ + Calculate the absolute profit in stake currency between Close and Open trade + :param fee: fee to use on the close rate (optional). + If fee is not set self.fee will be used + :param rate: close rate to compare with (optional). + If rate is not set self.close_rate will be used + :param interest_rate: interest_charge for borrowing this coin (optional). + If interest_rate is not set self.interest_rate will be used + :return: profit in stake currency as float + """ + close_trade_value = self.calc_close_trade_value( + rate=(rate or self.close_rate), + fee=(fee or self.fee_close), + interest_rate=(interest_rate or self.interest_rate) + ) + + if self.is_short: + profit = self.open_trade_value - close_trade_value + else: + profit = close_trade_value - self.open_trade_value + return float(f"{profit:.8f}") + + def calc_profit_ratio(self, rate: Optional[float] = None, + fee: Optional[float] = None, + interest_rate: Optional[float] = None) -> float: + """ + Calculates the profit as ratio (including fee). + :param rate: rate to compare with (optional). + If rate is not set self.close_rate will be used + :param fee: fee to use on the close rate (optional). + :param interest_rate: interest_charge for borrowing this coin (optional). + If interest_rate is not set self.interest_rate will be used + :return: profit ratio as float + """ + close_trade_value = self.calc_close_trade_value( + rate=(rate or self.close_rate), + fee=(fee or self.fee_close), + interest_rate=(interest_rate or self.interest_rate) + ) + + short_close_zero = (self.is_short and close_trade_value == 0.0) + long_close_zero = (not self.is_short and self.open_trade_value == 0.0) + leverage = self.leverage or 1.0 + + if (short_close_zero or long_close_zero): + return 0.0 + else: + if self.is_short: + profit_ratio = (1 - (close_trade_value / self.open_trade_value)) * leverage + else: + profit_ratio = ((close_trade_value / self.open_trade_value) - 1) * leverage + + return float(f"{profit_ratio:.8f}") + + def recalc_trade_from_orders(self): + # We need at least 2 entry orders for averaging amounts and rates. + # TODO: this condition could probably be removed + if len(self.select_filled_orders(self.entry_side)) < 2: + self.stake_amount = self.amount * self.open_rate / self.leverage + + # Just in case, still recalc open trade value + self.recalc_open_trade_value() + return + + total_amount = 0.0 + total_stake = 0.0 + for o in self.orders: + if (o.ft_is_open or + (o.ft_order_side != self.entry_side) or + (o.status not in NON_OPEN_EXCHANGE_STATES)): + continue + + tmp_amount = o.safe_amount_after_fee + tmp_price = o.average or o.price + if o.filled is not None: + tmp_amount = o.filled + if tmp_amount > 0.0 and tmp_price is not None: + total_amount += tmp_amount + total_stake += tmp_price * tmp_amount + + if total_amount > 0: + # Leverage not updated, as we don't allow changing leverage through DCA at the moment. + self.open_rate = total_stake / total_amount + self.stake_amount = total_stake / (self.leverage or 1.0) + self.amount = total_amount + self.fee_open_cost = self.fee_open * self.stake_amount + self.recalc_open_trade_value() + if self.stop_loss_pct is not None and self.open_rate is not None: + self.adjust_stop_loss(self.open_rate, self.stop_loss_pct) + + def select_order_by_order_id(self, order_id: str) -> Optional[Order]: + """ + Finds order object by Order id. + :param order_id: Exchange order id + """ + for o in self.orders: + if o.order_id == order_id: + return o + return None + + def select_order( + self, order_side: str = None, is_open: Optional[bool] = None) -> Optional[Order]: + """ + Finds latest order for this orderside and status + :param order_side: ft_order_side of the order (either 'buy', 'sell' or 'stoploss') + :param is_open: Only search for open orders? + :return: latest Order object if it exists, else None + """ + orders = self.orders + if order_side: + orders = [o for o in self.orders if o.ft_order_side == order_side] + if is_open is not None: + orders = [o for o in orders if o.ft_is_open == is_open] + if len(orders) > 0: + return orders[-1] + else: + return None + + def select_filled_orders(self, order_side: Optional[str] = None) -> List['Order']: + """ + Finds filled orders for this orderside. + :param order_side: Side of the order (either 'buy', 'sell', or None) + :return: array of Order objects + """ + return [o for o in self.orders if ((o.ft_order_side == order_side) or (order_side is None)) + and o.ft_is_open is False and + (o.filled or 0) > 0 and + o.status in NON_OPEN_EXCHANGE_STATES] + + @property + def nr_of_successful_entries(self) -> int: + """ + Helper function to count the number of entry orders that have been filled. + :return: int count of entry orders that have been filled for this trade. + """ + + return len(self.select_filled_orders(self.entry_side)) + + @property + def nr_of_successful_exits(self) -> int: + """ + Helper function to count the number of exit orders that have been filled. + :return: int count of exit orders that have been filled for this trade. + """ + return len(self.select_filled_orders(self.exit_side)) + + @property + def nr_of_successful_buys(self) -> int: + """ + Helper function to count the number of buy orders that have been filled. + WARNING: Please use nr_of_successful_entries for short support. + :return: int count of buy orders that have been filled for this trade. + """ + + return len(self.select_filled_orders('buy')) + + @property + def nr_of_successful_sells(self) -> int: + """ + Helper function to count the number of sell orders that have been filled. + WARNING: Please use nr_of_successful_exits for short support. + :return: int count of sell orders that have been filled for this trade. + """ + return len(self.select_filled_orders('sell')) + + @property + def sell_reason(self) -> str: + """ DEPRECATED! Please use exit_reason instead.""" + return self.exit_reason + + @staticmethod + def get_trades_proxy(*, pair: str = None, is_open: bool = None, + open_date: datetime = None, close_date: datetime = None, + ) -> List['LocalTrade']: + """ + Helper function to query Trades. + Returns a List of trades, filtered on the parameters given. + In live mode, converts the filter to a database query and returns all rows + In Backtest mode, uses filters on Trade.trades to get the result. + + :return: unsorted List[Trade] + """ + + # Offline mode - without database + if is_open is not None: + if is_open: + sel_trades = LocalTrade.trades_open + else: + sel_trades = LocalTrade.trades + + else: + # Not used during backtesting, but might be used by a strategy + sel_trades = list(LocalTrade.trades + LocalTrade.trades_open) + + if pair: + sel_trades = [trade for trade in sel_trades if trade.pair == pair] + if open_date: + sel_trades = [trade for trade in sel_trades if trade.open_date > open_date] + if close_date: + sel_trades = [trade for trade in sel_trades if trade.close_date + and trade.close_date > close_date] + + return sel_trades + + @staticmethod + def close_bt_trade(trade): + LocalTrade.trades_open.remove(trade) + LocalTrade.trades.append(trade) + LocalTrade.total_profit += trade.close_profit_abs + + @staticmethod + def add_bt_trade(trade): + if trade.is_open: + LocalTrade.trades_open.append(trade) + else: + LocalTrade.trades.append(trade) + + @staticmethod + def get_open_trades() -> List[Any]: + """ + Query trades from persistence layer + """ + return Trade.get_trades_proxy(is_open=True) + + @staticmethod + def stoploss_reinitialization(desired_stoploss): + """ + Adjust initial Stoploss to desired stoploss for all open trades. + """ + for trade in Trade.get_open_trades(): + logger.info("Found open trade: %s", trade) + + # skip case if trailing-stop changed the stoploss already. + if (trade.stop_loss == trade.initial_stop_loss + and trade.initial_stop_loss_pct != desired_stoploss): + # Stoploss value got changed + + logger.info(f"Stoploss for {trade} needs adjustment...") + # Force reset of stoploss + trade.stop_loss = None + trade.initial_stop_loss_pct = None + trade.adjust_stop_loss(trade.open_rate, desired_stoploss) + logger.info(f"New stoploss: {trade.stop_loss}.") + + +class Trade(_DECL_BASE, LocalTrade): + """ + Trade database model. + Also handles updating and querying trades + + Note: Fields must be aligned with LocalTrade class + """ + __tablename__ = 'trades' + + use_db: bool = True + + id = Column(Integer, primary_key=True) + + orders = relationship("Order", order_by="Order.id", cascade="all, delete-orphan", lazy="joined") + + exchange = Column(String(25), nullable=False) + pair = Column(String(25), nullable=False, index=True) + base_currency = Column(String(25), nullable=True) + stake_currency = Column(String(25), nullable=True) + is_open = Column(Boolean, nullable=False, default=True, index=True) + fee_open = Column(Float, nullable=False, default=0.0) + fee_open_cost = Column(Float, nullable=True) + fee_open_currency = Column(String(25), nullable=True) + fee_close = Column(Float, nullable=False, default=0.0) + fee_close_cost = Column(Float, nullable=True) + fee_close_currency = Column(String(25), nullable=True) + open_rate: float = Column(Float) + open_rate_requested = Column(Float) + # open_trade_value - calculated via _calc_open_trade_value + open_trade_value = Column(Float) + close_rate: Optional[float] = Column(Float) + close_rate_requested = Column(Float) + close_profit = Column(Float) + close_profit_abs = Column(Float) + stake_amount = Column(Float, nullable=False) + amount = Column(Float) + amount_requested = Column(Float) + open_date = Column(DateTime, nullable=False, default=datetime.utcnow) + close_date = Column(DateTime) + open_order_id = Column(String(255)) + # absolute value of the stop loss + stop_loss = Column(Float, nullable=True, default=0.0) + # percentage value of the stop loss + stop_loss_pct = Column(Float, nullable=True) + # absolute value of the initial stop loss + initial_stop_loss = Column(Float, nullable=True, default=0.0) + # percentage value of the initial stop loss + initial_stop_loss_pct = Column(Float, nullable=True) + # stoploss order id which is on exchange + stoploss_order_id = Column(String(255), nullable=True, index=True) + # last update time of the stoploss order on exchange + stoploss_last_update = Column(DateTime, nullable=True) + # absolute value of the highest reached price + max_rate = Column(Float, nullable=True, default=0.0) + # Lowest price reached + min_rate = Column(Float, nullable=True) + exit_reason = Column(String(100), nullable=True) + exit_order_status = Column(String(100), nullable=True) + strategy = Column(String(100), nullable=True) + enter_tag = Column(String(100), nullable=True) + timeframe = Column(Integer, nullable=True) + + trading_mode = Column(Enum(TradingMode), nullable=True) + + # Leverage trading properties + leverage = Column(Float, nullable=True, default=1.0) + is_short = Column(Boolean, nullable=False, default=False) + liquidation_price = Column(Float, nullable=True) + + # Margin Trading Properties + interest_rate = Column(Float, nullable=False, default=0.0) + + # Futures properties + funding_fees = Column(Float, nullable=True, default=None) + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.recalc_open_trade_value() + + def delete(self) -> None: + + for order in self.orders: + Order.query.session.delete(order) + + Trade.query.session.delete(self) + Trade.commit() + + @staticmethod + def commit(): + Trade.query.session.commit() + + @staticmethod + def get_trades_proxy(*, pair: str = None, is_open: bool = None, + open_date: datetime = None, close_date: datetime = None, + ) -> List['LocalTrade']: + """ + Helper function to query Trades.j + Returns a List of trades, filtered on the parameters given. + In live mode, converts the filter to a database query and returns all rows + In Backtest mode, uses filters on Trade.trades to get the result. + + :return: unsorted List[Trade] + """ + if Trade.use_db: + trade_filter = [] + if pair: + trade_filter.append(Trade.pair == pair) + if open_date: + trade_filter.append(Trade.open_date > open_date) + if close_date: + trade_filter.append(Trade.close_date > close_date) + if is_open is not None: + trade_filter.append(Trade.is_open.is_(is_open)) + return Trade.get_trades(trade_filter).all() + else: + return LocalTrade.get_trades_proxy( + pair=pair, is_open=is_open, + open_date=open_date, + close_date=close_date + ) + + @staticmethod + def get_trades(trade_filter=None) -> Query: + """ + Helper function to query Trades using filters. + NOTE: Not supported in Backtesting. + :param trade_filter: Optional filter to apply to trades + Can be either a Filter object, or a List of filters + e.g. `(trade_filter=[Trade.id == trade_id, Trade.is_open.is_(True),])` + e.g. `(trade_filter=Trade.id == trade_id)` + :return: unsorted query object + """ + if not Trade.use_db: + raise NotImplementedError('`Trade.get_trades()` not supported in backtesting mode.') + if trade_filter is not None: + if not isinstance(trade_filter, list): + trade_filter = [trade_filter] + return Trade.query.filter(*trade_filter) + else: + return Trade.query + + @staticmethod + def get_open_order_trades() -> List['Trade']: + """ + Returns all open trades + NOTE: Not supported in Backtesting. + """ + return Trade.get_trades(Trade.open_order_id.isnot(None)).all() + + @staticmethod + def get_open_trades_without_assigned_fees(): + """ + Returns all open trades which don't have open fees set correctly + NOTE: Not supported in Backtesting. + """ + return Trade.get_trades([Trade.fee_open_currency.is_(None), + Trade.orders.any(), + Trade.is_open.is_(True), + ]).all() + + @staticmethod + def get_closed_trades_without_assigned_fees(): + """ + Returns all closed trades which don't have fees set correctly + NOTE: Not supported in Backtesting. + """ + return Trade.get_trades([Trade.fee_close_currency.is_(None), + Trade.orders.any(), + Trade.is_open.is_(False), + ]).all() + + @staticmethod + def get_total_closed_profit() -> float: + """ + Retrieves total realized profit + """ + if Trade.use_db: + total_profit = Trade.query.with_entities( + func.sum(Trade.close_profit_abs)).filter(Trade.is_open.is_(False)).scalar() + else: + total_profit = sum( + t.close_profit_abs for t in LocalTrade.get_trades_proxy(is_open=False)) + return total_profit or 0 + + @staticmethod + def total_open_trades_stakes() -> float: + """ + Calculates total invested amount in open trades + in stake currency + """ + if Trade.use_db: + total_open_stake_amount = Trade.query.with_entities( + func.sum(Trade.stake_amount)).filter(Trade.is_open.is_(True)).scalar() + else: + total_open_stake_amount = sum( + t.stake_amount for t in LocalTrade.get_trades_proxy(is_open=True)) + return total_open_stake_amount or 0 + + @staticmethod + def get_overall_performance(minutes=None) -> List[Dict[str, Any]]: + """ + Returns List of dicts containing all Trades, including profit and trade count + NOTE: Not supported in Backtesting. + """ + filters = [Trade.is_open.is_(False)] + if minutes: + start_date = datetime.now(timezone.utc) - timedelta(minutes=minutes) + filters.append(Trade.close_date >= start_date) + pair_rates = Trade.query.with_entities( + Trade.pair, + func.sum(Trade.close_profit).label('profit_sum'), + func.sum(Trade.close_profit_abs).label('profit_sum_abs'), + func.count(Trade.pair).label('count') + ).filter(*filters)\ + .group_by(Trade.pair) \ + .order_by(desc('profit_sum_abs')) \ + .all() + return [ + { + 'pair': pair, + 'profit_ratio': profit, + 'profit': round(profit * 100, 2), # Compatibility mode + 'profit_pct': round(profit * 100, 2), + 'profit_abs': profit_abs, + 'count': count + } + for pair, profit, profit_abs, count in pair_rates + ] + + @staticmethod + def get_enter_tag_performance(pair: Optional[str]) -> List[Dict[str, Any]]: + """ + Returns List of dicts containing all Trades, based on buy tag performance + Can either be average for all pairs or a specific pair provided + NOTE: Not supported in Backtesting. + """ + + filters = [Trade.is_open.is_(False)] + if(pair is not None): + filters.append(Trade.pair == pair) + + enter_tag_perf = Trade.query.with_entities( + Trade.enter_tag, + func.sum(Trade.close_profit).label('profit_sum'), + func.sum(Trade.close_profit_abs).label('profit_sum_abs'), + func.count(Trade.pair).label('count') + ).filter(*filters)\ + .group_by(Trade.enter_tag) \ + .order_by(desc('profit_sum_abs')) \ + .all() + + return [ + { + 'enter_tag': enter_tag if enter_tag is not None else "Other", + 'profit_ratio': profit, + 'profit_pct': round(profit * 100, 2), + 'profit_abs': profit_abs, + 'count': count + } + for enter_tag, profit, profit_abs, count in enter_tag_perf + ] + + @staticmethod + def get_exit_reason_performance(pair: Optional[str]) -> List[Dict[str, Any]]: + """ + Returns List of dicts containing all Trades, based on exit reason performance + Can either be average for all pairs or a specific pair provided + NOTE: Not supported in Backtesting. + """ + + filters = [Trade.is_open.is_(False)] + if(pair is not None): + filters.append(Trade.pair == pair) + + sell_tag_perf = Trade.query.with_entities( + Trade.exit_reason, + func.sum(Trade.close_profit).label('profit_sum'), + func.sum(Trade.close_profit_abs).label('profit_sum_abs'), + func.count(Trade.pair).label('count') + ).filter(*filters)\ + .group_by(Trade.exit_reason) \ + .order_by(desc('profit_sum_abs')) \ + .all() + + return [ + { + 'exit_reason': exit_reason if exit_reason is not None else "Other", + 'profit_ratio': profit, + 'profit_pct': round(profit * 100, 2), + 'profit_abs': profit_abs, + 'count': count + } + for exit_reason, profit, profit_abs, count in sell_tag_perf + ] + + @staticmethod + def get_mix_tag_performance(pair: Optional[str]) -> List[Dict[str, Any]]: + """ + Returns List of dicts containing all Trades, based on entry_tag + exit_reason performance + Can either be average for all pairs or a specific pair provided + NOTE: Not supported in Backtesting. + """ + + filters = [Trade.is_open.is_(False)] + if(pair is not None): + filters.append(Trade.pair == pair) + + mix_tag_perf = Trade.query.with_entities( + Trade.id, + Trade.enter_tag, + Trade.exit_reason, + func.sum(Trade.close_profit).label('profit_sum'), + func.sum(Trade.close_profit_abs).label('profit_sum_abs'), + func.count(Trade.pair).label('count') + ).filter(*filters)\ + .group_by(Trade.id) \ + .order_by(desc('profit_sum_abs')) \ + .all() + + return_list: List[Dict] = [] + for id, enter_tag, exit_reason, profit, profit_abs, count in mix_tag_perf: + enter_tag = enter_tag if enter_tag is not None else "Other" + exit_reason = exit_reason if exit_reason is not None else "Other" + + if(exit_reason is not None and enter_tag is not None): + mix_tag = enter_tag + " " + exit_reason + i = 0 + if not any(item["mix_tag"] == mix_tag for item in return_list): + return_list.append({'mix_tag': mix_tag, + 'profit': profit, + 'profit_pct': round(profit * 100, 2), + 'profit_abs': profit_abs, + 'count': count}) + else: + while i < len(return_list): + if return_list[i]["mix_tag"] == mix_tag: + return_list[i] = { + 'mix_tag': mix_tag, + 'profit': profit + return_list[i]["profit"], + 'profit_pct': round(profit + return_list[i]["profit"] * 100, 2), + 'profit_abs': profit_abs + return_list[i]["profit_abs"], + 'count': 1 + return_list[i]["count"]} + i += 1 + + return return_list + + @staticmethod + def get_best_pair(start_date: datetime = datetime.fromtimestamp(0)): + """ + Get best pair with closed trade. + NOTE: Not supported in Backtesting. + :returns: Tuple containing (pair, profit_sum) + """ + best_pair = Trade.query.with_entities( + Trade.pair, func.sum(Trade.close_profit).label('profit_sum') + ).filter(Trade.is_open.is_(False) & (Trade.close_date >= start_date)) \ + .group_by(Trade.pair) \ + .order_by(desc('profit_sum')).first() + return best_pair diff --git a/freqtrade/plot/plotting.py b/freqtrade/plot/plotting.py index 5ef955354..ce8f54cbd 100644 --- a/freqtrade/plot/plotting.py +++ b/freqtrade/plot/plotting.py @@ -5,12 +5,13 @@ from typing import Any, Dict, List, Optional import pandas as pd from freqtrade.configuration import TimeRange -from freqtrade.data.btanalysis import (analyze_trade_parallelism, calculate_max_drawdown, - calculate_underwater, combine_dataframes_with_mean, - create_cum_profit, extract_trades_of_period, load_trades) +from freqtrade.data.btanalysis import (analyze_trade_parallelism, extract_trades_of_period, + load_trades) from freqtrade.data.converter import trim_dataframe from freqtrade.data.dataprovider import DataProvider from freqtrade.data.history import get_timerange, load_data +from freqtrade.data.metrics import (calculate_max_drawdown, calculate_underwater, + combine_dataframes_with_mean, create_cum_profit) from freqtrade.enums import CandleType from freqtrade.exceptions import OperationalException from freqtrade.exchange import timeframe_to_prev_date, timeframe_to_seconds @@ -158,12 +159,15 @@ def add_profit(fig, row, data: pd.DataFrame, column: str, name: str) -> make_sub def add_max_drawdown(fig, row, trades: pd.DataFrame, df_comb: pd.DataFrame, - timeframe: str) -> make_subplots: + timeframe: str, starting_balance: float) -> make_subplots: """ Add scatter points indicating max drawdown """ try: - _, highdate, lowdate, _, _, max_drawdown = calculate_max_drawdown(trades) + _, highdate, lowdate, _, _, max_drawdown = calculate_max_drawdown( + trades, + starting_balance=starting_balance + ) drawdown = go.Scatter( x=[highdate, lowdate], @@ -188,22 +192,37 @@ def add_max_drawdown(fig, row, trades: pd.DataFrame, df_comb: pd.DataFrame, return fig -def add_underwater(fig, row, trades: pd.DataFrame) -> make_subplots: +def add_underwater(fig, row, trades: pd.DataFrame, starting_balance: float) -> make_subplots: """ - Add underwater plot + Add underwater plots """ try: - underwater = calculate_underwater(trades, value_col="profit_abs") + underwater = calculate_underwater( + trades, + value_col="profit_abs", + starting_balance=starting_balance + ) - underwater = go.Scatter( + underwater_plot = go.Scatter( x=underwater['date'], y=underwater['drawdown'], name="Underwater Plot", fill='tozeroy', fillcolor='#cc362b', - line={'color': '#cc362b'}, + line={'color': '#cc362b'} ) - fig.add_trace(underwater, row, 1) + + underwater_plot_relative = go.Scatter( + x=underwater['date'], + y=(-underwater['drawdown_relative']), + name="Underwater Plot (%)", + fill='tozeroy', + fillcolor='green', + line={'color': 'green'} + ) + + fig.add_trace(underwater_plot, row, 1) + fig.add_trace(underwater_plot_relative, row + 1, 1) except ValueError: logger.warning("No trades found - not plotting underwater plot") return fig @@ -240,7 +259,7 @@ def plot_trades(fig, trades: pd.DataFrame) -> make_subplots: trades['desc'] = trades.apply( lambda row: f"{row['profit_ratio']:.2%}, " + (f"{row['enter_tag']}, " if row['enter_tag'] is not None else "") + - f"{row['sell_reason']}, " + + f"{row['exit_reason']}, " + f"{row['trade_duration']} min", axis=1) trade_buys = go.Scatter( @@ -506,7 +525,8 @@ def generate_candlestick_graph(pair: str, data: pd.DataFrame, trades: pd.DataFra def generate_profit_graph(pairs: str, data: Dict[str, pd.DataFrame], - trades: pd.DataFrame, timeframe: str, stake_currency: str) -> go.Figure: + trades: pd.DataFrame, timeframe: str, stake_currency: str, + starting_balance: float) -> go.Figure: # Combine close-values for all pairs, rename columns to "pair" try: df_comb = combine_dataframes_with_mean(data, "close") @@ -530,8 +550,8 @@ def generate_profit_graph(pairs: str, data: Dict[str, pd.DataFrame], name='Avg close price', ) - fig = make_subplots(rows=5, cols=1, shared_xaxes=True, - row_heights=[1, 1, 1, 0.5, 1], + fig = make_subplots(rows=6, cols=1, shared_xaxes=True, + row_heights=[1, 1, 1, 0.5, 0.75, 0.75], vertical_spacing=0.05, subplot_titles=[ "AVG Close Price", @@ -539,6 +559,7 @@ def generate_profit_graph(pairs: str, data: Dict[str, pd.DataFrame], "Profit per pair", "Parallelism", "Underwater", + "Relative Drawdown", ]) fig['layout'].update(title="Freqtrade Profit plot") fig['layout']['yaxis1'].update(title='Price') @@ -546,14 +567,16 @@ def generate_profit_graph(pairs: str, data: Dict[str, pd.DataFrame], fig['layout']['yaxis3'].update(title=f'Profit {stake_currency}') fig['layout']['yaxis4'].update(title='Trade count') fig['layout']['yaxis5'].update(title='Underwater Plot') + fig['layout']['yaxis6'].update(title='Underwater Plot Relative (%)', tickformat=',.2%') fig['layout']['xaxis']['rangeslider'].update(visible=False) fig.update_layout(modebar_add=["v1hovermode", "toggleSpikeLines"]) fig.add_trace(avgclose, 1, 1) fig = add_profit(fig, 2, df_comb, 'cum_profit', 'Profit') - fig = add_max_drawdown(fig, 2, trades, df_comb, timeframe) + fig = add_max_drawdown(fig, 2, trades, df_comb, timeframe, starting_balance) fig = add_parallelism(fig, 4, trades, timeframe) - fig = add_underwater(fig, 5, trades) + # Two rows consumed + fig = add_underwater(fig, 5, trades, starting_balance) for pair in pairs: profit_col = f'cum_profit_{pair}' @@ -610,6 +633,8 @@ 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() + strategy.bot_loop_start() plot_elements = init_plotscript(config, list(exchange.markets), strategy.startup_candle_count) timerange = plot_elements['timerange'] trades = plot_elements['trades'] @@ -668,7 +693,8 @@ def plot_profit(config: Dict[str, Any]) -> None: # this could be useful to gauge the overall market trend fig = generate_profit_graph(plot_elements['pairs'], plot_elements['ohlcv'], trades, config['timeframe'], - config.get('stake_currency', '')) + config.get('stake_currency', ''), + config.get('available_capital', config['dry_run_wallet'])) store_plot_file(fig, filename='freqtrade-profit-plot.html', directory=config['user_data_dir'] / 'plot', auto_open=config.get('plot_auto_open', False)) diff --git a/freqtrade/plugins/pairlist/AgeFilter.py b/freqtrade/plugins/pairlist/AgeFilter.py index bb6f75012..418c0f14e 100644 --- a/freqtrade/plugins/pairlist/AgeFilter.py +++ b/freqtrade/plugins/pairlist/AgeFilter.py @@ -32,18 +32,19 @@ class AgeFilter(IPairList): self._min_days_listed = pairlistconfig.get('min_days_listed', 10) self._max_days_listed = pairlistconfig.get('max_days_listed', None) + candle_limit = exchange.ohlcv_candle_limit('1d', self._config['candle_type_def']) if self._min_days_listed < 1: raise OperationalException("AgeFilter requires min_days_listed to be >= 1") - if self._min_days_listed > exchange.ohlcv_candle_limit('1d'): + if self._min_days_listed > candle_limit: raise OperationalException("AgeFilter requires min_days_listed to not exceed " "exchange max request size " - f"({exchange.ohlcv_candle_limit('1d')})") + f"({candle_limit})") if self._max_days_listed and self._max_days_listed <= self._min_days_listed: raise OperationalException("AgeFilter max_days_listed <= min_days_listed not permitted") - if self._max_days_listed and self._max_days_listed > exchange.ohlcv_candle_limit('1d'): + if self._max_days_listed and self._max_days_listed > candle_limit: raise OperationalException("AgeFilter requires max_days_listed to not exceed " "exchange max request size " - f"({exchange.ohlcv_candle_limit('1d')})") + f"({candle_limit})") @property def needstickers(self) -> bool: diff --git a/freqtrade/plugins/pairlist/OffsetFilter.py b/freqtrade/plugins/pairlist/OffsetFilter.py index 573a573a6..e0f8414ef 100644 --- a/freqtrade/plugins/pairlist/OffsetFilter.py +++ b/freqtrade/plugins/pairlist/OffsetFilter.py @@ -19,6 +19,7 @@ class OffsetFilter(IPairList): super().__init__(exchange, pairlistmanager, config, pairlistconfig, pairlist_pos) self._offset = pairlistconfig.get('offset', 0) + self._number_pairs = pairlistconfig.get('number_assets', 0) if self._offset < 0: raise OperationalException("OffsetFilter requires offset to be >= 0") @@ -36,7 +37,9 @@ class OffsetFilter(IPairList): """ Short whitelist method description - used for startup-messages """ - return f"{self.name} - Offseting pairs by {self._offset}." + if self._number_pairs: + return f"{self.name} - Taking {self._number_pairs} Pairs, starting from {self._offset}." + return f"{self.name} - Offsetting pairs by {self._offset}." def filter_pairlist(self, pairlist: List[str], tickers: Dict) -> List[str]: """ @@ -50,5 +53,9 @@ class OffsetFilter(IPairList): self.log_once(f"Offset of {self._offset} is larger than " + f"pair count of {len(pairlist)}", logger.warning) pairs = pairlist[self._offset:] + if self._number_pairs: + pairs = pairs[:self._number_pairs] + self.log_once(f"Searching {len(pairs)} pairs: {pairs}", logger.info) + return pairs diff --git a/freqtrade/plugins/pairlist/VolatilityFilter.py b/freqtrade/plugins/pairlist/VolatilityFilter.py index 7a355c291..bab44bdd1 100644 --- a/freqtrade/plugins/pairlist/VolatilityFilter.py +++ b/freqtrade/plugins/pairlist/VolatilityFilter.py @@ -38,12 +38,12 @@ class VolatilityFilter(IPairList): self._pair_cache: TTLCache = TTLCache(maxsize=1000, ttl=self._refresh_period) + candle_limit = exchange.ohlcv_candle_limit('1d', self._config['candle_type_def']) if self._days < 1: raise OperationalException("VolatilityFilter requires lookback_days to be >= 1") - if self._days > exchange.ohlcv_candle_limit('1d'): + if self._days > candle_limit: raise OperationalException("VolatilityFilter requires lookback_days to not " - "exceed exchange max request size " - f"({exchange.ohlcv_candle_limit('1d')})") + f"exceed exchange max request size ({candle_limit})") @property def needstickers(self) -> bool: @@ -107,7 +107,7 @@ class VolatilityFilter(IPairList): returns = (np.log(daily_candles.close / daily_candles.close.shift(-1))) returns.fillna(0, inplace=True) - volatility_series = returns.rolling(window=self._days).std()*np.sqrt(self._days) + volatility_series = returns.rolling(window=self._days).std() * np.sqrt(self._days) volatility_avg = volatility_series.mean() if self._min_volatility <= volatility_avg <= self._max_volatility: diff --git a/freqtrade/plugins/pairlist/VolumePairList.py b/freqtrade/plugins/pairlist/VolumePairList.py index 26e7d45be..cd16a46a3 100644 --- a/freqtrade/plugins/pairlist/VolumePairList.py +++ b/freqtrade/plugins/pairlist/VolumePairList.py @@ -84,12 +84,13 @@ class VolumePairList(IPairList): raise OperationalException( f'key {self._sort_key} not in {SORT_VALUES}') + candle_limit = exchange.ohlcv_candle_limit( + self._lookback_timeframe, self._config['candle_type_def']) if self._lookback_period < 0: raise OperationalException("VolumeFilter requires lookback_period to be >= 0") - if self._lookback_period > exchange.ohlcv_candle_limit(self._lookback_timeframe): + if self._lookback_period > candle_limit: raise OperationalException("VolumeFilter requires lookback_period to not " - "exceed exchange max request size " - f"({exchange.ohlcv_candle_limit(self._lookback_timeframe)})") + f"exceed exchange max request size ({candle_limit})") @property def needstickers(self) -> bool: diff --git a/freqtrade/plugins/pairlist/rangestabilityfilter.py b/freqtrade/plugins/pairlist/rangestabilityfilter.py index c9edfd13d..de016c3a6 100644 --- a/freqtrade/plugins/pairlist/rangestabilityfilter.py +++ b/freqtrade/plugins/pairlist/rangestabilityfilter.py @@ -33,12 +33,12 @@ class RangeStabilityFilter(IPairList): self._pair_cache: TTLCache = TTLCache(maxsize=1000, ttl=self._refresh_period) + candle_limit = exchange.ohlcv_candle_limit('1d', self._config['candle_type_def']) if self._days < 1: raise OperationalException("RangeStabilityFilter requires lookback_days to be >= 1") - if self._days > exchange.ohlcv_candle_limit('1d'): + if self._days > candle_limit: raise OperationalException("RangeStabilityFilter requires lookback_days to not " - "exceed exchange max request size " - f"({exchange.ohlcv_candle_limit('1d')})") + f"exceed exchange max request size ({candle_limit})") @property def needstickers(self) -> bool: diff --git a/freqtrade/plugins/protectionmanager.py b/freqtrade/plugins/protectionmanager.py index 2510d6fee..d33294fa7 100644 --- a/freqtrade/plugins/protectionmanager.py +++ b/freqtrade/plugins/protectionmanager.py @@ -5,6 +5,7 @@ import logging from datetime import datetime, timezone from typing import Dict, List, Optional +from freqtrade.constants import LongShort from freqtrade.persistence import PairLocks from freqtrade.persistence.models import PairLock from freqtrade.plugins.protections import IProtection @@ -44,28 +45,31 @@ class ProtectionManager(): """ return [{p.name: p.short_desc()} for p in self._protection_handlers] - def global_stop(self, now: Optional[datetime] = None) -> Optional[PairLock]: + def global_stop(self, now: Optional[datetime] = None, + side: LongShort = 'long') -> Optional[PairLock]: if not now: now = datetime.now(timezone.utc) result = None for protection_handler in self._protection_handlers: if protection_handler.has_global_stop: - lock, until, reason = protection_handler.global_stop(now) - - # Early stopping - first positive result blocks further trades - if lock and until: - if not PairLocks.is_global_lock(until): - result = PairLocks.lock_pair('*', until, reason, now=now) + lock = protection_handler.global_stop(date_now=now, side=side) + if lock and lock.until: + if not PairLocks.is_global_lock(lock.until, side=lock.lock_side): + result = PairLocks.lock_pair( + '*', lock.until, lock.reason, now=now, side=lock.lock_side) return result - def stop_per_pair(self, pair, now: Optional[datetime] = None) -> Optional[PairLock]: + def stop_per_pair(self, pair, now: Optional[datetime] = None, + side: LongShort = 'long') -> Optional[PairLock]: if not now: now = datetime.now(timezone.utc) result = None for protection_handler in self._protection_handlers: if protection_handler.has_local_stop: - lock, until, reason = protection_handler.stop_per_pair(pair, now) - if lock and until: - if not PairLocks.is_pair_locked(pair, until): - result = PairLocks.lock_pair(pair, until, reason, now=now) + lock = protection_handler.stop_per_pair( + pair=pair, date_now=now, side=side) + if lock and lock.until: + if not PairLocks.is_pair_locked(pair, lock.until, lock.lock_side): + result = PairLocks.lock_pair( + pair, lock.until, lock.reason, now=now, side=lock.lock_side) return result diff --git a/freqtrade/plugins/protections/cooldown_period.py b/freqtrade/plugins/protections/cooldown_period.py index a2d8eca34..426b8f1b6 100644 --- a/freqtrade/plugins/protections/cooldown_period.py +++ b/freqtrade/plugins/protections/cooldown_period.py @@ -1,7 +1,9 @@ import logging from datetime import datetime, timedelta +from typing import Optional +from freqtrade.constants import LongShort from freqtrade.persistence import Trade from freqtrade.plugins.protections import IProtection, ProtectionReturn @@ -26,7 +28,7 @@ class CooldownPeriod(IProtection): """ return (f"{self.name} - Cooldown period of {self.stop_duration_str}.") - def _cooldown_period(self, pair: str, date_now: datetime, ) -> ProtectionReturn: + def _cooldown_period(self, pair: str, date_now: datetime) -> Optional[ProtectionReturn]: """ Get last trade for this pair """ @@ -45,11 +47,15 @@ class CooldownPeriod(IProtection): self.log_once(f"Cooldown for {pair} for {self.stop_duration_str}.", logger.info) until = self.calculate_lock_end([trade], self._stop_duration) - return True, until, self._reason() + return ProtectionReturn( + lock=True, + until=until, + reason=self._reason(), + ) - return False, None, None + return None - def global_stop(self, date_now: datetime) -> ProtectionReturn: + def global_stop(self, date_now: datetime, side: LongShort) -> Optional[ProtectionReturn]: """ Stops trading (position entering) for all pairs This must evaluate to true for the whole period of the "cooldown period". @@ -57,9 +63,10 @@ class CooldownPeriod(IProtection): If true, all pairs will be locked with until """ # Not implemented for cooldown period. - return False, None, None + return None - def stop_per_pair(self, pair: str, date_now: datetime) -> ProtectionReturn: + def stop_per_pair( + self, pair: str, date_now: datetime, side: LongShort) -> Optional[ProtectionReturn]: """ Stops trading (position entering) for this pair This must evaluate to true for the whole period of the "cooldown period". diff --git a/freqtrade/plugins/protections/iprotection.py b/freqtrade/plugins/protections/iprotection.py index e0a89e334..890988226 100644 --- a/freqtrade/plugins/protections/iprotection.py +++ b/freqtrade/plugins/protections/iprotection.py @@ -1,9 +1,11 @@ import logging from abc import ABC, abstractmethod +from dataclasses import dataclass from datetime import datetime, timedelta, timezone -from typing import Any, Dict, List, Optional, Tuple +from typing import Any, Dict, List, Optional +from freqtrade.constants import LongShort from freqtrade.exchange import timeframe_to_minutes from freqtrade.misc import plural from freqtrade.mixins import LoggingMixin @@ -12,7 +14,13 @@ from freqtrade.persistence import LocalTrade logger = logging.getLogger(__name__) -ProtectionReturn = Tuple[bool, Optional[datetime], Optional[str]] + +@dataclass +class ProtectionReturn: + lock: bool + until: datetime + reason: Optional[str] + lock_side: str = '*' class IProtection(LoggingMixin, ABC): @@ -80,14 +88,15 @@ class IProtection(LoggingMixin, ABC): """ @abstractmethod - def global_stop(self, date_now: datetime) -> ProtectionReturn: + def global_stop(self, date_now: datetime, side: LongShort) -> Optional[ProtectionReturn]: """ Stops trading (position entering) for all pairs This must evaluate to true for the whole period of the "cooldown period". """ @abstractmethod - def stop_per_pair(self, pair: str, date_now: datetime) -> ProtectionReturn: + def stop_per_pair( + self, pair: str, date_now: datetime, side: LongShort) -> Optional[ProtectionReturn]: """ Stops trading (position entering) for this pair This must evaluate to true for the whole period of the "cooldown period". diff --git a/freqtrade/plugins/protections/low_profit_pairs.py b/freqtrade/plugins/protections/low_profit_pairs.py index 7822ce73c..099242b8d 100644 --- a/freqtrade/plugins/protections/low_profit_pairs.py +++ b/freqtrade/plugins/protections/low_profit_pairs.py @@ -1,8 +1,9 @@ import logging from datetime import datetime, timedelta -from typing import Any, Dict +from typing import Any, Dict, Optional +from freqtrade.constants import LongShort from freqtrade.persistence import Trade from freqtrade.plugins.protections import IProtection, ProtectionReturn @@ -20,6 +21,7 @@ class LowProfitPairs(IProtection): self._trade_limit = protection_config.get('trade_limit', 1) self._required_profit = protection_config.get('required_profit', 0.0) + self._only_per_side = protection_config.get('only_per_side', False) def short_desc(self) -> str: """ @@ -35,7 +37,8 @@ class LowProfitPairs(IProtection): return (f'{profit} < {self._required_profit} in {self.lookback_period_str}, ' f'locking for {self.stop_duration_str}.') - def _low_profit(self, date_now: datetime, pair: str) -> ProtectionReturn: + def _low_profit( + self, date_now: datetime, pair: str, side: LongShort) -> Optional[ProtectionReturn]: """ Evaluate recent trades for pair """ @@ -51,33 +54,42 @@ class LowProfitPairs(IProtection): # trades = Trade.get_trades(filters).all() if len(trades) < self._trade_limit: # Not enough trades in the relevant period - return False, None, None + return None - profit = sum(trade.close_profit for trade in trades if trade.close_profit) + profit = sum( + trade.close_profit for trade in trades if trade.close_profit + and (not self._only_per_side or trade.trade_direction == side) + ) if profit < self._required_profit: self.log_once( f"Trading for {pair} stopped due to {profit:.2f} < {self._required_profit} " f"within {self._lookback_period} minutes.", logger.info) until = self.calculate_lock_end(trades, self._stop_duration) - return True, until, self._reason(profit) + return ProtectionReturn( + lock=True, + until=until, + reason=self._reason(profit), + lock_side=(side if self._only_per_side else '*') + ) - return False, None, None + return None - def global_stop(self, date_now: datetime) -> ProtectionReturn: + def global_stop(self, date_now: datetime, side: LongShort) -> Optional[ProtectionReturn]: """ Stops trading (position entering) for all pairs This must evaluate to true for the whole period of the "cooldown period". :return: Tuple of [bool, until, reason]. If true, all pairs will be locked with until """ - return False, None, None + return None - def stop_per_pair(self, pair: str, date_now: datetime) -> ProtectionReturn: + def stop_per_pair( + self, pair: str, date_now: datetime, side: LongShort) -> Optional[ProtectionReturn]: """ Stops trading (position entering) for this pair This must evaluate to true for the whole period of the "cooldown period". :return: Tuple of [bool, until, reason]. If true, this pair will be locked with until """ - return self._low_profit(date_now, pair=pair) + return self._low_profit(date_now, pair=pair, side=side) diff --git a/freqtrade/plugins/protections/max_drawdown_protection.py b/freqtrade/plugins/protections/max_drawdown_protection.py index b6ef92bd5..e0b016cb8 100644 --- a/freqtrade/plugins/protections/max_drawdown_protection.py +++ b/freqtrade/plugins/protections/max_drawdown_protection.py @@ -1,11 +1,12 @@ import logging from datetime import datetime, timedelta -from typing import Any, Dict +from typing import Any, Dict, Optional import pandas as pd -from freqtrade.data.btanalysis import calculate_max_drawdown +from freqtrade.constants import LongShort +from freqtrade.data.metrics import calculate_max_drawdown from freqtrade.persistence import Trade from freqtrade.plugins.protections import IProtection, ProtectionReturn @@ -39,7 +40,7 @@ class MaxDrawdown(IProtection): return (f'{drawdown} passed {self._max_allowed_drawdown} in {self.lookback_period_str}, ' f'locking for {self.stop_duration_str}.') - def _max_drawdown(self, date_now: datetime) -> ProtectionReturn: + def _max_drawdown(self, date_now: datetime) -> Optional[ProtectionReturn]: """ Evaluate recent trades for drawdown ... """ @@ -51,14 +52,14 @@ class MaxDrawdown(IProtection): if len(trades) < self._trade_limit: # Not enough trades in the relevant period - return False, None, None + return None # Drawdown is always positive try: # TODO: This should use absolute profit calculation, considering account balance. drawdown, _, _, _, _, _ = calculate_max_drawdown(trades_df, value_col='close_profit') except ValueError: - return False, None, None + return None if drawdown > self._max_allowed_drawdown: self.log_once( @@ -66,11 +67,15 @@ class MaxDrawdown(IProtection): f" within {self.lookback_period_str}.", logger.info) until = self.calculate_lock_end(trades, self._stop_duration) - return True, until, self._reason(drawdown) + return ProtectionReturn( + lock=True, + until=until, + reason=self._reason(drawdown), + ) - return False, None, None + return None - def global_stop(self, date_now: datetime) -> ProtectionReturn: + def global_stop(self, date_now: datetime, side: LongShort) -> Optional[ProtectionReturn]: """ Stops trading (position entering) for all pairs This must evaluate to true for the whole period of the "cooldown period". @@ -79,11 +84,12 @@ class MaxDrawdown(IProtection): """ return self._max_drawdown(date_now) - def stop_per_pair(self, pair: str, date_now: datetime) -> ProtectionReturn: + def stop_per_pair( + self, pair: str, date_now: datetime, side: LongShort) -> Optional[ProtectionReturn]: """ Stops trading (position entering) for this pair This must evaluate to true for the whole period of the "cooldown period". :return: Tuple of [bool, until, reason]. If true, this pair will be locked with until """ - return False, None, None + return None diff --git a/freqtrade/plugins/protections/stoploss_guard.py b/freqtrade/plugins/protections/stoploss_guard.py index 7a29c20b1..713a2da07 100644 --- a/freqtrade/plugins/protections/stoploss_guard.py +++ b/freqtrade/plugins/protections/stoploss_guard.py @@ -1,8 +1,9 @@ import logging from datetime import datetime, timedelta -from typing import Any, Dict +from typing import Any, Dict, Optional +from freqtrade.constants import LongShort from freqtrade.enums import ExitType from freqtrade.persistence import Trade from freqtrade.plugins.protections import IProtection, ProtectionReturn @@ -21,6 +22,7 @@ class StoplossGuard(IProtection): self._trade_limit = protection_config.get('trade_limit', 10) self._disable_global_stop = protection_config.get('only_per_pair', False) + self._only_per_side = protection_config.get('only_per_side', False) def short_desc(self) -> str: """ @@ -36,37 +38,37 @@ class StoplossGuard(IProtection): return (f'{self._trade_limit} stoplosses in {self._lookback_period} min, ' f'locking for {self._stop_duration} min.') - def _stoploss_guard(self, date_now: datetime, pair: str = None) -> ProtectionReturn: + def _stoploss_guard(self, date_now: datetime, pair: Optional[str], + side: LongShort) -> Optional[ProtectionReturn]: """ Evaluate recent trades """ look_back_until = date_now - timedelta(minutes=self._lookback_period) - # filters = [ - # Trade.is_open.is_(False), - # Trade.close_date > look_back_until, - # or_(Trade.sell_reason == ExitType.STOP_LOSS.value, - # and_(Trade.sell_reason == ExitType.TRAILING_STOP_LOSS.value, - # Trade.close_profit < 0)) - # ] - # if pair: - # filters.append(Trade.pair == pair) - # trades = Trade.get_trades(filters).all() trades1 = Trade.get_trades_proxy(pair=pair, is_open=False, close_date=look_back_until) - trades = [trade for trade in trades1 if (str(trade.sell_reason) in ( + trades = [trade for trade in trades1 if (str(trade.exit_reason) in ( ExitType.TRAILING_STOP_LOSS.value, ExitType.STOP_LOSS.value, ExitType.STOPLOSS_ON_EXCHANGE.value) and trade.close_profit and trade.close_profit < 0)] + if self._only_per_side: + # Long or short trades only + trades = [trade for trade in trades if trade.trade_direction == side] + if len(trades) < self._trade_limit: - return False, None, None + return None self.log_once(f"Trading stopped due to {self._trade_limit} " f"stoplosses within {self._lookback_period} minutes.", logger.info) until = self.calculate_lock_end(trades, self._stop_duration) - return True, until, self._reason() + return ProtectionReturn( + lock=True, + until=until, + reason=self._reason(), + lock_side=(side if self._only_per_side else '*') + ) - def global_stop(self, date_now: datetime) -> ProtectionReturn: + def global_stop(self, date_now: datetime, side: LongShort) -> Optional[ProtectionReturn]: """ Stops trading (position entering) for all pairs This must evaluate to true for the whole period of the "cooldown period". @@ -74,14 +76,15 @@ class StoplossGuard(IProtection): If true, all pairs will be locked with until """ if self._disable_global_stop: - return False, None, None - return self._stoploss_guard(date_now, None) + return None + return self._stoploss_guard(date_now, None, side) - def stop_per_pair(self, pair: str, date_now: datetime) -> ProtectionReturn: + def stop_per_pair( + self, pair: str, date_now: datetime, side: LongShort) -> Optional[ProtectionReturn]: """ Stops trading (position entering) for this pair This must evaluate to true for the whole period of the "cooldown period". :return: Tuple of [bool, until, reason]. If true, this pair will be locked with until """ - return self._stoploss_guard(date_now, pair) + return self._stoploss_guard(date_now, pair, side) 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/freqtrade/resolvers/iresolver.py b/freqtrade/resolvers/iresolver.py index 3ab461041..74b28dffe 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: List[str] = []) -> List[Path]: abs_paths: List[Path] = [] if cls.initial_search_path: @@ -53,9 +53,9 @@ class IResolver: if user_subdir: abs_paths.insert(0, config['user_data_dir'].joinpath(user_subdir)) - if extra_dir: - # Add extra directory to the top of the search paths - abs_paths.insert(0, Path(extra_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 @@ -164,9 +164,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) @@ -178,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 87a9cc4b3..44d590b67 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.configuration.config_validation import validate_migrated_strategy_settings from freqtrade.constants import REQUIRED_ORDERTIF, REQUIRED_ORDERTYPES, USERPATH_STRATEGIES @@ -85,10 +86,10 @@ class StrategyResolver(IResolver): ("protections", None), ("startup_candle_count", None), ("unfilledtimeout", None), - ("use_sell_signal", True), - ("sell_profit_only", False), - ("ignore_roi_if_buy_signal", False), - ("sell_profit_offset", 0.0), + ("use_exit_signal", True), + ("exit_profit_only", False), + ("ignore_roi_if_entry_signal", False), + ("exit_profit_offset", 0.0), ("disable_dataframe_checks", False), ("ignore_buying_expired_candle_after", 0), ("position_adjustment_enable", False), @@ -173,6 +174,12 @@ class StrategyResolver(IResolver): def validate_strategy(strategy: IStrategy) -> IStrategy: if strategy.config.get('trading_mode', TradingMode.SPOT) != TradingMode.SPOT: # Require new method + warn_deprecated_setting(strategy, 'sell_profit_only', 'exit_profit_only', True) + warn_deprecated_setting(strategy, 'sell_profit_offset', 'exit_profit_offset', True) + warn_deprecated_setting(strategy, 'use_sell_signal', 'use_exit_signal', True) + warn_deprecated_setting(strategy, 'ignore_roi_if_buy_signal', + 'ignore_roi_if_entry_signal', True) + if not check_override(strategy, IStrategy, 'populate_entry_trend'): raise OperationalException("`populate_entry_trend` must be implemented.") if not check_override(strategy, IStrategy, 'populate_exit_trend'): @@ -187,9 +194,16 @@ class StrategyResolver(IResolver): if check_override(strategy, IStrategy, 'custom_sell'): raise OperationalException( "Please migrate your implementation of `custom_sell` to `custom_exit`.") + else: # TODO: Implementing one of the following methods should show a deprecation warning # buy_trend and sell_trend, custom_sell + warn_deprecated_setting(strategy, 'sell_profit_only', 'exit_profit_only') + warn_deprecated_setting(strategy, 'sell_profit_offset', 'exit_profit_offset') + warn_deprecated_setting(strategy, 'use_sell_signal', 'use_exit_signal') + warn_deprecated_setting(strategy, 'ignore_roi_if_buy_signal', + 'ignore_roi_if_entry_signal') + if ( not check_override(strategy, IStrategy, 'populate_buy_trend') and not check_override(strategy, IStrategy, 'populate_entry_trend') @@ -203,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 @@ -224,10 +242,19 @@ class StrategyResolver(IResolver): :param extra_dir: additional directory to search for the given strategy :return: Strategy instance or None """ + 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 + else: + extra_dirs = [] + + 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") @@ -262,6 +289,15 @@ class StrategyResolver(IResolver): ) +def warn_deprecated_setting(strategy: IStrategy, old: str, new: str, error=False): + if hasattr(strategy, old): + errormsg = f"DEPRECATED: Using '{old}' moved to '{new}'." + if error: + raise OperationalException(errormsg) + logger.warning(errormsg) + setattr(strategy, new, getattr(strategy, f'{old}')) + + def check_override(object, parentclass, attribute): """ Checks if a object overrides the parent class attribute. diff --git a/freqtrade/rpc/api_server/api_backtest.py b/freqtrade/rpc/api_server/api_backtest.py index 757ed8aac..26b100408 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 Any, Dict, 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_and_merge_backtest_result 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 @@ -81,6 +84,7 @@ async def api_start_backtest(bt_settings: BacktestRequest, background_tasks: Bac lastconfig['enable_protections'] = btconfig.get('enable_protections') lastconfig['dry_run_wallet'] = btconfig.get('dry_run_wallet') + ApiServer._bt.strategylist = [strat] ApiServer._bt.results = {} ApiServer._bt.load_prior_backtest() @@ -168,6 +172,7 @@ def api_delete_backtest(ws_mode=Depends(is_webserver_mode)): "status_msg": "Backtest running", } if ApiServer._bt: + ApiServer._bt.cleanup() del ApiServer._bt ApiServer._bt = None del ApiServer._bt_data @@ -200,3 +205,30 @@ 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') + + +@router.get('/backtest/history/result', response_model=BacktestResponse, tags=['webserver', 'backtest']) +def api_backtest_history_result(filename: str, strategy: str, config=Depends(get_config), ws_mode=Depends(is_webserver_mode)): + # Get backtest result history, read from metadata files + fn = config['user_data_dir'] / 'backtest_results' / filename + results: Dict[str, Any] = { + '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": results, + } diff --git a/freqtrade/rpc/api_server/api_schemas.py b/freqtrade/rpc/api_server/api_schemas.py index 11baa9560..d78ea8b78 100644 --- a/freqtrade/rpc/api_server/api_schemas.py +++ b/freqtrade/rpc/api_server/api_schemas.py @@ -113,7 +113,7 @@ class SellReason(BaseModel): class Stats(BaseModel): - sell_reasons: Dict[str, SellReason] + exit_reasons: Dict[str, SellReason] durations: Dict[str, Optional[float]] @@ -140,9 +140,9 @@ class UnfilledTimeout(BaseModel): class OrderTypes(BaseModel): entry: OrderTypeValues exit: OrderTypeValues - emergencyexit: Optional[OrderTypeValues] - forceexit: Optional[OrderTypeValues] - forceentry: Optional[OrderTypeValues] + emergency_exit: Optional[OrderTypeValues] + force_exit: Optional[OrderTypeValues] + force_entry: Optional[OrderTypeValues] stoploss: OrderTypeValues stoploss_on_exchange: bool stoploss_on_exchange_interval: Optional[int] @@ -174,7 +174,7 @@ class ShowConfig(BaseModel): timeframe_min: int exchange: str strategy: Optional[str] - forcebuy_enabled: bool + force_entry_enable: bool exit_pricing: Dict[str, Any] entry_pricing: Dict[str, Any] bot_name: str @@ -203,6 +203,8 @@ class OrderSchema(BaseModel): class TradeSchema(BaseModel): trade_id: int pair: str + base_currency: str + quote_currency: str is_open: bool is_short: bool exchange: str @@ -235,8 +237,9 @@ class TradeSchema(BaseModel): profit_pct: Optional[float] profit_abs: Optional[float] profit_fiat: Optional[float] - sell_reason: Optional[str] - sell_order_status: Optional[str] + sell_reason: Optional[str] # Deprecated + exit_reason: Optional[str] + exit_order_status: Optional[str] stop_loss_abs: Optional[float] stop_loss_ratio: Optional[float] stop_loss_pct: Optional[float] @@ -288,6 +291,7 @@ class LockModel(BaseModel): lock_time: str lock_timestamp: int pair: str + side: str reason: str @@ -418,6 +422,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 diff --git a/freqtrade/rpc/api_server/api_v1.py b/freqtrade/rpc/api_server/api_v1.py index 61c5243aa..a8b9873d7 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() @@ -135,13 +136,13 @@ def show_config(rpc: Optional[RPC] = Depends(get_rpc_optional), config=Depends(g return resp -# /forcebuy is deprecated with short addition. use ForceEntry instead +# /forcebuy is deprecated with short addition. use /forceentry instead @router.post('/forceenter', response_model=ForceEnterResponse, tags=['trading']) @router.post('/forcebuy', response_model=ForceEnterResponse, tags=['trading']) -def forceentry(payload: ForceEnterPayload, rpc: RPC = Depends(get_rpc)): +def force_entry(payload: ForceEnterPayload, rpc: RPC = Depends(get_rpc)): ordertype = payload.ordertype.value if payload.ordertype else None stake_amount = payload.stakeamount if payload.stakeamount else None - entry_tag = payload.entry_tag if payload.entry_tag else 'forceentry' + entry_tag = payload.entry_tag if payload.entry_tag else 'force_entry' trade = rpc._rpc_force_entry(payload.pair, payload.price, order_side=payload.side, order_type=ordertype, stake_amount=stake_amount, @@ -154,11 +155,12 @@ def forceentry(payload: ForceEnterPayload, rpc: RPC = Depends(get_rpc)): {"status": f"Error entering {payload.side} trade for pair {payload.pair}."}) +# /forcesell is deprecated with short addition. use /forceexit instead @router.post('/forceexit', response_model=ResultMsg, tags=['trading']) @router.post('/forcesell', response_model=ResultMsg, tags=['trading']) -def forcesell(payload: ForceExitPayload, rpc: RPC = Depends(get_rpc)): +def forceexit(payload: ForceExitPayload, rpc: RPC = Depends(get_rpc)): ordertype = payload.ordertype.value if payload.ordertype else None - return rpc._rpc_forceexit(payload.tradeid, ordertype) + return rpc._rpc_force_exit(payload.tradeid, ordertype) @router.get('/blacklist', response_model=BlacklistResponse, tags=['info', 'pairlist']) @@ -251,7 +253,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]} 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/freqtrade/rpc/fiat_convert.py b/freqtrade/rpc/fiat_convert.py index 70f3647b6..df33693ac 100644 --- a/freqtrade/rpc/fiat_convert.py +++ b/freqtrade/rpc/fiat_convert.py @@ -63,7 +63,7 @@ class CryptoToFiatConverter: except RequestException as request_exception: if "429" in str(request_exception): logger.warning( - "Too many requests for Coingecko API, backing off and trying again later.") + "Too many requests for CoinGecko API, backing off and trying again later.") # Set backoff timestamp to 60 seconds in the future self._backoff = datetime.datetime.now().timestamp() + 60 return @@ -86,7 +86,7 @@ class CryptoToFiatConverter: return None else: return None - found = [x for x in self._coinlistings if x['symbol'] == crypto_symbol] + found = [x for x in self._coinlistings if x['symbol'].lower() == crypto_symbol] if crypto_symbol in coingecko_mapping.keys(): found = [x for x in self._coinlistings if x['id'] == coingecko_mapping[crypto_symbol]] @@ -96,7 +96,7 @@ class CryptoToFiatConverter: if len(found) > 0: # Wrong! - logger.warning(f"Found multiple mappings in goingekko for {crypto_symbol}.") + logger.warning(f"Found multiple mappings in CoinGecko for {crypto_symbol}.") return None def convert_amount(self, crypto_amount: float, crypto_symbol: str, fiat_symbol: str) -> float: @@ -160,7 +160,7 @@ class CryptoToFiatConverter: def _find_price(self, crypto_symbol: str, fiat_symbol: str) -> float: """ - Call CoinGekko API to retrieve the price in the FIAT + Call CoinGecko API to retrieve the price in the FIAT :param crypto_symbol: Crypto-currency you want to convert (e.g btc) :param fiat_symbol: FIAT currency you want to convert to (e.g usd) :return: float, price of the crypto-currency in Fiat diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 1388a9bda..a98e3f96d 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -136,7 +136,7 @@ class RPC: ) if 'timeframe' in config else 0, 'exchange': config['exchange']['name'], 'strategy': config['strategy'], - 'forcebuy_enabled': config.get('forcebuy_enable', False), + 'force_entry_enable': config.get('force_entry_enable', False), 'exit_pricing': config.get('exit_pricing', {}), 'entry_pricing': config.get('entry_pricing', {}), 'state': str(botstate), @@ -177,16 +177,19 @@ class RPC: current_rate = NAN else: current_rate = trade.close_rate - current_profit = trade.calc_profit_ratio(current_rate) - current_profit_abs = trade.calc_profit(current_rate) - current_profit_fiat: Optional[float] = None - # Calculate fiat profit - if self._fiat_converter: - current_profit_fiat = self._fiat_converter.convert_amount( - current_profit_abs, - self._freqtrade.config['stake_currency'], - self._freqtrade.config['fiat_display_currency'] - ) + if len(trade.select_filled_orders(trade.entry_side)) > 0: + current_profit = trade.calc_profit_ratio(current_rate) + current_profit_abs = trade.calc_profit(current_rate) + current_profit_fiat: Optional[float] = None + # Calculate fiat profit + if self._fiat_converter: + current_profit_fiat = self._fiat_converter.convert_amount( + current_profit_abs, + self._freqtrade.config['stake_currency'], + self._freqtrade.config['fiat_display_currency'] + ) + else: + current_profit = current_profit_abs = current_profit_fiat = 0.0 # Calculate guaranteed profit (in case of trailing stop) stoploss_entry_dist = trade.calc_profit(trade.stop_loss) @@ -197,7 +200,6 @@ class RPC: trade_dict = trade.to_json() trade_dict.update(dict( - base_currency=self._freqtrade.config['stake_currency'], close_profit=trade.close_profit if trade.close_profit is not None else None, current_rate=current_rate, current_profit=current_profit, # Deprecated @@ -223,6 +225,7 @@ class RPC: def _rpc_status_table(self, stake_currency: str, fiat_display_currency: str) -> Tuple[List, List, float]: trades: List[Trade] = Trade.get_open_trades() + nonspot = self._config.get('trading_mode', TradingMode.SPOT) != TradingMode.SPOT if not trades: raise RPCException('no active trade') else: @@ -235,16 +238,20 @@ class RPC: trade.pair, side='exit', is_short=trade.is_short, refresh=False) except (PricingError, ExchangeError): current_rate = NAN - trade_profit = trade.calc_profit(current_rate) - profit_str = f'{trade.calc_profit_ratio(current_rate):.2%}' - direction_str = 'S' if trade.is_short else 'L' + if len(trade.select_filled_orders(trade.entry_side)) > 0: + trade_profit = trade.calc_profit(current_rate) + profit_str = f'{trade.calc_profit_ratio(current_rate):.2%}' + else: + trade_profit = 0.0 + profit_str = f'{0.0:.2f}' + direction_str = ('S' if trade.is_short else 'L') if nonspot else '' if self._fiat_converter: fiat_profit = self._fiat_converter.convert_amount( trade_profit, stake_currency, fiat_display_currency ) - if fiat_profit and not isnan(fiat_profit): + if not isnan(fiat_profit): profit_str += f" ({fiat_profit:.2f})" fiat_profit_sum = fiat_profit if isnan(fiat_profit_sum) \ else fiat_profit_sum + fiat_profit @@ -267,7 +274,11 @@ class RPC: if self._fiat_converter: profitcol += " (" + fiat_display_currency + ")" - columns = ['ID L/S', 'Pair', 'Since', profitcol] + columns = [ + 'ID L/S' if nonspot else 'ID', + 'Pair', + 'Since', + profitcol] if self._config.get('position_adjustment_enable', False): columns.append('# Entries') return trades_list, columns, fiat_profit_sum @@ -428,13 +439,13 @@ class RPC: return 'losses' else: return 'draws' - trades = trades = Trade.get_trades([Trade.is_open.is_(False)]) + trades: List[Trade] = Trade.get_trades([Trade.is_open.is_(False)]) # Sell reason - sell_reasons = {} + exit_reasons = {} for trade in trades: - if trade.sell_reason not in sell_reasons: - sell_reasons[trade.sell_reason] = {'wins': 0, 'losses': 0, 'draws': 0} - sell_reasons[trade.sell_reason][trade_win_loss(trade)] += 1 + if trade.exit_reason not in exit_reasons: + exit_reasons[trade.exit_reason] = {'wins': 0, 'losses': 0, 'draws': 0} + exit_reasons[trade.exit_reason][trade_win_loss(trade)] += 1 # Duration dur: Dict[str, List[int]] = {'wins': [], 'draws': [], 'losses': []} @@ -448,7 +459,7 @@ class RPC: losses_dur = sum(dur['losses']) / len(dur['losses']) if len(dur['losses']) > 0 else None durations = {'wins': wins_dur, 'draws': draws_dur, 'losses': losses_dur} - return {'sell_reasons': sell_reasons, 'durations': durations} + return {'exit_reasons': exit_reasons, 'durations': durations} def _rpc_trade_statistics( self, stake_currency: str, fiat_display_currency: str, @@ -684,32 +695,32 @@ class RPC: return {'status': 'No more buy will occur from now. Run /reload_config to reset.'} - def _rpc_forceexit(self, trade_id: str, ordertype: Optional[str] = None) -> Dict[str, str]: + def _rpc_force_exit(self, trade_id: str, ordertype: Optional[str] = None) -> Dict[str, str]: """ - Handler for forcesell . + Handler for forceexit . Sells the given trade at current price """ - def _exec_forcesell(trade: Trade) -> None: + def _exec_force_exit(trade: Trade) -> None: # Check if there is there is an open order fully_canceled = False if trade.open_order_id: order = self._freqtrade.exchange.fetch_order(trade.open_order_id, trade.pair) - if order['side'] == trade.enter_side: + if order['side'] == trade.entry_side: fully_canceled = self._freqtrade.handle_cancel_enter( - trade, order, CANCEL_REASON['FORCE_SELL']) + trade, order, CANCEL_REASON['FORCE_EXIT']) if order['side'] == trade.exit_side: # Cancel order - so it is placed anew with a fresh price. - self._freqtrade.handle_cancel_exit(trade, order, CANCEL_REASON['FORCE_SELL']) + self._freqtrade.handle_cancel_exit(trade, order, CANCEL_REASON['FORCE_EXIT']) if not fully_canceled: # Get current rate and execute sell current_rate = self._freqtrade.exchange.get_rate( trade.pair, side='exit', is_short=trade.is_short, refresh=True) - exit_check = ExitCheckTuple(exit_type=ExitType.FORCE_SELL) + exit_check = ExitCheckTuple(exit_type=ExitType.FORCE_EXIT) order_type = ordertype or self._freqtrade.strategy.order_types.get( - "forceexit", self._freqtrade.strategy.order_types["exit"]) + "force_exit", self._freqtrade.strategy.order_types["exit"]) self._freqtrade.execute_trade_exit( trade, current_rate, exit_check, ordertype=order_type) @@ -722,7 +733,7 @@ class RPC: if trade_id == 'all': # Execute sell for all open orders for trade in Trade.get_open_trades(): - _exec_forcesell(trade) + _exec_force_exit(trade) Trade.commit() self._freqtrade.wallets.update() return {'result': 'Created sell orders for all open trades.'} @@ -732,10 +743,10 @@ class RPC: trade_filter=[Trade.id == trade_id, Trade.is_open.is_(True), ] ).first() if not trade: - logger.warning('forceexit: Invalid argument received') + logger.warning('force_exit: Invalid argument received') raise RPCException('invalid argument') - _exec_forcesell(trade) + _exec_force_exit(trade) Trade.commit() self._freqtrade.wallets.update() return {'result': f'Created sell order for trade {trade_id}.'} @@ -744,14 +755,14 @@ class RPC: order_type: Optional[str] = None, order_side: SignalDirection = SignalDirection.LONG, stake_amount: Optional[float] = None, - enter_tag: Optional[str] = 'forceentry') -> Optional[Trade]: + enter_tag: Optional[str] = 'force_entry') -> Optional[Trade]: """ Handler for forcebuy Buys a pair trade at the given or current price """ - if not self._freqtrade.config.get('forcebuy_enable', False): - raise RPCException('Forceentry not enabled.') + if not self._freqtrade.config.get('force_entry_enable', False): + raise RPCException('Force_entry not enabled.') if self._freqtrade.state != State.RUNNING: raise RPCException('trader is not running') @@ -781,7 +792,7 @@ class RPC: # execute buy if not order_type: order_type = self._freqtrade.strategy.order_types.get( - 'forceentry', self._freqtrade.strategy.order_types['entry']) + 'force_entry', self._freqtrade.strategy.order_types['entry']) if self._freqtrade.execute_entry(pair, stake_amount, price, ordertype=order_type, trade=trade, is_short=is_short, @@ -791,7 +802,7 @@ class RPC: trade = Trade.get_trades([Trade.is_open.is_(True), Trade.pair == pair]).first() return trade else: - return None + raise RPCException(f'Failed to enter position for {pair}.') def _rpc_delete(self, trade_id: int) -> Dict[str, Union[str, int]]: """ @@ -848,16 +859,16 @@ class RPC: """ return Trade.get_enter_tag_performance(pair) - def _rpc_sell_reason_performance(self, pair: Optional[str]) -> List[Dict[str, Any]]: + def _rpc_exit_reason_performance(self, pair: Optional[str]) -> List[Dict[str, Any]]: """ - Handler for sell reason performance. + Handler for exit reason performance. Shows a performance statistic from finished trades """ - return Trade.get_sell_reason_performance(pair) + return Trade.get_exit_reason_performance(pair) def _rpc_mix_tag_performance(self, pair: Optional[str]) -> List[Dict[str, Any]]: """ - Handler for mix tag (enter_tag + sell_reason) performance. + Handler for mix tag (enter_tag + exit_reason) performance. Shows a performance statistic from finished trades """ mix_tags = Trade.get_mix_tag_performance(pair) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 20ab86aeb..1a9be4503 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -103,18 +103,19 @@ class Telegram(RPCHandler): ['/count', '/start', '/stop', '/help'] ] # do not allow commands with mandatory arguments and critical cmds - # like /forcesell and /forcebuy # TODO: DRY! - its not good to list all valid cmds here. But otherwise # this needs refactoring of the whole telegram module (same # problem in _help()). valid_keys: List[str] = [r'/start$', r'/stop$', r'/status$', r'/status table$', - r'/trades$', r'/performance$', r'/buys', r'/sells', r'/mix_tags', + r'/trades$', r'/performance$', r'/buys', r'/entries', + r'/sells', r'/exits', r'/mix_tags', r'/daily$', r'/daily \d+$', r'/profit$', r'/profit \d+', r'/stats$', r'/count$', r'/locks$', r'/balance$', r'/stopbuy$', r'/reload_config$', r'/show_config$', r'/logs$', r'/whitelist$', r'/blacklist$', r'/bl_delete$', r'/weekly$', r'/weekly \d+$', r'/monthly$', r'/monthly \d+$', r'/forcebuy$', r'/forcelong$', r'/forceshort$', + r'/forcesell$', r'/forceexit$', r'/edge$', r'/health$', r'/help$', r'/version$'] # Create keys for generation valid_keys_print = [k.replace('$', '') for k in valid_keys] @@ -152,16 +153,16 @@ class Telegram(RPCHandler): CommandHandler('balance', self._balance), CommandHandler('start', self._start), CommandHandler('stop', self._stop), - CommandHandler(['forcesell', 'forceexit'], self._forceexit), + CommandHandler(['forcesell', 'forceexit', 'fx'], self._force_exit), CommandHandler(['forcebuy', 'forcelong'], partial( - self._forceenter, order_side=SignalDirection.LONG)), + self._force_enter, order_side=SignalDirection.LONG)), CommandHandler('forceshort', partial( - self._forceenter, order_side=SignalDirection.SHORT)), + self._force_enter, order_side=SignalDirection.SHORT)), CommandHandler('trades', self._trades), CommandHandler('delete', self._delete_trade), CommandHandler('performance', self._performance), CommandHandler(['buys', 'entries'], self._enter_tag_performance), - CommandHandler('sells', self._sell_reason_performance), + CommandHandler(['sells', 'exits'], self._exit_reason_performance), CommandHandler('mix_tags', self._mix_tag_performance), CommandHandler('stats', self._stats), CommandHandler('daily', self._daily), @@ -192,11 +193,12 @@ class Telegram(RPCHandler): CallbackQueryHandler(self._performance, pattern='update_performance'), CallbackQueryHandler(self._enter_tag_performance, pattern='update_enter_tag_performance'), - CallbackQueryHandler(self._sell_reason_performance, - pattern='update_sell_reason_performance'), + CallbackQueryHandler(self._exit_reason_performance, + pattern='update_exit_reason_performance'), CallbackQueryHandler(self._mix_tag_performance, pattern='update_mix_tag_performance'), CallbackQueryHandler(self._count, pattern='update_count'), - CallbackQueryHandler(self._forceenter_inline), + CallbackQueryHandler(self._force_exit_inline, pattern=r"force_exit__\S+"), + CallbackQueryHandler(self._force_enter_inline, pattern=r"\S+\/\S+"), ] for handle in handles: self._updater.dispatcher.add_handler(handle) @@ -223,21 +225,20 @@ class Telegram(RPCHandler): # This can take up to `timeout` from the call to `start_polling`. self._updater.stop() - def _format_buy_msg(self, msg: Dict[str, Any]) -> str: + def _format_entry_msg(self, msg: Dict[str, Any]) -> str: if self._rpc._fiat_converter: msg['stake_amount_fiat'] = self._rpc._fiat_converter.convert_amount( msg['stake_amount'], msg['stake_currency'], msg['fiat_currency']) else: msg['stake_amount_fiat'] = 0 - is_fill = msg['type'] in [RPCMessageType.BUY_FILL, RPCMessageType.SHORT_FILL] + is_fill = msg['type'] in [RPCMessageType.ENTRY_FILL] emoji = '\N{CHECK MARK}' if is_fill else '\N{LARGE BLUE CIRCLE}' - enter_side = ({'enter': 'Long', 'entered': 'Longed'} if msg['type'] - in [RPCMessageType.BUY_FILL, RPCMessageType.BUY] + entry_side = ({'enter': 'Long', 'entered': 'Longed'} if msg['direction'] == 'Long' else {'enter': 'Short', 'entered': 'Shorted'}) message = ( f"{emoji} *{msg['exchange']}:*" - f" {enter_side['entered'] if is_fill else enter_side['enter']} {msg['pair']}" + f" {entry_side['entered'] if is_fill else entry_side['enter']} {msg['pair']}" f" (#{msg['trade_id']})\n" ) message += f"*Enter Tag:* `{msg['enter_tag']}`\n" if msg.get('enter_tag', None) else "" @@ -245,9 +246,9 @@ class Telegram(RPCHandler): if msg.get('leverage') and msg.get('leverage', 1.0) != 1.0: message += f"*Leverage:* `{msg['leverage']}`\n" - if msg['type'] in [RPCMessageType.BUY_FILL, RPCMessageType.SHORT_FILL]: + if msg['type'] in [RPCMessageType.ENTRY_FILL]: message += f"*Open Rate:* `{msg['open_rate']:.8f}`\n" - elif msg['type'] in [RPCMessageType.BUY, RPCMessageType.SHORT]: + elif msg['type'] in [RPCMessageType.ENTRY]: message += f"*Open Rate:* `{msg['limit']:.8f}`\n"\ f"*Current Rate:* `{msg['current_rate']:.8f}`\n" @@ -259,7 +260,7 @@ class Telegram(RPCHandler): message += ")`" return message - def _format_sell_msg(self, msg: Dict[str, Any]) -> str: + def _format_exit_msg(self, msg: Dict[str, Any]) -> str: msg['amount'] = round(msg['amount'], 8) msg['profit_percent'] = round(msg['profit_ratio'] * 100, 2) msg['duration'] = msg['close_date'].replace( @@ -273,7 +274,7 @@ class Telegram(RPCHandler): else "") # Check if all sell properties are available. - # This might not be the case if the message origin is triggered by /forcesell + # This might not be the case if the message origin is triggered by /forceexit if (all(prop in msg for prop in ['gain', 'fiat_currency', 'stake_currency']) and self._rpc._fiat_converter): msg['profit_fiat'] = self._rpc._fiat_converter.convert_amount( @@ -283,41 +284,38 @@ class Telegram(RPCHandler): f" / {msg['profit_fiat']:.3f} {msg['fiat_currency']})") else: msg['profit_extra'] = '' - is_fill = msg['type'] == RPCMessageType.SELL_FILL + is_fill = msg['type'] == RPCMessageType.EXIT_FILL message = ( f"{msg['emoji']} *{msg['exchange']}:* " f"{'Exited' if is_fill else 'Exiting'} {msg['pair']} (#{msg['trade_id']})\n" f"*{'Profit' if is_fill else 'Unrealized Profit'}:* " f"`{msg['profit_ratio']:.2%}{msg['profit_extra']}`\n" f"*Enter Tag:* `{msg['enter_tag']}`\n" - f"*Exit Reason:* `{msg['sell_reason']}`\n" + f"*Exit Reason:* `{msg['exit_reason']}`\n" f"*Duration:* `{msg['duration']} ({msg['duration_min']:.1f} min)`\n" f"*Direction:* `{msg['direction']}`\n" f"{msg['leverage_text']}" f"*Amount:* `{msg['amount']:.8f}`\n" f"*Open Rate:* `{msg['open_rate']:.8f}`\n" ) - if msg['type'] == RPCMessageType.SELL: + if msg['type'] == RPCMessageType.EXIT: message += (f"*Current Rate:* `{msg['current_rate']:.8f}`\n" f"*Close Rate:* `{msg['limit']:.8f}`") - elif msg['type'] == RPCMessageType.SELL_FILL: + elif msg['type'] == RPCMessageType.EXIT_FILL: message += f"*Close Rate:* `{msg['close_rate']:.8f}`" return message def compose_message(self, msg: Dict[str, Any], msg_type: RPCMessageType) -> str: - if msg_type in [RPCMessageType.BUY, RPCMessageType.BUY_FILL, RPCMessageType.SHORT, - RPCMessageType.SHORT_FILL]: - message = self._format_buy_msg(msg) + if msg_type in [RPCMessageType.ENTRY, RPCMessageType.ENTRY_FILL]: + message = self._format_entry_msg(msg) - elif msg_type in [RPCMessageType.SELL, RPCMessageType.SELL_FILL]: - message = self._format_sell_msg(msg) + elif msg_type in [RPCMessageType.EXIT, RPCMessageType.EXIT_FILL]: + message = self._format_exit_msg(msg) - elif msg_type in (RPCMessageType.BUY_CANCEL, RPCMessageType.SHORT_CANCEL, - RPCMessageType.SELL_CANCEL): - msg['message_side'] = 'enter' if msg_type in [RPCMessageType.BUY_CANCEL, - RPCMessageType.SHORT_CANCEL] else 'exit' + elif msg_type in (RPCMessageType.ENTRY_CANCEL, RPCMessageType.EXIT_CANCEL): + msg['message_side'] = 'enter' if msg_type in [RPCMessageType.ENTRY_CANCEL] else 'exit' message = ("\N{WARNING SIGN} *{exchange}:* " "Cancelling {message_side} Order for {pair} (#{trade_id}). " "Reason: {reason}.".format(**msg)) @@ -354,14 +352,14 @@ class Telegram(RPCHandler): msg_type = msg['type'] noti = '' - if msg_type == RPCMessageType.SELL: + if msg_type == RPCMessageType.EXIT: sell_noti = self._config['telegram'] \ .get('notification_settings', {}).get(str(msg_type), {}) # For backward compatibility sell still can be string if isinstance(sell_noti, str): noti = sell_noti else: - noti = sell_noti.get(str(msg['sell_reason']), default_noti) + noti = sell_noti.get(str(msg['exit_reason']), default_noti) else: noti = self._config['telegram'] \ .get('notification_settings', {}).get(str(msg_type), default_noti) @@ -384,12 +382,12 @@ class Telegram(RPCHandler): return "\N{ROCKET}" elif float(msg['profit_percent']) >= 0.0: return "\N{EIGHT SPOKED ASTERISK}" - elif msg['sell_reason'] == "stop_loss": + elif msg['exit_reason'] == "stop_loss": return "\N{WARNING SIGN}" 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 """ @@ -407,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 @@ -421,7 +419,8 @@ class Telegram(RPCHandler): if prev_avg_price: minus_on_entry = (cur_entry_average - prev_avg_price) / prev_avg_price - dur_entry = cur_entry_datetime - arrow.get(filled_orders[x-1]["order_filled_date"]) + dur_entry = cur_entry_datetime - arrow.get( + filled_orders[x - 1]["order_filled_date"]) days = dur_entry.days hours, remainder = divmod(dur_entry.seconds, 3600) minutes, seconds = divmod(remainder, 60) @@ -430,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']}") @@ -466,16 +465,16 @@ class Telegram(RPCHandler): for r in results: r['open_date_hum'] = arrow.get(r['open_date']).humanize() r['num_entries'] = len([o for o in r['orders'] if o['ft_is_entry']]) - r['sell_reason'] = r.get('sell_reason', "") + r['exit_reason'] = r.get('exit_reason', "") lines = [ "*Trade ID:* `{trade_id}`" + ("` (since {open_date_hum})`" if r['is_open'] else ""), "*Current Pair:* {pair}", "*Direction:* " + ("`Short`" if r.get('is_short') else "`Long`"), "*Leverage:* `{leverage}`" if r.get('leverage') else "", - "*Amount:* `{amount} ({stake_amount} {base_currency})`", + "*Amount:* `{amount} ({stake_amount} {quote_currency})`", "*Enter Tag:* `{enter_tag}`" if r['enter_tag'] else "", - "*Exit Reason:* `{sell_reason}`" if r['sell_reason'] else "", + "*Exit Reason:* `{exit_reason}`" if r['exit_reason'] else "", ] if position_adjust: @@ -505,13 +504,13 @@ class Telegram(RPCHandler): lines.append("*Stoploss distance:* `{stoploss_current_dist:.8f}` " "`({stoploss_current_dist_ratio:.2%})`") if r['open_order']: - if r['sell_order_status']: - lines.append("*Open Order:* `{open_order}` - `{sell_order_status}`") + if r['exit_order_status']: + lines.append("*Open Order:* `{open_order}` - `{exit_order_status}`") else: lines.append("*Open Order:* `{open_order}`") lines_detail = self._prepare_entry_details( - r['orders'], r['base_currency'], r['is_open']) + r['orders'], r['quote_currency'], r['is_open']) lines.extend(lines_detail if lines_detail else "") # Filter empty lines using list-comprehension @@ -767,27 +766,27 @@ class Telegram(RPCHandler): 'stop_loss': 'Stoploss', 'trailing_stop_loss': 'Trail. Stop', 'stoploss_on_exchange': 'Stoploss', - 'sell_signal': 'Sell Signal', - 'force_sell': 'Forcesell', - 'emergency_sell': 'Emergency Sell', + 'exit_signal': 'Exit Signal', + 'force_exit': 'Force Exit', + 'emergency_exit': 'Emergency Exit', } - sell_reasons_tabulate = [ + exit_reasons_tabulate = [ [ reason_map.get(reason, reason), sum(count.values()), count['wins'], count['losses'] - ] for reason, count in stats['sell_reasons'].items() + ] for reason, count in stats['exit_reasons'].items() ] - sell_reasons_msg = 'No trades yet.' - for reason in chunks(sell_reasons_tabulate, 25): - sell_reasons_msg = tabulate( + exit_reasons_msg = 'No trades yet.' + for reason in chunks(exit_reasons_tabulate, 25): + exit_reasons_msg = tabulate( reason, - headers=['Sell Reason', 'Sells', 'Wins', 'Losses'] + headers=['Exit Reason', 'Exits', 'Wins', 'Losses'] ) - if len(sell_reasons_tabulate) > 25: - self._send_msg(sell_reasons_msg, ParseMode.MARKDOWN) - sell_reasons_msg = '' + if len(exit_reasons_tabulate) > 25: + self._send_msg(exit_reasons_msg, ParseMode.MARKDOWN) + exit_reasons_msg = '' durations = stats['durations'] duration_msg = tabulate( @@ -799,7 +798,7 @@ class Telegram(RPCHandler): ], headers=['', 'Avg. Duration'] ) - msg = (f"""```\n{sell_reasons_msg}```\n```\n{duration_msg}```""") + msg = (f"""```\n{exit_reasons_msg}```\n```\n{duration_msg}```""") self._send_msg(msg, ParseMode.MARKDOWN) @@ -929,34 +928,69 @@ class Telegram(RPCHandler): self._send_msg('Status: `{status}`'.format(**msg)) @authorized_only - def _forceexit(self, update: Update, context: CallbackContext) -> None: + def _force_exit(self, update: Update, context: CallbackContext) -> None: """ - Handler for /forcesell . + Handler for /forceexit . Sells the given trade at current price :param bot: telegram bot :param update: message update :return: None """ - trade_id = context.args[0] if context.args and len(context.args) > 0 else None - if not trade_id: - self._send_msg("You must specify a trade-id or 'all'.") - return - try: - msg = self._rpc._rpc_forceexit(trade_id) - self._send_msg('Forceexit Result: `{result}`'.format(**msg)) + if context.args: + trade_id = context.args[0] + self._force_exit_action(trade_id) + else: + fiat_currency = self._config.get('fiat_display_currency', '') + try: + statlist, _, _ = self._rpc._rpc_status_table( + self._config['stake_currency'], fiat_currency) + except RPCException: + self._send_msg(msg='No open trade found.') + return + trades = [] + for trade in statlist: + trades.append((trade[0], f"{trade[0]} {trade[1]} {trade[2]} {trade[3]}")) - except RPCException as e: - self._send_msg(str(e)) + trade_buttons = [ + InlineKeyboardButton(text=trade[1], callback_data=f"force_exit__{trade[0]}") + for trade in trades] + buttons_aligned = self._layout_inline_keyboard_onecol(trade_buttons) - def _forceenter_action(self, pair, price: Optional[float], order_side: SignalDirection): + buttons_aligned.append([InlineKeyboardButton( + text='Cancel', callback_data='force_exit__cancel')]) + self._send_msg(msg="Which trade?", keyboard=buttons_aligned) + + def _force_exit_action(self, trade_id): + if trade_id != 'cancel': + try: + self._rpc._rpc_force_exit(trade_id) + except RPCException as e: + self._send_msg(str(e)) + + def _force_exit_inline(self, update: Update, _: CallbackContext) -> None: + if update.callback_query: + query = update.callback_query + if query.data and '__' in query.data: + # Input data is "force_exit__" + trade_id = query.data.split("__")[1].split(' ')[0] + if trade_id == 'cancel': + query.answer() + query.edit_message_text(text="Force exit canceled.") + return + trade: Trade = Trade.get_trades(trade_filter=Trade.id == trade_id).first() + query.answer() + query.edit_message_text(text=f"Manually exiting Trade #{trade_id}, {trade.pair}") + self._force_exit_action(trade_id) + + def _force_enter_action(self, pair, price: Optional[float], order_side: SignalDirection): if pair != 'cancel': try: self._rpc._rpc_force_entry(pair, price, order_side=order_side) except RPCException as e: self._send_msg(str(e)) - def _forceenter_inline(self, update: Update, _: CallbackContext) -> None: + def _force_enter_inline(self, update: Update, _: CallbackContext) -> None: if update.callback_query: query = update.callback_query if query.data and '_||_' in query.data: @@ -964,15 +998,20 @@ class Telegram(RPCHandler): order_side = SignalDirection(side) query.answer() query.edit_message_text(text=f"Manually entering {order_side} for {pair}") - self._forceenter_action(pair, None, order_side) + self._force_enter_action(pair, None, order_side) @staticmethod - def _layout_inline_keyboard(buttons: List[InlineKeyboardButton], - cols=3) -> List[List[InlineKeyboardButton]]: + def _layout_inline_keyboard( + buttons: List[InlineKeyboardButton], cols=3) -> List[List[InlineKeyboardButton]]: + return [buttons[i:i + cols] for i in range(0, len(buttons), cols)] + + @staticmethod + def _layout_inline_keyboard_onecol( + buttons: List[InlineKeyboardButton], cols=1) -> List[List[InlineKeyboardButton]]: return [buttons[i:i + cols] for i in range(0, len(buttons), cols)] @authorized_only - def _forceenter( + def _force_enter( self, update: Update, context: CallbackContext, order_side: SignalDirection) -> None: """ Handler for /forcelong and `/forceshort @@ -984,7 +1023,7 @@ class Telegram(RPCHandler): if context.args: pair = context.args[0] price = float(context.args[1]) if len(context.args) > 1 else None - self._forceenter_action(pair, price, order_side) + self._force_enter_action(pair, price, order_side) else: whitelist = self._rpc._rpc_whitelist()['whitelist'] pair_buttons = [ @@ -1101,7 +1140,7 @@ class Telegram(RPCHandler): pair = context.args[0] trades = self._rpc._rpc_enter_tag_performance(pair) - output = "Buy Tag Performance:\n" + output = "Entry Tag Performance:\n" for i, trade in enumerate(trades): stat_line = ( f"{i+1}.\t {trade['enter_tag']}\t" @@ -1122,7 +1161,7 @@ class Telegram(RPCHandler): self._send_msg(str(e)) @authorized_only - def _sell_reason_performance(self, update: Update, context: CallbackContext) -> None: + def _exit_reason_performance(self, update: Update, context: CallbackContext) -> None: """ Handler for /sells. Shows a performance statistic from finished trades @@ -1135,11 +1174,11 @@ class Telegram(RPCHandler): if context.args and isinstance(context.args[0], str): pair = context.args[0] - trades = self._rpc._rpc_sell_reason_performance(pair) - output = "Sell Reason Performance:\n" + trades = self._rpc._rpc_exit_reason_performance(pair) + output = "Exit Reason Performance:\n" for i, trade in enumerate(trades): stat_line = ( - f"{i+1}.\t {trade['sell_reason']}\t" + f"{i+1}.\t {trade['exit_reason']}\t" f"{round_coin_value(trade['profit_abs'], self._config['stake_currency'])} " f"({trade['profit_ratio']:.2%}) " f"({trade['count']})\n") @@ -1151,7 +1190,7 @@ class Telegram(RPCHandler): output += stat_line self._send_msg(output, parse_mode=ParseMode.HTML, - reload_able=True, callback_path="update_sell_reason_performance", + reload_able=True, callback_path="update_exit_reason_performance", query=update.callback_query) except RPCException as e: self._send_msg(str(e)) @@ -1362,14 +1401,14 @@ class Telegram(RPCHandler): :param update: message update :return: None """ - forceenter_text = ("*/forcelong []:* `Instantly buys the given pair. " - "Optionally takes a rate at which to buy " - "(only applies to limit orders).` \n" - ) + force_enter_text = ("*/forcelong []:* `Instantly buys the given pair. " + "Optionally takes a rate at which to buy " + "(only applies to limit orders).` \n" + ) if self._rpc._freqtrade.trading_mode != TradingMode.SPOT: - forceenter_text += ("*/forceshort []:* `Instantly shorts the given pair. " - "Optionally takes a rate at which to sell " - "(only applies to limit orders).` \n") + force_enter_text += ("*/forceshort []:* `Instantly shorts the given pair. " + "Optionally takes a rate at which to sell " + "(only applies to limit orders).` \n") message = ( "_BotControl_\n" "------------\n" @@ -1378,7 +1417,8 @@ class Telegram(RPCHandler): "*/stopbuy:* `Stops buying, but handles open trades gracefully` \n" "*/forceexit |all:* `Instantly exits the given trade or all trades, " "regardless of profit`\n" - f"{forceenter_text if self._config.get('forcebuy_enable', False) else ''}" + "*/fe |all:* `Alias to /forceexit`" + f"{force_enter_text if self._config.get('force_entry_enable', False) else ''}" "*/delete :* `Instantly delete the given trade in the database`\n" "*/whitelist:* `Show current whitelist` \n" "*/blacklist [pair]:* `Show current blacklist, or adds one or more pairs " @@ -1407,8 +1447,8 @@ class Telegram(RPCHandler): " `pending buy orders are marked with an asterisk (*)`\n" " `pending sell orders are marked with a double asterisk (**)`\n" "*/buys :* `Shows the enter_tag performance`\n" - "*/sells :* `Shows the sell reason performance`\n" - "*/mix_tags :* `Shows combined buy tag + sell reason performance`\n" + "*/sells :* `Shows the exit reason performance`\n" + "*/mix_tags :* `Shows combined entry tag + exit reason performance`\n" "*/trades [limit]:* `Lists last closed trades (limited to 10 by default)`\n" "*/profit []:* `Lists cumulative profit from all finished trades, " "over the last n days`\n" diff --git a/freqtrade/rpc/webhook.py b/freqtrade/rpc/webhook.py index b0a884a88..a2edcbc85 100644 --- a/freqtrade/rpc/webhook.py +++ b/freqtrade/rpc/webhook.py @@ -43,23 +43,23 @@ class Webhook(RPCHandler): def send_msg(self, msg: Dict[str, Any]) -> None: """ Send a message to telegram channel """ try: - - if msg['type'] in [RPCMessageType.BUY, RPCMessageType.SHORT]: - valuedict = self._config['webhook'].get('webhookbuy', None) - elif msg['type'] in [RPCMessageType.BUY_CANCEL, RPCMessageType.SHORT_CANCEL]: - valuedict = self._config['webhook'].get('webhookbuycancel', None) - elif msg['type'] in [RPCMessageType.BUY_FILL, RPCMessageType.SHORT_FILL]: - valuedict = self._config['webhook'].get('webhookbuyfill', None) - elif msg['type'] == RPCMessageType.SELL: - valuedict = self._config['webhook'].get('webhooksell', None) - elif msg['type'] == RPCMessageType.SELL_FILL: - valuedict = self._config['webhook'].get('webhooksellfill', None) - elif msg['type'] == RPCMessageType.SELL_CANCEL: - valuedict = self._config['webhook'].get('webhooksellcancel', None) + whconfig = self._config['webhook'] + if msg['type'] in [RPCMessageType.ENTRY]: + valuedict = whconfig.get('webhookentry', None) + elif msg['type'] in [RPCMessageType.ENTRY_CANCEL]: + valuedict = whconfig.get('webhookentrycancel', None) + elif msg['type'] in [RPCMessageType.ENTRY_FILL]: + valuedict = whconfig.get('webhookentryfill', None) + elif msg['type'] == RPCMessageType.EXIT: + valuedict = whconfig.get('webhookexit', None) + elif msg['type'] == RPCMessageType.EXIT_FILL: + valuedict = whconfig.get('webhookexitfill', None) + elif msg['type'] == RPCMessageType.EXIT_CANCEL: + valuedict = whconfig.get('webhookexitcancel', None) elif msg['type'] in (RPCMessageType.STATUS, RPCMessageType.STARTUP, RPCMessageType.WARNING): - valuedict = self._config['webhook'].get('webhookstatus', None) + valuedict = whconfig.get('webhookstatus', None) else: raise NotImplementedError('Unknown message type: {}'.format(msg['type'])) if not valuedict: 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 06fa121b3..57afbf32a 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 @@ -16,10 +15,8 @@ from freqtrade.data.dataprovider import DataProvider from freqtrade.enums import (CandleType, ExitCheckTuple, ExitType, SignalDirection, SignalTagType, SignalType, TradingMode) from freqtrade.exceptions import OperationalException, StrategyError -from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds -from freqtrade.exchange.exchange import timeframe_to_next_date -from freqtrade.persistence import PairLocks, Trade -from freqtrade.persistence.models import LocalTrade, Order +from freqtrade.exchange import timeframe_to_minutes, timeframe_to_next_date, timeframe_to_seconds +from freqtrade.persistence import LocalTrade, Order, PairLocks, Trade from freqtrade.strategy.hyper import HyperStrategyMixin from freqtrade.strategy.informative_decorator import (InformativeData, PopulateIndicators, _create_and_merge_informative_pair, @@ -44,14 +41,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 = {} @@ -90,10 +84,10 @@ class IStrategy(ABC, HyperStrategyMixin): # run "populate_indicators" only for new candle process_only_new_candles: bool = False - use_sell_signal: bool - sell_profit_only: bool - sell_profit_offset: float - ignore_roi_if_buy_signal: bool + use_exit_signal: bool + exit_profit_only: bool + exit_profit_offset: float + ignore_roi_if_entry_signal: bool # Position adjustment is disabled by default position_adjustment_enable: bool = False @@ -114,7 +108,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 @@ -197,6 +191,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). @@ -206,18 +207,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 +226,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 +235,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) @@ -308,10 +309,10 @@ class IStrategy(ABC, HyperStrategyMixin): :param time_in_force: Time in force. Defaults to GTC (Good-til-cancelled). :param exit_reason: Exit reason. Can be any of ['roi', 'stop_loss', 'stoploss_on_exchange', 'trailing_stop_loss', - 'sell_signal', 'force_sell', 'emergency_sell'] + 'exit_signal', 'force_exit', 'emergency_exit'] :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, then the sell-order/exit_short-order is placed on the exchange. + :return bool: When True, then the exit-order is placed on the exchange. False aborts the process """ return True @@ -339,7 +340,7 @@ class IStrategy(ABC, HyperStrategyMixin): return self.stoploss def custom_entry_price(self, pair: str, current_time: datetime, proposed_rate: float, - entry_tag: Optional[str], **kwargs) -> float: + entry_tag: Optional[str], side: str, **kwargs) -> float: """ Custom entry price logic, returning the new entry price. @@ -351,6 +352,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 entry_tag: Optional entry_tag (buy_tag) if provided with the buy signal. + :param side: 'long' or 'short' - indicating the direction of the proposed trade :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. :return float: New entry price value if provided """ @@ -358,7 +360,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. @@ -371,6 +373,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 """ @@ -396,7 +399,7 @@ class IStrategy(ABC, HyperStrategyMixin): :param current_rate: Rate, calculated based on pricing settings in exit_pricing. :param current_profit: Current profit (as ratio), calculated based on current_rate. :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. - :return: To execute exit, return a string with custom sell reason or True. Otherwise return + :return: To execute exit, return a string with custom exit reason or True. Otherwise return None or False. """ return None @@ -420,7 +423,7 @@ class IStrategy(ABC, HyperStrategyMixin): :param current_rate: Rate, calculated based on pricing settings in exit_pricing. :param current_profit: Current profit (as ratio), calculated based on current_rate. :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. - :return: To execute exit, return a string with custom sell reason or True. Otherwise return + :return: To execute exit, return a string with custom exit reason or True. Otherwise return None or False. """ return self.custom_sell(pair, trade, current_time, current_rate, current_profit, **kwargs) @@ -466,6 +469,34 @@ class IStrategy(ABC, HyperStrategyMixin): """ return None + def adjust_entry_price(self, trade: Trade, order: Optional[Order], pair: str, + current_time: datetime, proposed_rate: float, current_order_rate: float, + entry_tag: Optional[str], side: str, **kwargs) -> float: + """ + Entry price re-adjustment logic, returning the user desired limit price. + This only executes when a order was already placed, still open (unfilled fully or partially) + and not timed out on subsequent candles after entry trigger. + + For full documentation please go to https://www.freqtrade.io/en/latest/strategy-callbacks/ + + When not implemented by a strategy, returns current_order_rate as default. + If current_order_rate is returned then the existing order is maintained. + If None is returned then order gets canceled but not replaced by a new one. + + :param pair: Pair that's currently analyzed + :param trade: Trade object. + :param order: Order object + :param current_time: datetime object, containing the current datetime + :param proposed_rate: Rate, calculated based on pricing settings in entry_pricing. + :param current_order_rate: Rate of the existing order in place. + :param entry_tag: Optional entry_tag (buy_tag) if provided with the buy signal. + :param side: 'long' or 'short' - indicating the direction of the proposed trade + :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. + :return float: New entry price value if provided + + """ + return current_order_rate + def leverage(self, pair: str, current_time: datetime, current_rate: float, proposed_leverage: float, max_leverage: float, side: str, **kwargs) -> float: @@ -540,7 +571,7 @@ class IStrategy(ABC, HyperStrategyMixin): """ return self.__class__.__name__ - def lock_pair(self, pair: str, until: datetime, reason: str = None) -> None: + def lock_pair(self, pair: str, until: datetime, reason: str = None, side: str = '*') -> None: """ Locks pair until a given timestamp happens. Locked pairs are not analyzed, and are prevented from opening new trades. @@ -550,8 +581,9 @@ class IStrategy(ABC, HyperStrategyMixin): :param until: datetime in UTC until the pair should be blocked from opening new trades. Needs to be timezone aware `datetime.now(timezone.utc)` :param reason: Optional string explaining why the pair was locked. + :param side: Side to check, can be long, short or '*' """ - PairLocks.lock_pair(pair, until, reason) + PairLocks.lock_pair(pair, until, reason, side=side) def unlock_pair(self, pair: str) -> None: """ @@ -571,7 +603,7 @@ class IStrategy(ABC, HyperStrategyMixin): """ PairLocks.unlock_reason(reason, datetime.now(timezone.utc)) - def is_pair_locked(self, pair: str, candle_date: datetime = None) -> bool: + def is_pair_locked(self, pair: str, *, candle_date: datetime = None, side: str = '*') -> bool: """ Checks if a pair is currently locked The 2nd, optional parameter ensures that locks are applied until the new candle arrives, @@ -579,15 +611,16 @@ class IStrategy(ABC, HyperStrategyMixin): of 2 seconds for an entry order to happen on an old signal. :param pair: "Pair to check" :param candle_date: Date of the last candle. Optional, defaults to current date + :param side: Side to check, can be long, short or '*' :returns: locking state of the pair in question. """ if not candle_date: # Simple call ... - return PairLocks.is_pair_locked(pair) + return PairLocks.is_pair_locked(pair, side=side) else: lock_time = timeframe_to_next_date(self.timeframe, candle_date) - return PairLocks.is_pair_locked(pair, lock_time) + return PairLocks.is_pair_locked(pair, lock_time, side=side) def analyze_ticker(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """ @@ -634,8 +667,6 @@ class IStrategy(ABC, HyperStrategyMixin): dataframe[SignalTagType.ENTER_TAG.value] = None dataframe[SignalTagType.EXIT_TAG.value] = None - # Other Defs in strategy that want to be called every loop here - # twitter_sell = self.watch_twitter_feed(dataframe, metadata) logger.debug("Loop Analysis Launched") return dataframe @@ -716,7 +747,7 @@ class IStrategy(ABC, HyperStrategyMixin): """ Calculates current signal based based on the entry order or exit order columns of the dataframe. - Used by Bot to get the signal to buy, sell, short, or exit_short + Used by Bot to get the signal to enter, or exit :param pair: pair in format ANT/BTC :param timeframe: timeframe to use :param dataframe: Analyzed dataframe to get signal from. @@ -750,7 +781,7 @@ class IStrategy(ABC, HyperStrategyMixin): is_short: bool = None ) -> Tuple[bool, bool, Optional[str]]: """ - Calculates current exit signal based based on the buy/short or sell/exit_short + Calculates current exit signal based based on the dataframe columns of the dataframe. Used by Bot to get the signal to exit. depending on is_short, looks at "short" or "long" columns. @@ -787,9 +818,9 @@ class IStrategy(ABC, HyperStrategyMixin): dataframe: DataFrame, ) -> Tuple[Optional[SignalDirection], Optional[str]]: """ - Calculates current entry signal based based on the buy/short or sell/exit_short + Calculates current entry signal based based on the dataframe signals columns of the dataframe. - Used by Bot to get the signal to buy, sell, short, or exit_short + Used by Bot to get the signal to enter trades. :param pair: pair in format ANT/BTC :param timeframe: timeframe to use :param dataframe: Analyzed dataframe to get signal from. @@ -867,59 +898,59 @@ class IStrategy(ABC, HyperStrategyMixin): current_profit=current_profit, force_stoploss=force_stoploss, low=low, high=high) - # Set current rate to high for backtesting sell + # Set current rate to high for backtesting exits current_rate = (low if trade.is_short else high) or rate current_profit = trade.calc_profit_ratio(current_rate) # if enter signal and ignore_roi is set, we don't need to evaluate min_roi. - roi_reached = (not (enter and self.ignore_roi_if_buy_signal) + roi_reached = (not (enter and self.ignore_roi_if_entry_signal) and self.min_roi_reached(trade=trade, current_profit=current_profit, current_time=current_time)) - sell_signal = ExitType.NONE + exit_signal = ExitType.NONE custom_reason = '' # use provided rate in backtesting, not high/low. current_rate = rate current_profit = trade.calc_profit_ratio(current_rate) - if (self.sell_profit_only and current_profit <= self.sell_profit_offset): - # sell_profit_only and profit doesn't reach the offset - ignore sell signal - pass - elif self.use_sell_signal and not enter: - if exit_: - sell_signal = ExitType.SELL_SIGNAL + if self.use_exit_signal: + if exit_ and not enter: + exit_signal = ExitType.EXIT_SIGNAL else: - trade_type = "exit_short" if trade.is_short else "sell" custom_reason = strategy_safe_wrapper(self.custom_exit, default_retval=False)( pair=trade.pair, trade=trade, current_time=current_time, current_rate=current_rate, current_profit=current_profit) if custom_reason: - sell_signal = ExitType.CUSTOM_SELL + exit_signal = ExitType.CUSTOM_EXIT if isinstance(custom_reason, str): if len(custom_reason) > CUSTOM_EXIT_MAX_LENGTH: - logger.warning(f'Custom {trade_type} reason returned from ' + logger.warning(f'Custom exit reason returned from ' f'custom_exit is too long and was trimmed' f'to {CUSTOM_EXIT_MAX_LENGTH} characters.') custom_reason = custom_reason[:CUSTOM_EXIT_MAX_LENGTH] else: custom_reason = None - if sell_signal in (ExitType.CUSTOM_SELL, ExitType.SELL_SIGNAL): + if ( + exit_signal == ExitType.CUSTOM_EXIT + or (exit_signal == ExitType.EXIT_SIGNAL + and (not self.exit_profit_only or current_profit > self.exit_profit_offset)) + ): logger.debug(f"{trade.pair} - Sell signal received. " - f"sell_type=ExitType.{sell_signal.name}" + + f"exit_type=ExitType.{exit_signal.name}" + (f", custom_reason={custom_reason}" if custom_reason else "")) - return ExitCheckTuple(exit_type=sell_signal, exit_reason=custom_reason) + return ExitCheckTuple(exit_type=exit_signal, exit_reason=custom_reason) # Sequence: # Exit-signal # ROI (if not stoploss) # Stoploss if roi_reached and stoplossflag.exit_type != ExitType.STOP_LOSS: - logger.debug(f"{trade.pair} - Required profit reached. sell_type=ExitType.ROI") + logger.debug(f"{trade.pair} - Required profit reached. exit_type=ExitType.ROI") return ExitCheckTuple(exit_type=ExitType.ROI) if stoplossflag.exit_flag: - logger.debug(f"{trade.pair} - Stoploss hit. sell_type={stoplossflag.exit_type}") + logger.debug(f"{trade.pair} - Stoploss hit. exit_type={stoplossflag.exit_type}") return stoplossflag # This one is noisy, commented out... @@ -988,11 +1019,11 @@ class IStrategy(ABC, HyperStrategyMixin): if ((sl_higher_long or sl_lower_short) and (not self.order_types.get('stoploss_on_exchange') or self.config['dry_run'])): - sell_type = ExitType.STOP_LOSS + exit_type = ExitType.STOP_LOSS # If initial stoploss is not the same as current one then it is trailing. if trade.initial_stop_loss != trade.stop_loss: - sell_type = ExitType.TRAILING_STOP_LOSS + exit_type = ExitType.TRAILING_STOP_LOSS logger.debug( f"{trade.pair} - HIT STOP: current price at " f"{((high if trade.is_short else low) or current_rate):.6f}, " @@ -1007,7 +1038,7 @@ class IStrategy(ABC, HyperStrategyMixin): logger.debug(f"{trade.pair} - Trailing stop saved " f"{new_stoploss:.6f}") - return ExitCheckTuple(exit_type=sell_type) + return ExitCheckTuple(exit_type=exit_type) return ExitCheckTuple(exit_type=ExitType.NONE) @@ -1027,9 +1058,9 @@ class IStrategy(ABC, HyperStrategyMixin): def min_roi_reached(self, trade: Trade, current_profit: float, current_time: datetime) -> bool: """ Based on trade duration, current profit of the trade and ROI configuration, - decides whether bot should sell. + decides whether bot should exit. :param current_profit: current profit as ratio - :return: True if bot should sell at current rate + :return: True if bot should exit at current rate """ # Check if time matches and current rate is above threshold trade_dur = int((current_time.timestamp() - trade.open_date_utc.timestamp()) // 60) @@ -1045,7 +1076,7 @@ class IStrategy(ABC, HyperStrategyMixin): FT Internal method. Check if timeout is active, and if the order is still open and timed out """ - side = 'entry' if order.ft_order_side == trade.enter_side else 'exit' + side = 'entry' if order.ft_order_side == trade.entry_side else 'exit' timeout = self.config.get('unfilledtimeout', {}).get(side) if timeout is not None: @@ -1091,12 +1122,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: """ @@ -1110,12 +1136,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') @@ -1128,16 +1149,10 @@ class IStrategy(ABC, HyperStrategyMixin): :param dataframe: DataFrame :param metadata: Additional information dictionary, with details like the currently traded pair - :return: DataFrame with sell column + :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 diff --git a/freqtrade/strategy/strategy_helper.py b/freqtrade/strategy/strategy_helper.py index f07c14e24..43728dc1f 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 @@ -93,9 +99,9 @@ def stoploss_from_open( return 1 if is_short is True: - stoploss = -1+((1-open_relative_stop)/(1-current_profit)) + stoploss = -1 + ((1 - open_relative_stop) / (1 - current_profit)) else: - stoploss = 1-((1+open_relative_stop)/(1+current_profit)) + stoploss = 1 - ((1 + open_relative_stop) / (1 + current_profit)) # negative stoploss values indicate the requested stop price is higher/lower # (long/short) than the current price diff --git a/freqtrade/templates/base_config.json.j2 b/freqtrade/templates/base_config.json.j2 index f1f611a45..914aa964b 100644 --- a/freqtrade/templates/base_config.json.j2 +++ b/freqtrade/templates/base_config.json.j2 @@ -72,7 +72,7 @@ }, "bot_name": "freqtrade", "initial_state": "running", - "forcebuy_enable": false, + "force_entry_enable": false, "internals": { "process_throttle_secs": 5 } diff --git a/freqtrade/templates/base_strategy.py.j2 b/freqtrade/templates/base_strategy.py.j2 index e5eecf7eb..9e7e1fe50 100644 --- a/freqtrade/templates/base_strategy.py.j2 +++ b/freqtrade/templates/base_strategy.py.j2 @@ -4,7 +4,9 @@ # --- Do not remove these libs --- import numpy as np # noqa import pandas as pd # noqa -from pandas import DataFrame +from pandas import DataFrame # noqa +from datetime import datetime # noqa +from typing import Optional # noqa from freqtrade.strategy import (BooleanParameter, CategoricalParameter, DecimalParameter, IStrategy, IntParameter) @@ -65,9 +67,9 @@ class {{ strategy }}(IStrategy): process_only_new_candles = False # These values can be overridden in the config. - use_sell_signal = True - sell_profit_only = False - ignore_roi_if_buy_signal = False + use_exit_signal = True + exit_profit_only = False + ignore_roi_if_entry_signal = False # Number of candles the strategy requires before producing valid signals startup_candle_count: int = 30 diff --git a/freqtrade/templates/sample_strategy.py b/freqtrade/templates/sample_strategy.py index 0c5c501cf..f0ae6c10d 100644 --- a/freqtrade/templates/sample_strategy.py +++ b/freqtrade/templates/sample_strategy.py @@ -65,9 +65,9 @@ class SampleStrategy(IStrategy): process_only_new_candles = False # These values can be overridden in the config. - use_sell_signal = True - sell_profit_only = False - ignore_roi_if_buy_signal = False + use_exit_signal = True + exit_profit_only = False + ignore_roi_if_entry_signal = False # Hyperoptable parameters buy_rsi = IntParameter(low=1, high=50, default=30, space='buy', optimize=True, load=True) diff --git a/freqtrade/templates/strategy_analysis_example.ipynb b/freqtrade/templates/strategy_analysis_example.ipynb index dc20d71b8..93e4b83ae 100644 --- a/freqtrade/templates/strategy_analysis_example.ipynb +++ b/freqtrade/templates/strategy_analysis_example.ipynb @@ -187,7 +187,7 @@ "trades = load_backtest_data(backtest_dir)\n", "\n", "# Show value-counts per pair\n", - "trades.groupby(\"pair\")[\"sell_reason\"].value_counts()" + "trades.groupby(\"pair\")[\"exit_reason\"].value_counts()" ] }, { @@ -257,7 +257,7 @@ "trades = load_trades_from_db(\"sqlite:///tradesv3.sqlite\")\n", "\n", "# Display results\n", - "trades.groupby(\"pair\")[\"sell_reason\"].value_counts()" + "trades.groupby(\"pair\")[\"exit_reason\"].value_counts()" ] }, { diff --git a/freqtrade/templates/subtemplates/exchange_bittrex.j2 b/freqtrade/templates/subtemplates/exchange_bittrex.j2 index 2d9afd578..023862314 100644 --- a/freqtrade/templates/subtemplates/exchange_bittrex.j2 +++ b/freqtrade/templates/subtemplates/exchange_bittrex.j2 @@ -1,7 +1,7 @@ "order_types": { "entry": "limit", "exit": "limit", - "emergencyexit": "limit", + "emergency_exit": "limit", "stoploss": "limit", "stoploss_on_exchange": false }, diff --git a/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 b/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 index b2dbb736d..317602da9 100644 --- a/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 +++ b/freqtrade/templates/subtemplates/strategy_methods_advanced.j2 @@ -13,7 +13,7 @@ def bot_loop_start(self, **kwargs) -> None: pass def custom_entry_price(self, pair: str, current_time: 'datetime', proposed_rate: float, - entry_tag: 'Optional[str]', **kwargs) -> float: + entry_tag: Optional[str], **kwargs) -> float: """ Custom entry price logic, returning the new entry price. @@ -30,9 +30,37 @@ def custom_entry_price(self, pair: str, current_time: 'datetime', proposed_rate: """ return proposed_rate +def adjust_entry_price(self, trade: 'Trade', order: 'Optional[Order]', pair: str, + current_time: datetime, proposed_rate: float, current_order_rate: float, + entry_tag: Optional[str], side: str, **kwargs) -> float: + """ + Entry price re-adjustment logic, returning the user desired limit price. + This only executes when a order was already placed, still open (unfilled fully or partially) + and not timed out on subsequent candles after entry trigger. + + For full documentation please go to https://www.freqtrade.io/en/latest/strategy-callbacks/ + + When not implemented by a strategy, returns current_order_rate as default. + If current_order_rate is returned then the existing order is maintained. + If None is returned then order gets canceled but not replaced by a new one. + + :param pair: Pair that's currently analyzed + :param trade: Trade object. + :param order: Order object + :param current_time: datetime object, containing the current datetime + :param proposed_rate: Rate, calculated based on pricing settings in entry_pricing. + :param current_order_rate: Rate of the existing order in place. + :param entry_tag: Optional entry_tag (buy_tag) if provided with the buy signal. + :param side: 'long' or 'short' - indicating the direction of the proposed trade + :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. + :return float: New entry price value if provided + + """ + return current_order_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 +73,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 """ @@ -52,7 +81,7 @@ def custom_exit_price(self, pair: str, trade: 'Trade', def custom_stake_amount(self, pair: str, current_time: 'datetime', current_rate: float, proposed_stake: float, min_stake: float, max_stake: float, - side: str, entry_tag: 'Optional[str]', **kwargs) -> float: + side: str, entry_tag: Optional[str], **kwargs) -> float: """ Customize stake size for each new trade. @@ -95,7 +124,7 @@ def custom_stoploss(self, pair: str, trade: 'Trade', current_time: 'datetime', def custom_exit(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float, current_profit: float, **kwargs) -> 'Optional[Union[str, bool]]': """ - Custom sell signal logic indicating that specified position should be sold. Returning a + Custom exit signal logic indicating that specified position should be sold. Returning a string or True from this method is equal to setting sell signal on a candle at specified time. This method is not called when sell signal is set. @@ -103,7 +132,7 @@ def custom_exit(self, pair: str, trade: 'Trade', current_time: 'datetime', curre example you could implement a sell relative to the candle when the trade was opened, or a custom 1:2 risk-reward ROI. - Custom sell reason max length is 64. Exceeding characters will be removed. + Custom exit reason max length is 64. Exceeding characters will be removed. :param pair: Pair that's currently analyzed :param trade: trade object. @@ -111,13 +140,13 @@ def custom_exit(self, pair: str, trade: 'Trade', current_time: 'datetime', curre :param current_rate: Rate, calculated based on pricing settings in exit_pricing. :param current_profit: Current profit (as ratio), calculated based on current_rate. :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. - :return: To execute sell, return a string with custom sell reason or True. Otherwise return + :return: To execute sell, return a string with custom exit reason or True. Otherwise return None or False. """ return None 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. @@ -162,15 +191,16 @@ def confirm_trade_exit(self, pair: str, trade: 'Trade', order_type: str, amount: :param time_in_force: Time in force. Defaults to GTC (Good-til-cancelled). :param exit_reason: Exit reason. Can be any of ['roi', 'stop_loss', 'stoploss_on_exchange', 'trailing_stop_loss', - 'sell_signal', 'force_sell', 'emergency_sell'] + 'exit_signal', 'force_exit', 'emergency_exit'] :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 sell-order is placed on the exchange. + :return bool: When True is returned, then the exit-order is placed on the exchange. False aborts the process """ 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 +213,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,16 +235,17 @@ 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 sell-order is cancelled. + :return bool: When True is returned, then the exit-order is cancelled. """ return False def adjust_trade_position(self, trade: 'Trade', current_time: 'datetime', current_rate: float, current_profit: float, min_stake: float, - max_stake: float, **kwargs) -> 'Optional[float]': + max_stake: float, **kwargs) -> Optional[float]: """ Custom trade adjustment logic, returning the stake amount that a trade should be increased. This means extra buy orders with additional fees. diff --git a/freqtrade/wallets.py b/freqtrade/wallets.py index d93689a0e..0c2197917 100644 --- a/freqtrade/wallets.py +++ b/freqtrade/wallets.py @@ -300,7 +300,8 @@ class Wallets: if min_stake_amount is not None and min_stake_amount > max_stake_amount: if self._log: - logger.warning("Minimum stake amount > available balance.") + logger.warning("Minimum stake amount > available balance. " + f"{min_stake_amount} > {max_stake_amount}") return 0 if min_stake_amount is not None and stake_amount < min_stake_amount: if self._log: diff --git a/mkdocs.yml b/mkdocs.yml index 8b36ba699..a43322f78 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -29,6 +29,7 @@ nav: - Data Analysis: - Jupyter Notebooks: data-analysis.md - Strategy analysis: strategy_analysis_example.md + - Backtest analysis: advanced-backtesting.md - Advanced Topics: - Advanced Post-installation Tasks: advanced-setup.md - Edge Positioning: edge.md 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" diff --git a/requirements-dev.txt b/requirements-dev.txt index 063cfaa45..60f4da1a7 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,12 +2,14 @@ -r requirements.txt -r requirements-plot.txt -r requirements-hyperopt.txt +-r docs/requirements-docs.txt coveralls==3.3.1 flake8==4.0.1 -flake8-tidy-imports==4.6.0 -mypy==0.942 -pytest==7.1.1 +flake8-tidy-imports==4.7.0 +mypy==0.950 +pre-commit==2.19.0 +pytest==7.1.2 pytest-asyncio==0.18.3 pytest-cov==3.0.0 pytest-mock==3.7.0 @@ -17,13 +19,11 @@ isort==5.10.1 time-machine==2.6.0 # Convert jupyter notebooks to markdown documents -nbconvert==6.4.4 +nbconvert==6.5.0 # mypy types -types-cachetools==5.0.0 +types-cachetools==5.0.1 types-filelock==3.2.5 -types-requests==2.27.15 -types-tabulate==0.8.6 - -# Extensions to datetime library -types-python-dateutil==2.8.10 \ No newline at end of file +types-requests==2.27.25 +types-tabulate==0.8.9 +types-python-dateutil==2.8.15 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-plot.txt b/requirements-plot.txt index bb2132f87..d9faed301 100644 --- a/requirements-plot.txt +++ b/requirements-plot.txt @@ -1,5 +1,4 @@ # Include all requirements to run the bot. -r requirements.txt -plotly==5.6.0 - +plotly==5.7.0 diff --git a/requirements.txt b/requirements.txt index d305f91b4..bed3a7fed 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,37 +1,40 @@ numpy==1.22.3 -pandas==1.4.1 +pandas==1.4.2 pandas-ta==0.3.14b -ccxt==1.77.45 +ccxt==1.81.81 # Pin cryptography for now due to rust build errors with piwheels -cryptography==36.0.2 +cryptography==37.0.2 aiohttp==3.8.1 -SQLAlchemy==1.4.32 +SQLAlchemy==1.4.36 python-telegram-bot==13.11 arrow==1.2.2 cachetools==4.2.2 requests==2.27.1 urllib3==1.26.9 -jsonschema==4.4.0 +jsonschema==4.5.1 TA-Lib==0.4.24 technical==1.3.0 tabulate==0.8.9 pycoingecko==2.2.0 -jinja2==3.1.1 +jinja2==3.1.2 tables==3.7.0 blosc==1.10.6 +joblib==1.1.0 # find first, C search in arrays 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 # API Server -fastapi==0.75.0 +fastapi==0.76.0 uvicorn==0.17.6 pyjwt==2.3.0 aiofiles==0.8.0 @@ -41,7 +44,7 @@ psutil==5.9.0 colorama==0.4.4 # Building config files interactively questionary==1.10.0 -prompt-toolkit==3.0.28 +prompt-toolkit==3.0.29 # Extensions to datetime library python-dateutil==2.8.2 diff --git a/scripts/rest_client.py b/scripts/rest_client.py index e23954dd4..ecbb65253 100755 --- a/scripts/rest_client.py +++ b/scripts/rest_client.py @@ -261,7 +261,7 @@ class FtRestClient(): } return self._post("forcebuy", data=data) - def forceenter(self, pair, side, price=None): + def force_enter(self, pair, side, price=None): """Force entering a trade :param pair: Pair to buy (ETH/BTC) @@ -273,16 +273,16 @@ class FtRestClient(): "side": side, "price": price, } - return self._post("forceenter", data=data) + return self._post("force_enter", data=data) - def forcesell(self, tradeid): - """Force-sell a trade. + def forceexit(self, tradeid): + """Force-exit a trade. :param tradeid: Id of the trade (can be received via status command) :return: json object """ - return self._post("forcesell", data={"tradeid": tradeid}) + return self._post("forceexit", data={"tradeid": tradeid}) def strategies(self): """Lists available strategies diff --git a/setup.cfg b/setup.cfg index 6aaec9d73..042517ec9 100644 --- a/setup.cfg +++ b/setup.cfg @@ -32,14 +32,16 @@ tests_require = pytest-mock packages = find: -python_requires = >=3.6 +python_requires = >=3.8 [options.entry_points] console_scripts = freqtrade = freqtrade.main:main [flake8] -#ignore = +# Default from https://flake8.pycqa.org/en/latest/user/options.html#cmdoption-flake8-ignore +# minus E226 +ignore = E121,E123,E126,E24,E704,W503,W504 max-line-length = 100 max-complexity = 12 exclude = @@ -50,6 +52,11 @@ exclude = [mypy] ignore_missing_imports = True +warn_unused_ignores = True +exclude = (?x)( + ^build_helpers\.py$ + ) + [mypy-tests.*] ignore_errors = True diff --git a/setup.py b/setup.py index 640c8cc7b..c5e418d0d 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', @@ -57,6 +57,7 @@ setup( 'pycoingecko', 'py_find_1st', 'python-rapidjson', + 'orjson', 'sdnotify', 'colorama', 'jinja2', diff --git a/setup.sh b/setup.sh index ebfabaca5..bb51c3a2f 100755 --- a/setup.sh +++ b/setup.sh @@ -25,7 +25,7 @@ function check_installed_python() { exit 2 fi - for v in 9 10 8 + for v in 10 9 8 do PYTHON="python3.${v}" which $PYTHON @@ -51,6 +51,7 @@ function updateenv() { echo "pip install in-progress. Please wait..." ${PYTHON} -m pip install --upgrade pip read -p "Do you want to install dependencies for dev [y/N]? " + dev=$REPLY if [[ $REPLY =~ ^[Yy]$ ]] then REQUIREMENTS=requirements-dev.txt @@ -88,6 +89,13 @@ function updateenv() { fi echo "pip install completed" echo + if [[ $dev =~ ^[Yy]$ ]]; then + ${PYTHON} -m pre_commit install + if [ $? -ne 0 ]; then + echo "Failed installing pre-commit" + exit 1 + fi + fi } # Install tab lib @@ -147,7 +155,7 @@ function install_macos() { # Install bot Debian_ubuntu function install_debian() { sudo apt-get update - sudo apt-get install -y gcc build-essential autoconf libtool pkg-config make wget git $(echo lib${PYTHON}-dev ${PYTHON}-venv) + sudo apt-get install -y gcc build-essential autoconf libtool pkg-config make wget git curl $(echo lib${PYTHON}-dev ${PYTHON}-venv) install_talib } diff --git a/tests/commands/test_commands.py b/tests/commands/test_commands.py index 7baa91720..b37edf9c7 100644 --- a/tests/commands/test_commands.py +++ b/tests/commands/test_commands.py @@ -1,5 +1,6 @@ import json import re +from datetime import datetime from io import BytesIO from pathlib import Path from unittest.mock import MagicMock, PropertyMock @@ -14,11 +15,14 @@ from freqtrade.commands import (start_backtesting_show, start_convert_data, star start_list_exchanges, start_list_markets, start_list_strategies, start_list_timeframes, start_new_strategy, start_show_trades, start_test_pairlist, start_trading, start_webserver) +from freqtrade.commands.db_commands import start_convert_db from freqtrade.commands.deploy_commands import (clean_ui_subdir, download_and_install_ui, get_ui_download_url, read_ui_version) from freqtrade.configuration import setup_utils_configuration from freqtrade.enums import RunMode from freqtrade.exceptions import OperationalException +from freqtrade.persistence.models import init_db +from freqtrade.persistence.pairlock_middleware import PairLocks from tests.conftest import (CURRENT_TEST_STRATEGY, create_mock_trades, get_args, log_has, log_has_re, patch_exchange, patched_configuration_load_config_file) from tests.conftest_trades import MOCK_TRADE_COUNT @@ -826,8 +830,26 @@ def test_download_data_trades(mocker, caplog): ] with pytest.raises(OperationalException, match="Trade download not supported for futures."): + pargs = get_args(args) + pargs['config'] = None + start_download_data(pargs) - start_download_data(get_args(args)) + +def test_download_data_data_invalid(mocker): + patch_exchange(mocker, id="kraken") + mocker.patch( + 'freqtrade.exchange.Exchange.markets', PropertyMock(return_value={}) + ) + args = [ + "download-data", + "--exchange", "kraken", + "--pairs", "ETH/BTC", "XRP/BTC", + "--days", "20", + ] + pargs = get_args(args) + pargs['config'] = None + with pytest.raises(OperationalException, match=r"Historic klines not available for .*"): + start_download_data(pargs) def test_start_convert_trades(mocker, caplog): @@ -846,7 +868,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", @@ -858,8 +880,8 @@ def test_start_list_strategies(mocker, caplog, 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 @@ -873,8 +895,8 @@ def test_start_list_strategies(mocker, caplog, 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 @@ -887,10 +909,30 @@ def test_start_list_strategies(mocker, caplog, 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 + 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 "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 def test_start_test_pairlist(mocker, caplog, tickers, default_conf, capsys): @@ -1428,7 +1470,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) @@ -1437,3 +1479,33 @@ def test_backtesting_show(mocker, testdatadir, capsys): assert sbr.call_count == 1 out, err = capsys.readouterr() assert "Pairs for Strategy" in out + + +def test_start_convert_db(mocker, fee, tmpdir, caplog): + db_src_file = Path(f"{tmpdir}/db.sqlite") + db_from = f"sqlite:///{db_src_file}" + db_target_file = Path(f"{tmpdir}/db_target.sqlite") + db_to = f"sqlite:///{db_target_file}" + args = [ + "convert-db", + "--db-url-from", + db_from, + "--db-url", + db_to, + ] + + assert not db_src_file.is_file() + init_db(db_from, False) + + create_mock_trades(fee) + + PairLocks.timeframe = '5m' + PairLocks.lock_pair('XRP/USDT', datetime.now(), 'Random reason 125', side='long') + assert db_src_file.is_file() + assert not db_target_file.is_file() + + pargs = get_args(args) + pargs['config'] = None + start_convert_db(pargs) + + assert db_target_file.is_file() diff --git a/tests/conftest.py b/tests/conftest.py index 7c3bbe4a5..cc07de1de 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -87,7 +87,7 @@ def get_mock_coro(return_value): def patched_configuration_load_config_file(mocker, config) -> None: mocker.patch( - 'freqtrade.configuration.configuration.load_config_file', + 'freqtrade.configuration.load_config.load_config_file', lambda *args, **kwargs: config ) @@ -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 { @@ -2672,6 +2638,7 @@ def saved_hyperopt_results(): 'total_profit': -0.00125625, 'current_epoch': 1, 'is_initial_point': True, + 'is_random': False, 'is_best': True, }, { @@ -2688,6 +2655,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, @@ -2698,6 +2666,7 @@ def saved_hyperopt_results(): 'total_profit': -0.13639474, 'current_epoch': 3, 'is_initial_point': True, + 'is_random': False, 'is_best': False }, { 'loss': 100000, @@ -2705,7 +2674,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 # 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 @@ -2715,6 +2684,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, @@ -2725,6 +2695,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, @@ -2737,6 +2708,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 @@ -2747,6 +2719,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, @@ -2757,6 +2730,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 @@ -2767,6 +2741,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 @@ -2778,6 +2753,7 @@ def saved_hyperopt_results(): 'total_profit': -0.07436117, 'current_epoch': 11, 'is_initial_point': True, + 'is_random': False, 'is_best': False }, { 'loss': 100000, @@ -2788,6 +2764,7 @@ def saved_hyperopt_results(): 'total_profit': 0, 'current_epoch': 12, 'is_initial_point': True, + 'is_random': False, 'is_best': False } ] @@ -2935,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/conftest_trades.py b/tests/conftest_trades.py index 3e3ba9495..006eab98f 100644 --- a/tests/conftest_trades.py +++ b/tests/conftest_trades.py @@ -6,7 +6,7 @@ from freqtrade.persistence.models import Order, Trade MOCK_TRADE_COUNT = 6 -def enter_side(is_short: bool): +def entry_side(is_short: bool): return "sell" if is_short else "buy" @@ -23,7 +23,7 @@ def mock_order_1(is_short: bool): 'id': f'1234_{direc(is_short)}', 'symbol': 'ETH/BTC', 'status': 'closed', - 'side': enter_side(is_short), + 'side': entry_side(is_short), 'type': 'limit', 'price': 0.123, 'average': 0.123, @@ -50,7 +50,7 @@ def mock_trade_1(fee, is_short: bool): timeframe=5, is_short=is_short ) - o = Order.parse_from_ccxt_object(mock_order_1(is_short), 'ETH/BTC', enter_side(is_short)) + o = Order.parse_from_ccxt_object(mock_order_1(is_short), 'ETH/BTC', entry_side(is_short)) trade.orders.append(o) return trade @@ -60,7 +60,7 @@ def mock_order_2(is_short: bool): 'id': f'1235_{direc(is_short)}', 'symbol': 'ETC/BTC', 'status': 'closed', - 'side': enter_side(is_short), + 'side': entry_side(is_short), 'type': 'limit', 'price': 0.123, 'amount': 123.0, @@ -104,12 +104,12 @@ def mock_trade_2(fee, is_short: bool): strategy='StrategyTestV3', timeframe=5, enter_tag='TEST1', - sell_reason='sell_signal', + exit_reason='sell_signal', open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20), close_date=datetime.now(tz=timezone.utc) - timedelta(minutes=2), is_short=is_short ) - o = Order.parse_from_ccxt_object(mock_order_2(is_short), 'ETC/BTC', enter_side(is_short)) + o = Order.parse_from_ccxt_object(mock_order_2(is_short), 'ETC/BTC', entry_side(is_short)) trade.orders.append(o) o = Order.parse_from_ccxt_object(mock_order_2_sell(is_short), 'ETC/BTC', exit_side(is_short)) trade.orders.append(o) @@ -121,7 +121,7 @@ def mock_order_3(is_short: bool): 'id': f'41231a12a_{direc(is_short)}', 'symbol': 'XRP/BTC', 'status': 'closed', - 'side': enter_side(is_short), + 'side': entry_side(is_short), 'type': 'limit', 'price': 0.05, 'amount': 123.0, @@ -164,12 +164,12 @@ def mock_trade_3(fee, is_short: bool): is_open=False, strategy='StrategyTestV3', timeframe=5, - sell_reason='roi', + exit_reason='roi', open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20), close_date=datetime.now(tz=timezone.utc), is_short=is_short ) - o = Order.parse_from_ccxt_object(mock_order_3(is_short), 'XRP/BTC', enter_side(is_short)) + o = Order.parse_from_ccxt_object(mock_order_3(is_short), 'XRP/BTC', entry_side(is_short)) trade.orders.append(o) o = Order.parse_from_ccxt_object(mock_order_3_sell(is_short), 'XRP/BTC', exit_side(is_short)) trade.orders.append(o) @@ -181,7 +181,7 @@ def mock_order_4(is_short: bool): 'id': f'prod_buy_{direc(is_short)}_12345', 'symbol': 'ETC/BTC', 'status': 'open', - 'side': enter_side(is_short), + 'side': entry_side(is_short), 'type': 'limit', 'price': 0.123, 'amount': 123.0, @@ -210,7 +210,7 @@ def mock_trade_4(fee, is_short: bool): timeframe=5, is_short=is_short ) - o = Order.parse_from_ccxt_object(mock_order_4(is_short), 'ETC/BTC', enter_side(is_short)) + o = Order.parse_from_ccxt_object(mock_order_4(is_short), 'ETC/BTC', entry_side(is_short)) trade.orders.append(o) return trade @@ -220,7 +220,7 @@ def mock_order_5(is_short: bool): 'id': f'prod_buy_{direc(is_short)}_3455', 'symbol': 'XRP/BTC', 'status': 'closed', - 'side': enter_side(is_short), + 'side': entry_side(is_short), 'type': 'limit', 'price': 0.123, 'amount': 123.0, @@ -264,7 +264,7 @@ def mock_trade_5(fee, is_short: bool): timeframe=5, is_short=is_short ) - o = Order.parse_from_ccxt_object(mock_order_5(is_short), 'XRP/BTC', enter_side(is_short)) + o = Order.parse_from_ccxt_object(mock_order_5(is_short), 'XRP/BTC', entry_side(is_short)) trade.orders.append(o) o = Order.parse_from_ccxt_object(mock_order_5_stoploss(is_short), 'XRP/BTC', 'stoploss') trade.orders.append(o) @@ -276,7 +276,7 @@ def mock_order_6(is_short: bool): 'id': f'prod_buy_{direc(is_short)}_6', 'symbol': 'LTC/BTC', 'status': 'closed', - 'side': enter_side(is_short), + 'side': entry_side(is_short), 'type': 'limit', 'price': 0.15, 'amount': 2.0, @@ -320,7 +320,7 @@ def mock_trade_6(fee, is_short: bool): timeframe=5, is_short=is_short ) - o = Order.parse_from_ccxt_object(mock_order_6(is_short), 'LTC/BTC', enter_side(is_short)) + o = Order.parse_from_ccxt_object(mock_order_6(is_short), 'LTC/BTC', entry_side(is_short)) trade.orders.append(o) o = Order.parse_from_ccxt_object(mock_order_6_sell(is_short), 'LTC/BTC', exit_side(is_short)) trade.orders.append(o) @@ -401,7 +401,7 @@ def short_trade(fee): open_order_id='dry_run_exit_short_12345', strategy='DefaultStrategy', timeframe=5, - sell_reason='sell_signal', + exit_reason='sell_signal', open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20), # close_date=datetime.now(tz=timezone.utc) - timedelta(minutes=2), is_short=True @@ -490,7 +490,7 @@ def leverage_trade(fee): open_order_id='dry_run_leverage_buy_12368', strategy='DefaultStrategy', timeframe=5, - sell_reason='sell_signal', + exit_reason='sell_signal', open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=300), close_date=datetime.now(tz=timezone.utc), interest_rate=0.0005 diff --git a/tests/conftest_trades_usdt.py b/tests/conftest_trades_usdt.py index 508e54f03..59e7f0457 100644 --- a/tests/conftest_trades_usdt.py +++ b/tests/conftest_trades_usdt.py @@ -89,7 +89,7 @@ def mock_trade_usdt_2(fee): open_order_id='dry_run_sell_12345', strategy='StrategyTestV2', timeframe=5, - sell_reason='sell_signal', + exit_reason='sell_signal', open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20), close_date=datetime.now(tz=timezone.utc) - timedelta(minutes=2), ) @@ -148,7 +148,7 @@ def mock_trade_usdt_3(fee): is_open=False, strategy='StrategyTestV2', timeframe=5, - sell_reason='roi', + exit_reason='roi', open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20), close_date=datetime.now(tz=timezone.utc), ) diff --git a/tests/data/test_btanalysis.py b/tests/data/test_btanalysis.py index f4275edd9..4157bd899 100644 --- a/tests/data/test_btanalysis.py +++ b/tests/data/test_btanalysis.py @@ -8,14 +8,14 @@ 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, + 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.data.metrics import (calculate_cagr, calculate_csum, calculate_market_change, + calculate_max_drawdown, calculate_underwater, + combine_dataframes_with_mean, create_cum_profit) from freqtrade.exceptions import OperationalException from tests.conftest import CURRENT_TEST_STRATEGY, create_mock_trades from tests.conftest_trades import MOCK_TRADE_COUNT @@ -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) @@ -335,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, @@ -362,3 +376,38 @@ def test_calculate_max_drawdown2(): df = DataFrame(zip(values[:5], dates[:5]), columns=['profit', 'open_date']) with pytest.raises(ValueError, match='No losing trade, therefore no drawdown.'): calculate_max_drawdown(df, date_col='open_date', value_col='profit') + + +@pytest.mark.parametrize('profits,relative,highd,lowd,result,result_rel', [ + ([0.0, -500.0, 500.0, 10000.0, -1000.0], False, 3, 4, 1000.0, 0.090909), + ([0.0, -500.0, 500.0, 10000.0, -1000.0], True, 0, 1, 500.0, 0.5), + +]) +def test_calculate_max_drawdown_abs(profits, relative, highd, lowd, result, result_rel): + """ + Test case from issue https://github.com/freqtrade/freqtrade/issues/6655 + [1000, 500, 1000, 11000, 10000] # absolute results + [1000, 50%, 0%, 0%, ~9%] # Relative drawdowns + """ + init_date = Arrow(2020, 1, 1) + dates = [init_date.shift(days=i) for i in range(len(profits))] + df = DataFrame(zip(profits, dates), columns=['profit_abs', 'open_date']) + # sort by profit and reset index + df = df.sort_values('profit_abs').reset_index(drop=True) + df1 = df.copy() + drawdown, hdate, ldate, hval, lval, drawdown_rel = calculate_max_drawdown( + df, date_col='open_date', starting_balance=1000, relative=relative) + # Ensure df has not been altered. + assert df.equals(df1) + + assert isinstance(drawdown, float) + assert isinstance(drawdown_rel, float) + assert hdate == init_date.shift(days=highd) + assert ldate == init_date.shift(days=lowd) + + # High must be before low + assert hdate < ldate + # High value must be higher than low value + assert hval > lval + assert drawdown == result + assert pytest.approx(drawdown_rel) == result_rel diff --git a/tests/data/test_history.py b/tests/data/test_history.py index 0585fa0d4..82d4a841c 100644 --- a/tests/data/test_history.py +++ b/tests/data/test_history.py @@ -149,8 +149,8 @@ def test_load_data_with_new_pair_1min(ohlcv_history_list, mocker, caplog, load_pair_history(datadir=tmpdir1, timeframe='1m', pair='MEME/BTC', candle_type=candle_type) assert file.is_file() assert log_has_re( - r'Download history data for pair: "MEME/BTC" \(0/1\), timeframe: 1m, ' - r'candle type: spot and store in .*', caplog + r'\(0/1\) - Download history data for "MEME/BTC", 1m, ' + r'spot and store in .*', caplog ) @@ -223,42 +223,65 @@ def test_load_cached_data_for_updating(mocker, testdatadir) -> None: # timeframe starts earlier than the cached data # should fully update data timerange = TimeRange('date', None, test_data[0][0] / 1000 - 1, 0) - data, start_ts = _load_cached_data_for_updating( + data, start_ts, end_ts = _load_cached_data_for_updating( 'UNITTEST/BTC', '1m', timerange, data_handler, CandleType.SPOT) assert data.empty assert start_ts == test_data[0][0] - 1000 + assert end_ts is None + + # timeframe starts earlier than the cached data - prepending + + timerange = TimeRange('date', None, test_data[0][0] / 1000 - 1, 0) + data, start_ts, end_ts = _load_cached_data_for_updating( + 'UNITTEST/BTC', '1m', timerange, data_handler, CandleType.SPOT, True) + assert_frame_equal(data, test_data_df.iloc[:-1]) + assert start_ts == test_data[0][0] - 1000 + assert end_ts == test_data[0][0] # timeframe starts in the center of the cached data # should return the cached data w/o the last item timerange = TimeRange('date', None, test_data[0][0] / 1000 + 1, 0) - data, start_ts = _load_cached_data_for_updating( + data, start_ts, end_ts = _load_cached_data_for_updating( 'UNITTEST/BTC', '1m', timerange, data_handler, CandleType.SPOT) assert_frame_equal(data, test_data_df.iloc[:-1]) assert test_data[-2][0] <= start_ts < test_data[-1][0] + assert end_ts is None # timeframe starts after the cached data # should return the cached data w/o the last item timerange = TimeRange('date', None, test_data[-1][0] / 1000 + 100, 0) - data, start_ts = _load_cached_data_for_updating( + data, start_ts, end_ts = _load_cached_data_for_updating( 'UNITTEST/BTC', '1m', timerange, data_handler, CandleType.SPOT) assert_frame_equal(data, test_data_df.iloc[:-1]) assert test_data[-2][0] <= start_ts < test_data[-1][0] + assert end_ts is None # no datafile exist # should return timestamp start time timerange = TimeRange('date', None, now_ts - 10000, 0) - data, start_ts = _load_cached_data_for_updating( + data, start_ts, end_ts = _load_cached_data_for_updating( 'NONEXIST/BTC', '1m', timerange, data_handler, CandleType.SPOT) assert data.empty assert start_ts == (now_ts - 10000) * 1000 + assert end_ts is None + + # no datafile exist + # should return timestamp start and end time time + timerange = TimeRange('date', 'date', now_ts - 1000000, now_ts - 100000) + data, start_ts, end_ts = _load_cached_data_for_updating( + 'NONEXIST/BTC', '1m', timerange, data_handler, CandleType.SPOT) + assert data.empty + assert start_ts == (now_ts - 1000000) * 1000 + assert end_ts == (now_ts - 100000) * 1000 # no datafile exist, no timeframe is set # should return an empty array and None - data, start_ts = _load_cached_data_for_updating( + data, start_ts, end_ts = _load_cached_data_for_updating( 'NONEXIST/BTC', '1m', None, data_handler, CandleType.SPOT) assert data.empty assert start_ts is None + assert end_ts is None @pytest.mark.parametrize('candle_type,subdir,file_tail', [ diff --git a/tests/edge/test_edge.py b/tests/edge/test_edge.py index 4ac27adc0..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 @@ -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=[ @@ -95,8 +52,8 @@ tc1 = BTContainer(data=[ [6, 5000, 5025, 4975, 4987, 6172, 0, 0], # should sell ], stop_loss=-0.99, roi={"0": float('inf')}, profit_perc=0.00, - trades=[BTrade(sell_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=2), - BTrade(sell_reason=ExitType.SELL_SIGNAL, open_tick=4, close_tick=6)] + trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=2), + BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=4, close_tick=6)] ) # 3) Entered, sl 1%, candle drops 8% => Trade closed, 1% loss @@ -107,7 +64,7 @@ tc2 = BTContainer(data=[ [2, 5000, 5025, 4975, 4987, 6172, 0, 0], ], stop_loss=-0.01, roi={"0": float('inf')}, profit_perc=-0.01, - trades=[BTrade(sell_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=1)] + trades=[BTrade(exit_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=1)] ) # 4) Entered, sl 3 %, candle drops 4%, recovers to 1 % = > Trade closed, 3 % loss @@ -118,7 +75,7 @@ tc3 = BTContainer(data=[ [2, 5000, 5025, 4975, 4987, 6172, 0, 0], ], stop_loss=-0.03, roi={"0": float('inf')}, profit_perc=-0.03, - trades=[BTrade(sell_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=1)] + trades=[BTrade(exit_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=1)] ) # 5) Stoploss and sell are hit. should sell on stoploss @@ -129,7 +86,7 @@ tc4 = BTContainer(data=[ [2, 5000, 5025, 4975, 4987, 6172, 0, 0], ], stop_loss=-0.03, roi={"0": float('inf')}, profit_perc=-0.03, - trades=[BTrade(sell_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=1)] + trades=[BTrade(exit_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=1)] ) TESTS = [ @@ -162,7 +119,7 @@ def test_edge_results(edge_conf, mocker, caplog, data) -> None: for c, trade in enumerate(data.trades): res = results.iloc[c] - assert res.exit_type == trade.sell_reason + assert res.exit_type == trade.exit_reason assert res.open_date == _get_frame_time_from_offset(trade.open_tick).replace(tzinfo=None) assert res.close_date == _get_frame_time_from_offset(trade.close_tick).replace(tzinfo=None) @@ -391,7 +348,7 @@ def test_process_expectancy(mocker, edge_conf, fee, risk_reward_ratio, expectanc 'trade_duration': '', 'open_rate': 17, 'close_rate': 17, - 'exit_type': 'sell_signal'}, + 'exit_type': 'exit_signal'}, {'pair': 'TEST/BTC', 'stoploss': -0.9, @@ -402,7 +359,7 @@ def test_process_expectancy(mocker, edge_conf, fee, risk_reward_ratio, expectanc 'trade_duration': '', 'open_rate': 20, 'close_rate': 20, - 'exit_type': 'sell_signal'}, + 'exit_type': 'exit_signal'}, {'pair': 'TEST/BTC', 'stoploss': -0.9, @@ -413,7 +370,7 @@ def test_process_expectancy(mocker, edge_conf, fee, risk_reward_ratio, expectanc 'trade_duration': '', 'open_rate': 26, 'close_rate': 34, - 'exit_type': 'sell_signal'} + 'exit_type': 'exit_signal'} ] trades_df = DataFrame(trades) 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..e016873cb 100644 --- a/tests/exchange/test_ccxt_compat.py +++ b/tests/exchange/test_ccxt_compat.py @@ -13,6 +13,7 @@ import pytest from freqtrade.enums import CandleType from freqtrade.exchange import timeframe_to_minutes, timeframe_to_prev_date +from freqtrade.exchange.exchange import timeframe_to_msecs from freqtrade.resolvers.exchange_resolver import ExchangeResolver from tests.conftest import get_default_conf_usdt @@ -135,6 +136,7 @@ def exchange_futures(request, exchange_conf, class_mocker): class_mocker.patch( 'freqtrade.exchange.binance.Binance.fill_leverage_tiers') class_mocker.patch('freqtrade.exchange.exchange.Exchange.fetch_trading_fees') + class_mocker.patch('freqtrade.exchange.okx.Okx.additional_exchange_init') exchange = ExchangeResolver.load_exchange(request.param, exchange_conf, validate=True) yield exchange, request.param @@ -218,7 +220,7 @@ class TestCCXTExchange(): assert len(l2['asks']) == next_limit assert len(l2['asks']) == next_limit - def test_fetch_ohlcv(self, exchange): + def test_ccxt_fetch_ohlcv(self, exchange): exchange, exchangename = exchange pair = EXCHANGES[exchangename]['pair'] timeframe = EXCHANGES[exchangename]['timeframe'] @@ -230,11 +232,44 @@ class TestCCXTExchange(): assert len(ohlcv[pair_tf]) == len(exchange.klines(pair_tf)) # assert len(exchange.klines(pair_tf)) > 200 # Assume 90% uptime ... - assert len(exchange.klines(pair_tf)) > exchange.ohlcv_candle_limit(timeframe) * 0.90 + assert len(exchange.klines(pair_tf)) > exchange.ohlcv_candle_limit( + timeframe, CandleType.SPOT) * 0.90 # Check if last-timeframe is within the last 2 intervals now = datetime.now(timezone.utc) - timedelta(minutes=(timeframe_to_minutes(timeframe) * 2)) assert exchange.klines(pair_tf).iloc[-1]['date'] >= timeframe_to_prev_date(timeframe, now) + def test_ccxt__async_get_candle_history(self, exchange): + exchange, exchangename = exchange + # For some weired reason, this test returns random lengths for bittrex. + if not exchange._ft_has['ohlcv_has_history'] or exchangename == 'bittrex': + return + pair = EXCHANGES[exchangename]['pair'] + timeframe = EXCHANGES[exchangename]['timeframe'] + candle_type = CandleType.SPOT + timeframe_ms = timeframe_to_msecs(timeframe) + now = timeframe_to_prev_date( + timeframe, datetime.now(timezone.utc)) + for offset in (360, 120, 30, 10, 5, 2): + since = now - timedelta(days=offset) + since_ms = int(since.timestamp() * 1000) + + res = exchange.loop.run_until_complete(exchange._async_get_candle_history( + pair=pair, + timeframe=timeframe, + since_ms=since_ms, + candle_type=candle_type + ) + ) + assert res + assert res[0] == pair + assert res[1] == timeframe + assert res[2] == candle_type + candles = res[3] + candle_count = exchange.ohlcv_candle_limit(timeframe, candle_type, since_ms) * 0.9 + candle_count1 = (now.timestamp() * 1000 - since_ms) // timeframe_ms + assert len(candles) >= min(candle_count, candle_count1) + assert candles[0][0] == since_ms or (since_ms + timeframe_ms) + def test_ccxt_fetch_funding_rate_history(self, exchange_futures): exchange, exchangename = exchange_futures if not exchange: @@ -369,25 +404,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 14d5e6472..e580c82d3 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -17,9 +17,9 @@ from freqtrade.exceptions import (DDosProtection, DependencyException, InvalidOr from freqtrade.exchange import Binance, Bittrex, Exchange, Kraken from freqtrade.exchange.common import (API_FETCH_ORDER_RETRY_COUNT, API_RETRY_COUNT, calculate_backoff, remove_credentials) -from freqtrade.exchange.exchange import (market_is_active, timeframe_to_minutes, timeframe_to_msecs, - timeframe_to_next_date, timeframe_to_prev_date, - timeframe_to_seconds) +from freqtrade.exchange.exchange import (date_minus_candles, market_is_active, timeframe_to_minutes, + timeframe_to_msecs, timeframe_to_next_date, + timeframe_to_prev_date, timeframe_to_seconds) from freqtrade.resolvers.exchange_resolver import ExchangeResolver from tests.conftest import get_mock_coro, get_patched_exchange, log_has, log_has_re, num_log_has_re @@ -99,6 +99,8 @@ def test_remove_credentials(default_conf, caplog) -> None: def test_init_ccxt_kwargs(default_conf, mocker, caplog): mocker.patch('freqtrade.exchange.Exchange._load_markets', MagicMock(return_value={})) mocker.patch('freqtrade.exchange.Exchange.validate_stakecurrency') + aei_mock = mocker.patch('freqtrade.exchange.Exchange.additional_exchange_init') + caplog.set_level(logging.INFO) conf = copy.deepcopy(default_conf) conf['exchange']['ccxt_async_config'] = {'aiohttp_trust_env': True, 'asyncio_loop': True} @@ -108,6 +110,7 @@ def test_init_ccxt_kwargs(default_conf, mocker, caplog): caplog) assert ex._api_async.aiohttp_trust_env assert not ex._api.aiohttp_trust_env + assert aei_mock.call_count == 1 # Reset logging and config caplog.clear() @@ -231,6 +234,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'), @@ -382,11 +389,11 @@ def test__get_stake_amount_limit(mocker, default_conf) -> None: ) # min result = exchange.get_min_pair_stake_amount('ETH/BTC', 1, stoploss) - expected_result = 2 * (1+0.05) / (1-abs(stoploss)) + expected_result = 2 * (1 + 0.05) / (1 - abs(stoploss)) assert isclose(result, expected_result) # With Leverage result = exchange.get_min_pair_stake_amount('ETH/BTC', 1, stoploss, 3.0) - assert isclose(result, expected_result/3) + assert isclose(result, expected_result / 3) # max result = exchange.get_max_pair_stake_amount('ETH/BTC', 2) assert result == 10000 @@ -401,11 +408,11 @@ def test__get_stake_amount_limit(mocker, default_conf) -> None: PropertyMock(return_value=markets) ) result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss) - expected_result = 2 * 2 * (1+0.05) / (1-abs(stoploss)) + expected_result = 2 * 2 * (1 + 0.05) / (1 - abs(stoploss)) assert isclose(result, expected_result) # With Leverage result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss, 5.0) - assert isclose(result, expected_result/5) + assert isclose(result, expected_result / 5) # max result = exchange.get_max_pair_stake_amount('ETH/BTC', 2) assert result == 20000 @@ -420,11 +427,11 @@ def test__get_stake_amount_limit(mocker, default_conf) -> None: PropertyMock(return_value=markets) ) result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss) - expected_result = max(2, 2 * 2) * (1+0.05) / (1-abs(stoploss)) + expected_result = max(2, 2 * 2) * (1 + 0.05) / (1 - abs(stoploss)) assert isclose(result, expected_result) # With Leverage result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss, 10) - assert isclose(result, expected_result/10) + assert isclose(result, expected_result / 10) # min amount and cost are set (amount is minial) markets["ETH/BTC"]["limits"] = { @@ -436,11 +443,11 @@ def test__get_stake_amount_limit(mocker, default_conf) -> None: PropertyMock(return_value=markets) ) result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss) - expected_result = max(8, 2 * 2) * (1+0.05) / (1-abs(stoploss)) + expected_result = max(8, 2 * 2) * (1 + 0.05) / (1 - abs(stoploss)) assert isclose(result, expected_result) # With Leverage result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, stoploss, 7.0) - assert isclose(result, expected_result/7.0) + assert isclose(result, expected_result / 7.0) # Max result = exchange.get_max_pair_stake_amount('ETH/BTC', 2) assert result == 1000 @@ -450,7 +457,7 @@ def test__get_stake_amount_limit(mocker, default_conf) -> None: assert isclose(result, expected_result) # With Leverage result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, -0.4, 8.0) - assert isclose(result, expected_result/8.0) + assert isclose(result, expected_result / 8.0) # Max result = exchange.get_max_pair_stake_amount('ETH/BTC', 2) assert result == 1000 @@ -461,7 +468,7 @@ def test__get_stake_amount_limit(mocker, default_conf) -> None: assert isclose(result, expected_result) # With Leverage result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, -1, 12.0) - assert isclose(result, expected_result/12) + assert isclose(result, expected_result / 12) # Max result = exchange.get_max_pair_stake_amount('ETH/BTC', 2) assert result == 1000 @@ -489,7 +496,7 @@ def test__get_stake_amount_limit(mocker, default_conf) -> None: ) # With Leverage, Contract size 10 result = exchange.get_min_pair_stake_amount('ETH/BTC', 2, -1, 12.0) - assert isclose(result, (expected_result/12) * 10.0) + assert isclose(result, (expected_result / 12) * 10.0) # Max result = exchange.get_max_pair_stake_amount('ETH/BTC', 2) assert result == 10000 @@ -510,7 +517,7 @@ def test_get_min_pair_stake_amount_real_data(mocker, default_conf) -> None: PropertyMock(return_value=markets) ) result = exchange.get_min_pair_stake_amount('ETH/BTC', 0.020405, stoploss) - expected_result = max(0.0001, 0.001 * 0.020405) * (1+0.05) / (1-abs(stoploss)) + expected_result = max(0.0001, 0.001 * 0.020405) * (1 + 0.05) / (1 - abs(stoploss)) assert round(result, 8) == round(expected_result, 8) # Max result = exchange.get_max_pair_stake_amount('ETH/BTC', 2.0) @@ -518,12 +525,12 @@ def test_get_min_pair_stake_amount_real_data(mocker, default_conf) -> None: # Leverage result = exchange.get_min_pair_stake_amount('ETH/BTC', 0.020405, stoploss, 3.0) - assert round(result, 8) == round(expected_result/3, 8) + assert round(result, 8) == round(expected_result / 3, 8) # Contract_size markets["ETH/BTC"]["contractSize"] = 0.1 result = exchange.get_min_pair_stake_amount('ETH/BTC', 0.020405, stoploss, 3.0) - assert round(result, 8) == round((expected_result/3), 8) + assert round(result, 8) == round((expected_result / 3), 8) # Max result = exchange.get_max_pair_stake_amount('ETH/BTC', 12.0) @@ -905,7 +912,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) @@ -926,12 +933,13 @@ 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) def test_validate_timeframes_not_in_config(default_conf, mocker): + # TODO: this test does not assert ... del default_conf["timeframe"] api_mock = MagicMock() id_mock = PropertyMock(return_value='test_exchange') @@ -947,6 +955,7 @@ def test_validate_timeframes_not_in_config(default_conf, mocker): mocker.patch('freqtrade.exchange.Exchange.validate_pairs') mocker.patch('freqtrade.exchange.Exchange.validate_stakecurrency') mocker.patch('freqtrade.exchange.Exchange.validate_pricing') + mocker.patch('freqtrade.exchange.Exchange.validate_required_startup_candles') Exchange(default_conf) @@ -1077,6 +1086,13 @@ def test_validate_required_startup_candles(default_conf, mocker, caplog): with pytest.raises(OperationalException, match=r'This strategy requires 6000.*'): Exchange(default_conf) + # Emulate kraken mode + ex._ft_has['ohlcv_has_history'] = False + with pytest.raises(OperationalException, + match=r'This strategy requires 2500.*, ' + r'which is more than the amount.*'): + ex.validate_required_startup_candles(2500, '5m') + def test_exchange_has(default_conf, mocker): exchange = get_patched_exchange(mocker, default_conf) @@ -1868,7 +1884,7 @@ def test_get_historic_ohlcv(default_conf, mocker, caplog, exchange_name, candle_ exchange._async_get_candle_history = Mock(wraps=mock_candle_hist) # one_call calculation * 1.8 should do 2 calls - since = 5 * 60 * exchange.ohlcv_candle_limit('5m') * 1.8 + since = 5 * 60 * exchange.ohlcv_candle_limit('5m', CandleType.SPOT) * 1.8 ret = exchange.get_historic_ohlcv( pair, "5m", @@ -1934,7 +1950,7 @@ def test_get_historic_ohlcv_as_df(default_conf, mocker, exchange_name, candle_ty exchange._async_get_candle_history = Mock(wraps=mock_candle_hist) # one_call calculation * 1.8 should do 2 calls - since = 5 * 60 * exchange.ohlcv_candle_limit('5m') * 1.8 + since = 5 * 60 * exchange.ohlcv_candle_limit('5m', CandleType.SPOT) * 1.8 ret = exchange.get_historic_ohlcv_as_df( pair, "5m", @@ -1979,6 +1995,20 @@ async def test__async_get_historic_ohlcv(default_conf, mocker, caplog, exchange_ assert exchange._api_async.fetch_ohlcv.call_count > 200 assert res[0] == ohlcv[0] + exchange._api_async.fetch_ohlcv.reset_mock() + end_ts = 1_500_500_000_000 + start_ts = 1_500_000_000_000 + respair, restf, _, res = await exchange._async_get_historic_ohlcv( + pair, "5m", since_ms=start_ts, candle_type=candle_type, is_new_pair=False, + until_ms=end_ts + ) + # Required candles + candles = (end_ts - start_ts) / 300_000 + exp = candles // exchange.ohlcv_candle_limit('5m', CandleType.SPOT) + 1 + + # Depending on the exchange, this should be called between 1 and 6 times. + assert exchange._api_async.fetch_ohlcv.call_count == exp + @pytest.mark.parametrize('candle_type', [CandleType.FUTURES, CandleType.MARK, CandleType.SPOT]) def test_refresh_latest_ohlcv(mocker, default_conf, caplog, candle_type) -> None: @@ -2130,7 +2160,8 @@ async def test__async_kucoin_get_candle_history(default_conf, mocker, caplog): "kucoin GET https://openapi-v2.kucoin.com/api/v1/market/candles?" "symbol=ETH-BTC&type=5min&startAt=1640268735&endAt=1640418735" "429 Too Many Requests" '{"code":"429000","msg":"Too Many Requests"}')) - exchange = get_patched_exchange(mocker, default_conf, api_mock, id="kucoin") + exchange = get_patched_exchange(mocker, default_conf, api_mock, id="KuCoin") + mocker.patch('freqtrade.exchange.Exchange.name', PropertyMock(return_value='KuCoin')) msg = "Kucoin 429 error, avoid triggering DDosProtection backoff delay" assert not num_log_has_re(msg, caplog) @@ -2690,9 +2721,10 @@ async def test__async_get_trade_history_time(default_conf, mocker, caplog, excha # Monkey-patch async function exchange._api_async.fetch_trades = MagicMock(side_effect=mock_get_trade_hist) pair = 'ETH/BTC' - ret = await exchange._async_get_trade_history_time(pair, - since=fetch_trades_result[0]['timestamp'], - until=fetch_trades_result[-1]['timestamp']-1) + ret = await exchange._async_get_trade_history_time( + pair, + since=fetch_trades_result[0]['timestamp'], + until=fetch_trades_result[-1]['timestamp'] - 1) assert type(ret) is tuple assert ret[0] == pair assert type(ret[1]) is list @@ -2728,7 +2760,7 @@ async def test__async_get_trade_history_time_empty(default_conf, mocker, caplog, exchange._async_fetch_trades = MagicMock(side_effect=mock_get_trade_hist) pair = 'ETH/BTC' ret = await exchange._async_get_trade_history_time(pair, since=trades_history[0][0], - until=trades_history[-1][0]-1) + until=trades_history[-1][0] - 1) assert type(ret) is tuple assert ret[0] == pair assert type(ret[1]) is list @@ -3319,7 +3351,7 @@ def test_ohlcv_candle_limit(default_conf, mocker, exchange_name): expected = exchange._ft_has['ohlcv_candle_limit_per_timeframe'][timeframe] # This should only run for bittrex assert exchange_name == 'bittrex' - assert exchange.ohlcv_candle_limit(timeframe) == expected + assert exchange.ohlcv_candle_limit(timeframe, CandleType.SPOT) == expected def test_timeframe_to_minutes(): @@ -3401,6 +3433,17 @@ def test_timeframe_to_next_date(): assert timeframe_to_next_date("5m", date) == date + timedelta(minutes=5) +def test_date_minus_candles(): + + date = datetime(2019, 8, 12, 13, 25, 0, tzinfo=timezone.utc) + + assert date_minus_candles("5m", 3, date) == date - timedelta(minutes=15) + assert date_minus_candles("5m", 5, date) == date - timedelta(minutes=25) + assert date_minus_candles("1m", 6, date) == date - timedelta(minutes=6) + assert date_minus_candles("1h", 3, date) == date - timedelta(hours=3, minutes=25) + assert date_minus_candles("1h", 3) == timeframe_to_prev_date('1h') - timedelta(hours=3) + + @pytest.mark.parametrize( "market_symbol,base,quote,exchange,spot,margin,futures,trademode,add_dict,expected_result", [ @@ -4145,7 +4188,10 @@ def test__order_contracts_to_amount( 'cost': 60.0, 'filled': None, 'remaining': 30.0, - 'fee': 0.06, + 'fee': { + 'currency': 'USDT', + 'cost': 0.06, + }, 'fees': [{ 'currency': 'USDT', 'cost': 0.06, @@ -4172,7 +4218,10 @@ def test__order_contracts_to_amount( 'cost': 80.0, 'filled': None, 'remaining': 40.0, - 'fee': 0.08, + 'fee': { + 'currency': 'USDT', + 'cost': 0.08, + }, 'fees': [{ 'currency': 'USDT', 'cost': 0.08, @@ -4206,12 +4255,18 @@ def test__order_contracts_to_amount( 'info': {}, }, ] + order1_bef = orders[0] + order2_bef = orders[1] + order1 = exchange._order_contracts_to_amount(deepcopy(order1_bef)) + order2 = exchange._order_contracts_to_amount(deepcopy(order2_bef)) + assert order1['amount'] == order1_bef['amount'] * contract_size + assert order1['cost'] == order1_bef['cost'] * contract_size - order1 = exchange._order_contracts_to_amount(orders[0]) - order2 = exchange._order_contracts_to_amount(orders[1]) + assert order2['amount'] == order2_bef['amount'] * contract_size + assert order2['cost'] == order2_bef['cost'] * contract_size + + # Don't fail exchange._order_contracts_to_amount(orders[2]) - assert order1['amount'] == 30.0 * contract_size - assert order2['amount'] == 40.0 * contract_size @pytest.mark.parametrize('pair,contract_size,trading_mode', [ @@ -4501,8 +4556,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': { @@ -4542,8 +4597,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': { @@ -4578,15 +4633,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" } @@ -4602,8 +4657,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': { @@ -4726,8 +4781,10 @@ def test__get_params(mocker, default_conf, exchange_name): if exchange_name == 'okx': params2['tdMode'] = 'isolated' + params2['posSide'] = 'net' assert exchange._get_params( + side="buy", ordertype='market', reduceOnly=False, time_in_force='gtc', @@ -4735,6 +4792,7 @@ def test__get_params(mocker, default_conf, exchange_name): ) == params1 assert exchange._get_params( + side="buy", ordertype='market', reduceOnly=False, time_in_force='ioc', @@ -4742,6 +4800,7 @@ def test__get_params(mocker, default_conf, exchange_name): ) == params1 assert exchange._get_params( + side="buy", ordertype='limit', reduceOnly=False, time_in_force='gtc', @@ -4754,6 +4813,7 @@ def test__get_params(mocker, default_conf, exchange_name): exchange._params = {'test': True} assert exchange._get_params( + side="buy", ordertype='limit', reduceOnly=True, time_in_force='ioc', diff --git a/tests/exchange/test_okx.py b/tests/exchange/test_okx.py index 8ecdf6904..19c09ad9e 100644 --- a/tests/exchange/test_okx.py +++ b/tests/exchange/test_okx.py @@ -1,7 +1,40 @@ +from datetime import datetime, timedelta, timezone from unittest.mock import MagicMock, PropertyMock +import pytest + from freqtrade.enums import MarginMode, TradingMode +from freqtrade.enums.candletype import CandleType +from freqtrade.exchange.exchange import timeframe_to_minutes from tests.conftest import get_patched_exchange +from tests.exchange.test_exchange import ccxt_exceptionhandlers + + +def test_okx_ohlcv_candle_limit(default_conf, mocker): + exchange = get_patched_exchange(mocker, default_conf, id='okx') + timeframes = ('1m', '5m', '1h') + start_time = int(datetime(2021, 1, 1, tzinfo=timezone.utc).timestamp() * 1000) + + for timeframe in timeframes: + assert exchange.ohlcv_candle_limit(timeframe, CandleType.SPOT) == 300 + assert exchange.ohlcv_candle_limit(timeframe, CandleType.FUTURES) == 300 + assert exchange.ohlcv_candle_limit(timeframe, CandleType.MARK) == 100 + assert exchange.ohlcv_candle_limit(timeframe, CandleType.FUNDING_RATE) == 100 + + assert exchange.ohlcv_candle_limit(timeframe, CandleType.SPOT, start_time) == 100 + assert exchange.ohlcv_candle_limit(timeframe, CandleType.FUTURES, start_time) == 100 + assert exchange.ohlcv_candle_limit(timeframe, CandleType.MARK, start_time) == 100 + assert exchange.ohlcv_candle_limit(timeframe, CandleType.FUNDING_RATE, start_time) == 100 + one_call = int((datetime.now(timezone.utc) - timedelta( + minutes=290 * timeframe_to_minutes(timeframe))).timestamp() * 1000) + + assert exchange.ohlcv_candle_limit(timeframe, CandleType.SPOT, one_call) == 300 + assert exchange.ohlcv_candle_limit(timeframe, CandleType.FUTURES, one_call) == 300 + + one_call = int((datetime.now(timezone.utc) - timedelta( + minutes=320 * timeframe_to_minutes(timeframe))).timestamp() * 1000) + assert exchange.ohlcv_candle_limit(timeframe, CandleType.SPOT, one_call) == 100 + assert exchange.ohlcv_candle_limit(timeframe, CandleType.FUTURES, one_call) == 100 def test_get_maintenance_ratio_and_amt_okx( @@ -19,8 +52,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 +72,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 +92,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 +114,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 +134,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 +154,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': { @@ -170,6 +203,70 @@ def test_get_max_pair_stake_amount_okx(default_conf, mocker, leverage_tiers): assert exchange.get_max_pair_stake_amount('TTT/USDT', 1.0) == float('inf') # Not in tiers +@pytest.mark.parametrize('mode,side,reduceonly,result', [ + ('net', 'buy', False, 'net'), + ('net', 'sell', True, 'net'), + ('net', 'sell', False, 'net'), + ('net', 'buy', True, 'net'), + ('longshort', 'buy', False, 'long'), + ('longshort', 'sell', True, 'long'), + ('longshort', 'sell', False, 'short'), + ('longshort', 'buy', True, 'short'), +]) +def test__get_posSide(default_conf, mocker, mode, side, reduceonly, result): + + exchange = get_patched_exchange(mocker, default_conf, id="okx") + exchange.net_only = mode == 'net' + assert exchange._get_posSide(side, reduceonly) == result + + +def test_additional_exchange_init_okx(default_conf, mocker): + api_mock = MagicMock() + api_mock.fetch_accounts = MagicMock(return_value=[ + {'id': '2555', + 'type': '2', + 'currency': None, + 'info': {'acctLv': '2', + 'autoLoan': False, + 'ctIsoMode': 'automatic', + 'greeksType': 'PA', + 'level': 'Lv1', + 'levelTmp': '', + 'mgnIsoMode': 'automatic', + 'posMode': 'long_short_mode', + 'uid': '2555'}}]) + default_conf['dry_run'] = False + exchange = get_patched_exchange(mocker, default_conf, id="okx", api_mock=api_mock) + assert api_mock.fetch_accounts.call_count == 0 + exchange.trading_mode = TradingMode.FUTURES + # Default to netOnly + assert exchange.net_only + exchange.additional_exchange_init() + assert api_mock.fetch_accounts.call_count == 1 + assert not exchange.net_only + + api_mock.fetch_accounts = MagicMock(return_value=[ + {'id': '2555', + 'type': '2', + 'currency': None, + 'info': {'acctLv': '2', + 'autoLoan': False, + 'ctIsoMode': 'automatic', + 'greeksType': 'PA', + 'level': 'Lv1', + 'levelTmp': '', + 'mgnIsoMode': 'automatic', + 'posMode': 'net_mode', + 'uid': '2555'}}]) + exchange.additional_exchange_init() + assert api_mock.fetch_accounts.call_count == 1 + assert exchange.net_only + default_conf['trading_mode'] = 'futures' + default_conf['margin_mode'] = 'isolated' + ccxt_exceptionhandlers(mocker, default_conf, api_mock, 'okx', + "additional_exchange_init", "fetch_accounts") + + def test_load_leverage_tiers_okx(default_conf, mocker, markets): api_mock = MagicMock() type(api_mock).has = PropertyMock(return_value={ @@ -180,8 +277,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 +297,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 +317,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 +339,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 +359,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 +379,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': { diff --git a/tests/leverage/test_interest.py b/tests/leverage/test_interest.py index c7e787bdb..6b189ce50 100644 --- a/tests/leverage/test_interest.py +++ b/tests/leverage/test_interest.py @@ -6,7 +6,7 @@ import pytest from freqtrade.leverage import interest -ten_mins = Decimal(1/6) +ten_mins = Decimal(1 / 6) five_hours = Decimal(5.0) twentyfive_hours = Decimal(25.0) diff --git a/tests/optimize/__init__.py b/tests/optimize/__init__.py index ad14125b5..a3dd59004 100644 --- a/tests/optimize/__init__.py +++ b/tests/optimize/__init__.py @@ -15,7 +15,7 @@ class BTrade(NamedTuple): """ Minimalistic Trade result used for functional backtesting """ - sell_reason: ExitType + exit_reason: ExitType open_tick: int close_tick: int enter_tag: Optional[str] = None @@ -35,11 +35,13 @@ class BTContainer(NamedTuple): trailing_only_offset_is_reached: bool = False trailing_stop_positive: Optional[float] = None trailing_stop_positive_offset: float = 0.0 - use_sell_signal: bool = False + use_exit_signal: bool = False use_custom_stoploss: bool = False custom_entry_price: Optional[float] = None custom_exit_price: Optional[float] = None leverage: float = 1.0 + timeout: Optional[int] = None + adjust_entry_price: Optional[float] = None def _get_frame_time_from_offset(offset): diff --git a/tests/optimize/conftest.py b/tests/optimize/conftest.py index 7b93773f0..8a9e0cbf0 100644 --- a/tests/optimize/conftest.py +++ b/tests/optimize/conftest.py @@ -44,7 +44,7 @@ def hyperopt_results(): 'profit_abs': [-0.2, 0.4, -0.2, 0.6], 'trade_duration': [10, 30, 10, 10], 'amount': [0.1, 0.1, 0.1, 0.1], - 'sell_reason': [ExitType.STOP_LOSS, ExitType.ROI, ExitType.STOP_LOSS, ExitType.ROI], + 'exit_reason': [ExitType.STOP_LOSS, ExitType.ROI, ExitType.STOP_LOSS, ExitType.ROI], 'open_date': [ datetime(2019, 1, 1, 9, 15, 0), diff --git a/tests/optimize/test_backtest_detail.py b/tests/optimize/test_backtest_detail.py index f8de780b9..4b4c446e0 100644 --- a/tests/optimize/test_backtest_detail.py +++ b/tests/optimize/test_backtest_detail.py @@ -22,8 +22,8 @@ tc0 = BTContainer(data=[ [3, 5010, 5010, 4980, 5010, 6172, 0, 1], [4, 5010, 5011, 4977, 4995, 6172, 0, 0], [5, 4995, 4995, 4950, 4950, 6172, 0, 0]], - stop_loss=-0.01, roi={"0": 1}, profit_perc=0.002, use_sell_signal=True, - trades=[BTrade(sell_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=4)] + stop_loss=-0.01, roi={"0": 1}, profit_perc=0.002, use_exit_signal=True, + trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=4)] ) # Test 1: Stop-Loss Triggered 1% loss @@ -37,7 +37,7 @@ tc1 = BTContainer(data=[ [4, 4977, 4995, 4977, 4995, 6172, 0, 0], [5, 4995, 4995, 4950, 4950, 6172, 0, 0]], stop_loss=-0.01, roi={"0": 1}, profit_perc=-0.01, - trades=[BTrade(sell_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=2)] + trades=[BTrade(exit_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=2)] ) @@ -52,7 +52,7 @@ tc2 = BTContainer(data=[ [4, 4962, 4987, 4937, 4950, 6172, 0, 0], [5, 4950, 4975, 4925, 4950, 6172, 0, 0]], stop_loss=-0.03, roi={"0": 1}, profit_perc=-0.03, - trades=[BTrade(sell_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=3)] + trades=[BTrade(exit_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=3)] ) @@ -72,8 +72,8 @@ tc3 = BTContainer(data=[ [5, 4962, 4987, 4000, 4000, 6172, 0, 0], # exit with stoploss hit [6, 4950, 4975, 4950, 4950, 6172, 0, 0]], stop_loss=-0.02, roi={"0": 1}, profit_perc=-0.04, - trades=[BTrade(sell_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=2), - BTrade(sell_reason=ExitType.STOP_LOSS, open_tick=4, close_tick=5)] + trades=[BTrade(exit_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=2), + BTrade(exit_reason=ExitType.STOP_LOSS, open_tick=4, close_tick=5)] ) # Test 4: Minus 3% / recovery +15% @@ -89,7 +89,7 @@ tc4 = BTContainer(data=[ [4, 4962, 4987, 4937, 4950, 6172, 0, 0], [5, 4950, 4975, 4925, 4950, 6172, 0, 0]], stop_loss=-0.02, roi={"0": 0.06}, profit_perc=-0.02, - trades=[BTrade(sell_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=2)] + trades=[BTrade(exit_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=2)] ) # Test 5: Drops 0.5% Closes +20%, ROI triggers 3% Gain @@ -103,7 +103,7 @@ tc5 = BTContainer(data=[ [4, 4962, 4987, 4962, 4972, 6172, 0, 0], [5, 4950, 4975, 4925, 4950, 6172, 0, 0]], stop_loss=-0.01, roi={"0": 0.03}, profit_perc=0.03, - trades=[BTrade(sell_reason=ExitType.ROI, open_tick=1, close_tick=3)] + trades=[BTrade(exit_reason=ExitType.ROI, open_tick=1, close_tick=3)] ) # Test 6: Drops 3% / Recovers 6% Positive / Closes 1% positve, Stop-Loss triggers 2% Loss @@ -117,7 +117,7 @@ tc6 = BTContainer(data=[ [4, 4962, 4987, 4950, 4950, 6172, 0, 0], [5, 4950, 4975, 4925, 4950, 6172, 0, 0]], stop_loss=-0.02, roi={"0": 0.05}, profit_perc=-0.02, - trades=[BTrade(sell_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=2)] + trades=[BTrade(exit_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=2)] ) # Test 7: 6% Positive / 1% Negative / Close 1% Positve, ROI Triggers 3% Gain @@ -131,7 +131,7 @@ tc7 = BTContainer(data=[ [4, 4962, 4987, 4950, 4950, 6172, 0, 0], [5, 4950, 4975, 4925, 4950, 6172, 0, 0]], stop_loss=-0.02, roi={"0": 0.03}, profit_perc=0.03, - trades=[BTrade(sell_reason=ExitType.ROI, open_tick=1, close_tick=2)] + trades=[BTrade(exit_reason=ExitType.ROI, open_tick=1, close_tick=2)] ) @@ -145,7 +145,7 @@ tc8 = BTContainer(data=[ [3, 4850, 5050, 4650, 4750, 6172, 0, 0], [4, 4750, 4950, 4350, 4750, 6172, 0, 0]], stop_loss=-0.10, roi={"0": 0.10}, profit_perc=-0.055, trailing_stop=True, - trades=[BTrade(sell_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=3)] + trades=[BTrade(exit_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=3)] ) @@ -159,7 +159,7 @@ tc9 = BTContainer(data=[ [3, 5000, 5200, 4550, 4850, 6172, 0, 0], [4, 4750, 4950, 4350, 4750, 6172, 0, 0]], stop_loss=-0.10, roi={"0": 0.10}, profit_perc=-0.064, trailing_stop=True, - trades=[BTrade(sell_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=3)] + trades=[BTrade(exit_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=3)] ) # Test 10: trailing_stop should raise so candle 3 causes a stoploss @@ -175,7 +175,7 @@ tc10 = BTContainer(data=[ stop_loss=-0.10, roi={"0": 0.10}, profit_perc=-0.1, trailing_stop=True, trailing_only_offset_is_reached=True, trailing_stop_positive_offset=0.10, trailing_stop_positive=0.03, - trades=[BTrade(sell_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=4)] + trades=[BTrade(exit_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=4)] ) # Test 11: trailing_stop should raise so candle 3 causes a stoploss @@ -191,7 +191,7 @@ tc11 = BTContainer(data=[ stop_loss=-0.10, roi={"0": 0.10}, profit_perc=0.019, trailing_stop=True, trailing_only_offset_is_reached=True, trailing_stop_positive_offset=0.05, trailing_stop_positive=0.03, - trades=[BTrade(sell_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=3)] + trades=[BTrade(exit_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=3)] ) # Test 12: trailing_stop should raise in candle 2 and cause a stoploss in the same candle @@ -207,7 +207,7 @@ tc12 = BTContainer(data=[ stop_loss=-0.10, roi={"0": 0.10}, profit_perc=0.019, trailing_stop=True, trailing_only_offset_is_reached=True, trailing_stop_positive_offset=0.05, trailing_stop_positive=0.03, - trades=[BTrade(sell_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=2)] + trades=[BTrade(exit_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=2)] ) # Test 13: Buy and sell ROI on same candle @@ -220,7 +220,7 @@ tc13 = BTContainer(data=[ [3, 4850, 5050, 4750, 4750, 6172, 0, 0], [4, 4750, 4950, 4750, 4750, 6172, 0, 0]], stop_loss=-0.10, roi={"0": 0.01}, profit_perc=0.01, - trades=[BTrade(sell_reason=ExitType.ROI, open_tick=1, close_tick=1)] + trades=[BTrade(exit_reason=ExitType.ROI, open_tick=1, close_tick=1)] ) # Test 14 - Buy and Stoploss on same candle @@ -233,7 +233,7 @@ tc14 = BTContainer(data=[ [3, 4850, 5050, 4750, 4750, 6172, 0, 0], [4, 4750, 4950, 4350, 4750, 6172, 0, 0]], stop_loss=-0.05, roi={"0": 0.10}, profit_perc=-0.05, - trades=[BTrade(sell_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=1)] + trades=[BTrade(exit_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=1)] ) @@ -247,11 +247,11 @@ tc15 = BTContainer(data=[ [3, 4850, 5050, 4750, 4750, 6172, 0, 0], [4, 4750, 4950, 4350, 4750, 6172, 0, 0]], stop_loss=-0.05, roi={"0": 0.01}, profit_perc=-0.04, - trades=[BTrade(sell_reason=ExitType.ROI, open_tick=1, close_tick=1), - BTrade(sell_reason=ExitType.STOP_LOSS, open_tick=2, close_tick=2)] + trades=[BTrade(exit_reason=ExitType.ROI, open_tick=1, close_tick=1), + BTrade(exit_reason=ExitType.STOP_LOSS, open_tick=2, close_tick=2)] ) -# Test 16: Buy, hold for 65 min, then forcesell using roi=-1 +# Test 16: Buy, hold for 65 min, then forceexit using roi=-1 # Causes negative profit even though sell-reason is ROI. # stop-loss: 10%, ROI: 10% (should not apply), -100% after 65 minutes (limits trade duration) tc16 = BTContainer(data=[ @@ -259,14 +259,14 @@ tc16 = BTContainer(data=[ [0, 5000, 5025, 4975, 4987, 6172, 1, 0], [1, 5000, 5025, 4975, 4987, 6172, 0, 0], [2, 4987, 5300, 4950, 5050, 6172, 0, 0], - [3, 4975, 5000, 4940, 4962, 6172, 0, 0], # ForceSell on ROI (roi=-1) + [3, 4975, 5000, 4940, 4962, 6172, 0, 0], # Forceexit on ROI (roi=-1) [4, 4962, 4987, 4950, 4950, 6172, 0, 0], [5, 4950, 4975, 4925, 4950, 6172, 0, 0]], stop_loss=-0.10, roi={"0": 0.10, "65": -1}, profit_perc=-0.012, - trades=[BTrade(sell_reason=ExitType.ROI, open_tick=1, close_tick=3)] + trades=[BTrade(exit_reason=ExitType.ROI, open_tick=1, close_tick=3)] ) -# Test 17: Buy, hold for 120 mins, then forcesell using roi=-1 +# Test 17: Buy, hold for 120 mins, then forceexit using roi=-1 # Causes negative profit even though sell-reason is ROI. # stop-loss: 10%, ROI: 10% (should not apply), -100% after 100 minutes (limits trade duration) # Uses open as sell-rate (special case) - since the roi-time is a multiple of the timeframe. @@ -275,11 +275,11 @@ tc17 = BTContainer(data=[ [0, 5000, 5025, 4975, 4987, 6172, 1, 0], [1, 5000, 5025, 4975, 4987, 6172, 0, 0], [2, 4987, 5300, 4950, 5050, 6172, 0, 0], - [3, 4980, 5000, 4940, 4962, 6172, 0, 0], # ForceSell on ROI (roi=-1) + [3, 4980, 5000, 4940, 4962, 6172, 0, 0], # Forceexit on ROI (roi=-1) [4, 4962, 4987, 4950, 4950, 6172, 0, 0], [5, 4950, 4975, 4925, 4950, 6172, 0, 0]], stop_loss=-0.10, roi={"0": 0.10, "120": -1}, profit_perc=-0.004, - trades=[BTrade(sell_reason=ExitType.ROI, open_tick=1, close_tick=3)] + trades=[BTrade(exit_reason=ExitType.ROI, open_tick=1, close_tick=3)] ) @@ -295,7 +295,7 @@ tc18 = BTContainer(data=[ [4, 4962, 4987, 4950, 4950, 6172, 0, 0], [5, 4950, 4975, 4925, 4950, 6172, 0, 0]], stop_loss=-0.10, roi={"0": 0.10, "120": 0.01}, profit_perc=0.04, - trades=[BTrade(sell_reason=ExitType.ROI, open_tick=1, close_tick=3)] + trades=[BTrade(exit_reason=ExitType.ROI, open_tick=1, close_tick=3)] ) # Test 19: Buy, hold for 119 mins, then drop ROI to 1%, causing a sell in candle 3. @@ -310,7 +310,7 @@ tc19 = BTContainer(data=[ [4, 4962, 4987, 4950, 4950, 6172, 0, 0], [5, 4550, 4975, 4550, 4950, 6172, 0, 0]], stop_loss=-0.10, roi={"0": 0.10, "120": 0.01}, profit_perc=0.01, - trades=[BTrade(sell_reason=ExitType.ROI, open_tick=1, close_tick=3)] + trades=[BTrade(exit_reason=ExitType.ROI, open_tick=1, close_tick=3)] ) # Test 20: Buy, hold for 119 mins, then drop ROI to 1%, causing a sell in candle 3. @@ -325,7 +325,7 @@ tc20 = BTContainer(data=[ [4, 4962, 4987, 4950, 4950, 6172, 0, 0], [5, 4925, 4975, 4925, 4950, 6172, 0, 0]], stop_loss=-0.10, roi={"0": 0.10, "119": 0.01}, profit_perc=0.01, - trades=[BTrade(sell_reason=ExitType.ROI, open_tick=1, close_tick=3)] + trades=[BTrade(exit_reason=ExitType.ROI, open_tick=1, close_tick=3)] ) # Test 21: trailing_stop ROI collision. @@ -342,7 +342,7 @@ tc21 = BTContainer(data=[ stop_loss=-0.10, roi={"0": 0.04}, profit_perc=0.04, trailing_stop=True, trailing_only_offset_is_reached=True, trailing_stop_positive_offset=0.05, trailing_stop_positive=0.03, - trades=[BTrade(sell_reason=ExitType.ROI, open_tick=1, close_tick=2)] + trades=[BTrade(exit_reason=ExitType.ROI, open_tick=1, close_tick=2)] ) # Test 22: trailing_stop Raises in candle 2 - but ROI applies at the same time. @@ -358,7 +358,7 @@ tc22 = BTContainer(data=[ stop_loss=-0.10, roi={"0": 0.04}, profit_perc=0.04, trailing_stop=True, trailing_only_offset_is_reached=True, trailing_stop_positive_offset=0.05, trailing_stop_positive=0.03, - trades=[BTrade(sell_reason=ExitType.ROI, open_tick=1, close_tick=2)] + trades=[BTrade(exit_reason=ExitType.ROI, open_tick=1, close_tick=2)] ) @@ -375,7 +375,7 @@ tc23 = BTContainer(data=[ stop_loss=-0.10, roi={"0": 0.04}, profit_perc=0.04, trailing_stop=True, trailing_only_offset_is_reached=True, trailing_stop_positive_offset=0.05, trailing_stop_positive=0.03, - trades=[BTrade(sell_reason=ExitType.ROI, open_tick=1, close_tick=2, is_short=True)] + trades=[BTrade(exit_reason=ExitType.ROI, open_tick=1, close_tick=2, is_short=True)] ) # Test 24: trailing_stop Raises in candle 2 (does not trigger) @@ -394,7 +394,7 @@ tc24 = BTContainer(data=[ stop_loss=-0.10, roi={"0": 0.1, "119": 0.03}, profit_perc=0.03, trailing_stop=True, trailing_only_offset_is_reached=True, trailing_stop_positive_offset=0.05, trailing_stop_positive=0.03, - trades=[BTrade(sell_reason=ExitType.ROI, open_tick=1, close_tick=3)] + trades=[BTrade(exit_reason=ExitType.ROI, open_tick=1, close_tick=3)] ) # Test 25: Sell with signal sell in candle 3 (stoploss also triggers on this candle) @@ -408,8 +408,8 @@ tc25 = BTContainer(data=[ [3, 5010, 5010, 4855, 5010, 6172, 0, 1], # Triggers stoploss + sellsignal [4, 5010, 5010, 4977, 4995, 6172, 0, 0], [5, 4995, 4995, 4950, 4950, 6172, 0, 0]], - stop_loss=-0.01, roi={"0": 1}, profit_perc=-0.01, use_sell_signal=True, - trades=[BTrade(sell_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=3)] + stop_loss=-0.01, roi={"0": 1}, profit_perc=-0.01, use_exit_signal=True, + trades=[BTrade(exit_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=3)] ) # Test 26: Sell with signal sell in candle 3 (stoploss also triggers on this candle) @@ -423,8 +423,8 @@ tc26 = BTContainer(data=[ [3, 5010, 5010, 4986, 5010, 6172, 0, 1], [4, 5010, 5010, 4855, 4995, 6172, 0, 0], # Triggers stoploss + sellsignal acted on [5, 4995, 4995, 4950, 4950, 6172, 0, 0]], - stop_loss=-0.01, roi={"0": 1}, profit_perc=0.002, use_sell_signal=True, - trades=[BTrade(sell_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=4)] + stop_loss=-0.01, roi={"0": 1}, profit_perc=0.002, use_exit_signal=True, + trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=4)] ) # Test 27: (copy of test26 with leverage) @@ -439,9 +439,9 @@ tc27 = BTContainer(data=[ [3, 5010, 5010, 4986, 5010, 6172, 0, 1], [4, 5010, 5010, 4855, 4995, 6172, 0, 0], # Triggers stoploss + sellsignal acted on [5, 4995, 4995, 4950, 4950, 6172, 0, 0]], - stop_loss=-0.05, roi={"0": 1}, profit_perc=0.002 * 5.0, use_sell_signal=True, + stop_loss=-0.05, roi={"0": 1}, profit_perc=0.002 * 5.0, use_exit_signal=True, leverage=5.0, - trades=[BTrade(sell_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=4)] + trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=4)] ) # Test 28: (copy of test26 with leverage and as short) @@ -456,9 +456,9 @@ tc28 = BTContainer(data=[ [3, 5010, 5010, 4986, 5010, 6172, 0, 0, 0, 1], [4, 4990, 5010, 4855, 4995, 6172, 0, 0, 0, 0], # Triggers stoploss + sellsignal acted on [5, 4995, 4995, 4950, 4950, 6172, 0, 0, 0, 0]], - stop_loss=-0.05, roi={"0": 1}, profit_perc=0.002 * 5.0, use_sell_signal=True, + stop_loss=-0.05, roi={"0": 1}, profit_perc=0.002 * 5.0, use_exit_signal=True, leverage=5.0, - trades=[BTrade(sell_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=4, is_short=True)] + trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=4, is_short=True)] ) # Test 29: Sell with signal sell in candle 3 (ROI at signal candle) # Stoploss at 10% (irrelevant), ROI at 5% (will trigger) @@ -471,8 +471,8 @@ tc29 = BTContainer(data=[ [3, 5010, 5251, 4986, 5010, 6172, 0, 1], # Triggers ROI, sell-signal [4, 5010, 5010, 4855, 4995, 6172, 0, 0], [5, 4995, 4995, 4950, 4950, 6172, 0, 0]], - stop_loss=-0.10, roi={"0": 0.05}, profit_perc=0.05, use_sell_signal=True, - trades=[BTrade(sell_reason=ExitType.ROI, open_tick=1, close_tick=3)] + stop_loss=-0.10, roi={"0": 0.05}, profit_perc=0.05, use_exit_signal=True, + trades=[BTrade(exit_reason=ExitType.ROI, open_tick=1, close_tick=3)] ) # Test 30: Sell with signal sell in candle 3 (ROI at signal candle) @@ -485,8 +485,8 @@ tc30 = BTContainer(data=[ [3, 5010, 5012, 4986, 5010, 6172, 0, 1], # sell-signal [4, 5010, 5251, 4855, 4995, 6172, 0, 0], # Triggers ROI, sell-signal acted on [5, 4995, 4995, 4950, 4950, 6172, 0, 0]], - stop_loss=-0.10, roi={"0": 0.05}, profit_perc=0.002, use_sell_signal=True, - trades=[BTrade(sell_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=4)] + stop_loss=-0.10, roi={"0": 0.05}, profit_perc=0.002, use_exit_signal=True, + trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=4)] ) # Test 31: trailing_stop should raise so candle 3 causes a stoploss @@ -503,7 +503,7 @@ tc31 = BTContainer(data=[ stop_loss=-0.10, roi={"0": 0.10}, profit_perc=-0.03, trailing_stop=True, trailing_only_offset_is_reached=True, trailing_stop_positive_offset=0.05, trailing_stop_positive=0.03, - trades=[BTrade(sell_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=3)] + trades=[BTrade(exit_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=3)] ) # Test 32: (Short of test 31) trailing_stop should raise so candle 3 causes a stoploss @@ -521,8 +521,8 @@ tc32 = BTContainer(data=[ trailing_only_offset_is_reached=True, trailing_stop_positive_offset=0.05, trailing_stop_positive=0.03, trades=[ - BTrade(sell_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=3, is_short=True) - ] + BTrade(exit_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=3, is_short=True) +] ) # Test 33: trailing_stop should be triggered by low of next candle, without adjusting stoploss using @@ -537,7 +537,7 @@ tc33 = BTContainer(data=[ [4, 4750, 4950, 4350, 4750, 6172, 0, 0]], stop_loss=-0.10, roi={"0": 0.10}, profit_perc=-0.02, trailing_stop=True, trailing_stop_positive=0.03, - trades=[BTrade(sell_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=2)] + trades=[BTrade(exit_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=2)] ) # Test 34: trailing_stop should be triggered immediately on trade open candle. @@ -551,7 +551,7 @@ tc34 = BTContainer(data=[ [4, 4750, 4950, 4350, 4750, 6172, 0, 0]], stop_loss=-0.10, roi={"0": 0.10}, profit_perc=-0.01, trailing_stop=True, trailing_stop_positive=0.01, - trades=[BTrade(sell_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=1)] + trades=[BTrade(exit_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=1)] ) # Test 35: trailing_stop should be triggered immediately on trade open candle. @@ -566,7 +566,7 @@ tc35 = BTContainer(data=[ stop_loss=-0.10, roi={"0": 0.10}, profit_perc=0.01, trailing_stop=True, trailing_only_offset_is_reached=True, trailing_stop_positive_offset=0.02, trailing_stop_positive=0.01, - trades=[BTrade(sell_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=1)] + trades=[BTrade(exit_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=1)] ) # Test 36: trailing_stop should be triggered immediately on trade open candle. @@ -581,7 +581,7 @@ tc36 = BTContainer(data=[ stop_loss=-0.01, roi={"0": 0.10}, profit_perc=-0.01, trailing_stop=True, trailing_only_offset_is_reached=True, trailing_stop_positive_offset=0.02, trailing_stop_positive=0.01, use_custom_stoploss=True, - trades=[BTrade(sell_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=1)] + trades=[BTrade(exit_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=1)] ) # Test 37: trailing_stop should be triggered immediately on trade open candle. @@ -597,7 +597,7 @@ tc37 = BTContainer(data=[ trailing_only_offset_is_reached=True, trailing_stop_positive_offset=0.02, trailing_stop_positive=0.01, use_custom_stoploss=True, trades=[BTrade( - sell_reason=ExitType.TRAILING_STOP_LOSS, + exit_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=1, enter_tag='buy_signal_01' @@ -617,7 +617,7 @@ tc38 = BTContainer(data=[ trailing_only_offset_is_reached=True, trailing_stop_positive_offset=0.02, trailing_stop_positive=0.01, use_custom_stoploss=True, trades=[BTrade( - sell_reason=ExitType.TRAILING_STOP_LOSS, + exit_reason=ExitType.TRAILING_STOP_LOSS, open_tick=1, close_tick=1, enter_tag='short_signal_01', @@ -647,7 +647,7 @@ tc40 = BTContainer(data=[ [4, 4750, 4950, 4350, 4750, 6172, 0, 0]], stop_loss=-0.01, roi={"0": 0.10}, profit_perc=-0.01, custom_entry_price=7200, trades=[ - BTrade(sell_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=1) + BTrade(exit_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=1) ]) # Test 41: Custom-entry-price above all candles should have rate adjusted to "entry candle high" @@ -661,8 +661,8 @@ tc41 = BTContainer(data=[ stop_loss=-0.01, roi={"0": 0.10}, profit_perc=-0.01, custom_entry_price=4000, trades=[ - BTrade(sell_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=1, is_short=True) - ] + BTrade(exit_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=1, is_short=True) +] ) # Test 42: Custom-entry-price around candle low @@ -678,7 +678,7 @@ tc42 = BTContainer(data=[ [4, 4750, 4950, 4350, 4750, 6172, 0, 0]], stop_loss=-0.10, roi={"0": 0.01}, profit_perc=0.01, custom_entry_price=4952, - trades=[BTrade(sell_reason=ExitType.ROI, open_tick=1, close_tick=2)] + trades=[BTrade(exit_reason=ExitType.ROI, open_tick=1, close_tick=2)] ) # Test 43: Custom-entry-price around candle low @@ -693,7 +693,7 @@ tc43 = BTContainer(data=[ [4, 4750, 4950, 4350, 4750, 6172, 0, 0]], stop_loss=-0.10, roi={"0": 0.01}, profit_perc=0.01, custom_entry_price=4952, - trades=[BTrade(sell_reason=ExitType.ROI, open_tick=1, close_tick=1)] + trades=[BTrade(exit_reason=ExitType.ROI, open_tick=1, close_tick=1)] ) # Test 44: Custom exit price below all candles @@ -706,9 +706,9 @@ tc44 = BTContainer(data=[ [3, 5100, 5100, 4950, 4950, 6172, 0, 0], [4, 5000, 5100, 4950, 4950, 6172, 0, 0]], stop_loss=-0.10, roi={"0": 0.10}, profit_perc=-0.01, - use_sell_signal=True, + use_exit_signal=True, custom_exit_price=4552, - trades=[BTrade(sell_reason=ExitType.SELL_SIGNAL, open_tick=1, close_tick=3)] + trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=3)] ) # Test 45: Custom exit price above all candles @@ -721,9 +721,9 @@ tc45 = BTContainer(data=[ [3, 5100, 5100, 4950, 4950, 6172, 0, 0], [4, 5000, 5100, 4950, 4950, 6172, 0, 0]], stop_loss=-0.10, roi={"0": 0.10}, profit_perc=0.0, - use_sell_signal=True, + use_exit_signal=True, custom_exit_price=6052, - trades=[BTrade(sell_reason=ExitType.FORCE_SELL, open_tick=1, close_tick=4)] + trades=[BTrade(exit_reason=ExitType.FORCE_EXIT, open_tick=1, close_tick=4)] ) # Test 46: (Short of tc45) Custom short exit price above below candles @@ -736,9 +736,9 @@ tc46 = BTContainer(data=[ [3, 5100, 5100, 4950, 4950, 6172, 0, 0, 0, 0], [4, 5000, 5100, 4950, 4950, 6172, 0, 0, 0, 0]], stop_loss=-0.10, roi={"0": 0.10}, profit_perc=0.0, - use_sell_signal=True, + use_exit_signal=True, custom_exit_price=4700, - trades=[BTrade(sell_reason=ExitType.FORCE_SELL, open_tick=1, close_tick=4, is_short=True)] + trades=[BTrade(exit_reason=ExitType.FORCE_EXIT, open_tick=1, close_tick=4, is_short=True)] ) # Test 47: Colliding long and short signal @@ -750,10 +750,95 @@ tc47 = BTContainer(data=[ [3, 5100, 5100, 4950, 4950, 6172, 0, 0, 0, 0], [4, 5000, 5100, 4950, 4950, 6172, 0, 0, 0, 0]], stop_loss=-0.10, roi={"0": 0.10}, profit_perc=0.0, - use_sell_signal=True, + use_exit_signal=True, trades=[] ) +# Test 48: Custom-entry-price below all candles - readjust order +tc48 = BTContainer(data=[ + # D O H L C V EL XL ES Xs BT + [0, 5000, 5050, 4950, 5000, 6172, 1, 0], + [1, 5000, 5500, 4951, 5000, 6172, 0, 0], # timeout + [2, 4900, 5250, 4500, 5100, 6172, 0, 0], # Order readjust + [3, 5100, 5100, 4650, 4750, 6172, 0, 1], + [4, 4750, 4950, 4350, 4750, 6172, 0, 0]], + stop_loss=-0.2, roi={"0": 0.10}, profit_perc=-0.087, + use_exit_signal=True, timeout=1000, + custom_entry_price=4200, adjust_entry_price=5200, + trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=4, is_short=False)] +) + + +# Test 49: Custom-entry-price short above all candles - readjust order +tc49 = BTContainer(data=[ + # D O H L C V EL XL ES Xs BT + [0, 5000, 5050, 4950, 5000, 6172, 0, 0, 1, 0], + [1, 5000, 5200, 4951, 5000, 6172, 0, 0, 0, 0], # timeout + [2, 4900, 5250, 4900, 5100, 6172, 0, 0, 0, 0], # Order readjust + [3, 5100, 5100, 4650, 4750, 6172, 0, 0, 0, 1], + [4, 4750, 4950, 4350, 4750, 6172, 0, 0, 0, 0]], + stop_loss=-0.2, roi={"0": 0.10}, profit_perc=0.05, + use_exit_signal=True, timeout=1000, + custom_entry_price=5300, adjust_entry_price=5000, + trades=[BTrade(exit_reason=ExitType.EXIT_SIGNAL, open_tick=1, close_tick=4, is_short=True)] +) + +# Test 50: Custom-entry-price below all candles - readjust order cancels order +tc50 = BTContainer(data=[ + # D O H L C V EL XL ES Xs BT + [0, 5000, 5050, 4950, 5000, 6172, 1, 0], # Enter long - place order + [1, 5000, 5500, 4951, 5000, 6172, 0, 0], # Order readjust - cancel order + [2, 4900, 5250, 4500, 5100, 6172, 0, 0], + [3, 5100, 5100, 4650, 4750, 6172, 0, 0], + [4, 4750, 4950, 4350, 4750, 6172, 0, 0]], + stop_loss=-0.01, roi={"0": 0.10}, profit_perc=0.0, + use_exit_signal=True, timeout=1000, + custom_entry_price=4200, adjust_entry_price=None, + trades=[] +) + +# Test 51: Custom-entry-price below all candles - readjust order leaves order in place and timeout. +tc51 = BTContainer(data=[ + # D O H L C V EL XL ES Xs BT + [0, 5000, 5050, 4950, 5000, 6172, 1, 0], # Enter long - place order + [1, 5000, 5500, 4951, 5000, 6172, 0, 0], # Order readjust - replace order + [2, 4900, 5250, 4500, 5100, 6172, 0, 0], # Order readjust - maintain order + [3, 5100, 5100, 4650, 4750, 6172, 0, 0], # Timeout + [4, 4750, 4950, 4350, 4750, 6172, 0, 0]], + stop_loss=-0.01, roi={"0": 0.10}, profit_perc=0.0, + use_exit_signal=True, timeout=60, + custom_entry_price=4200, adjust_entry_price=4100, + trades=[] +) + +# Test 52: Custom-entry-price below all candles - readjust order - stoploss +tc52 = BTContainer(data=[ + # D O H L C V EL XL ES Xs BT + [0, 5000, 5050, 4950, 5000, 6172, 1, 0], + [1, 5000, 5500, 4951, 5000, 6172, 0, 0], # enter trade (signal on last candle) + [2, 4900, 5250, 4500, 5100, 6172, 0, 0], # Order readjust + [3, 5100, 5100, 4650, 4750, 6172, 0, 0], # stoploss hit? + [4, 4750, 4950, 4350, 4750, 6172, 0, 0]], + stop_loss=-0.03, roi={"0": 0.10}, profit_perc=-0.03, + use_exit_signal=True, timeout=1000, + custom_entry_price=4200, adjust_entry_price=5200, + trades=[BTrade(exit_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=2, is_short=False)] +) + + +# Test 53: Custom-entry-price short above all candles - readjust order - stoploss +tc53 = BTContainer(data=[ + # D O H L C V EL XL ES Xs BT + [0, 5000, 5050, 4950, 5000, 6172, 0, 0, 1, 0], + [1, 5000, 5200, 4951, 5000, 6172, 0, 0, 0, 0], # enter trade (signal on last candle) + [2, 4900, 5250, 4900, 5100, 6172, 0, 0, 0, 0], # Order readjust + [3, 5100, 5100, 4650, 4750, 6172, 0, 0, 0, 1], # stoploss hit? + [4, 4750, 4950, 4350, 4750, 6172, 0, 0, 0, 0]], + stop_loss=-0.03, roi={"0": 0.10}, profit_perc=-0.03, + use_exit_signal=True, timeout=1000, + custom_entry_price=5300, adjust_entry_price=5000, + trades=[BTrade(exit_reason=ExitType.STOP_LOSS, open_tick=1, close_tick=2, is_short=True)] +) TESTS = [ tc0, @@ -804,11 +889,17 @@ TESTS = [ tc45, tc46, tc47, + tc48, + tc49, + tc50, + tc51, + tc52, + tc53, ] @pytest.mark.parametrize("data", TESTS) -def test_backtest_results(default_conf, fee, mocker, caplog, data) -> None: +def test_backtest_results(default_conf, fee, mocker, caplog, data: BTContainer) -> None: """ run functional tests """ @@ -817,11 +908,16 @@ def test_backtest_results(default_conf, fee, mocker, caplog, data) -> None: default_conf["timeframe"] = tests_timeframe default_conf["trailing_stop"] = data.trailing_stop default_conf["trailing_only_offset_is_reached"] = data.trailing_only_offset_is_reached + if data.timeout: + default_conf['unfilledtimeout'].update({ + 'entry': data.timeout, + 'exit': data.timeout, + }) # Only add this to configuration If it's necessary if data.trailing_stop_positive is not None: default_conf["trailing_stop_positive"] = data.trailing_stop_positive default_conf["trailing_stop_positive_offset"] = data.trailing_stop_positive_offset - default_conf["use_sell_signal"] = data.use_sell_signal + default_conf["use_exit_signal"] = data.use_exit_signal mocker.patch("freqtrade.exchange.Exchange.get_fee", return_value=0.0) mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001) @@ -840,6 +936,8 @@ def test_backtest_results(default_conf, fee, mocker, caplog, data) -> None: backtesting.strategy.custom_entry_price = MagicMock(return_value=data.custom_entry_price) if data.custom_exit_price: backtesting.strategy.custom_exit_price = MagicMock(return_value=data.custom_exit_price) + backtesting.strategy.adjust_entry_price = MagicMock(return_value=data.adjust_entry_price) + backtesting.strategy.use_custom_stoploss = data.use_custom_stoploss backtesting.strategy.leverage = lambda **kwargs: data.leverage caplog.set_level(logging.DEBUG) @@ -861,8 +959,10 @@ def test_backtest_results(default_conf, fee, mocker, caplog, data) -> None: for c, trade in enumerate(data.trades): res: BTrade = results.iloc[c] - assert res.sell_reason == trade.sell_reason.value + assert res.exit_reason == trade.exit_reason.value assert res.enter_tag == trade.enter_tag assert res.open_date == _get_frame_time_from_offset(trade.open_tick) assert res.close_date == _get_frame_time_from_offset(trade.close_tick) assert res.is_short == trade.is_short + backtesting.cleanup() + del backtesting diff --git a/tests/optimize/test_backtesting.py b/tests/optimize/test_backtesting.py index 736071af9..c87a0ef73 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 @@ -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: @@ -384,14 +385,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 +410,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: @@ -497,14 +501,14 @@ 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) def test_backtest__enter_trade(default_conf, fee, mocker) -> None: - default_conf['use_sell_signal'] = False + default_conf['use_exit_signal'] = False mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001) mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf')) @@ -563,7 +567,7 @@ def test_backtest__enter_trade(default_conf, fee, mocker) -> None: def test_backtest__enter_trade_futures(default_conf_usdt, fee, mocker) -> None: - default_conf_usdt['use_sell_signal'] = False + default_conf_usdt['use_exit_signal'] = False mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001) mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf')) @@ -645,7 +649,7 @@ def test_backtest__enter_trade_futures(default_conf_usdt, fee, mocker) -> None: def test_backtest__get_sell_trade_entry(default_conf, fee, mocker) -> None: - default_conf['use_sell_signal'] = False + default_conf['use_exit_signal'] = False mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001) mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf')) @@ -711,9 +715,9 @@ 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.sell_reason == ExitType.ROI.value + assert res.exit_reason == ExitType.ROI.value assert res.close_date_utc == datetime(2020, 1, 1, 5, 0, tzinfo=timezone.utc) # Enter new trade @@ -724,15 +728,15 @@ 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.sell_reason == ExitType.ROI.value + assert res.exit_reason == ExitType.ROI.value # Sell at minute 3 (not available above!) assert res.close_date_utc == datetime(2020, 1, 1, 5, 3, tzinfo=timezone.utc) sell_order = res.select_order('sell', True) @@ -740,7 +744,7 @@ def test_backtest__get_sell_trade_entry(default_conf, fee, mocker) -> None: def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None: - default_conf['use_sell_signal'] = False + default_conf['use_exit_signal'] = False mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001) mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf')) @@ -781,7 +785,7 @@ def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None: 'trade_duration': [235, 40], 'profit_ratio': [0.0, 0.0], 'profit_abs': [0.0, 0.0], - 'sell_reason': [ExitType.ROI.value, ExitType.ROI.value], + 'exit_reason': [ExitType.ROI.value, ExitType.ROI.value], 'initial_stop_loss_abs': [0.0940005, 0.09272236], 'initial_stop_loss_ratio': [-0.1, -0.1], 'stop_loss_abs': [0.0940005, 0.09272236], @@ -807,7 +811,7 @@ def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None: def test_backtest_1min_timeframe(default_conf, fee, mocker, testdatadir) -> None: - default_conf['use_sell_signal'] = False + default_conf['use_exit_signal'] = False mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001) mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf')) @@ -832,6 +836,36 @@ def test_backtest_1min_timeframe(default_conf, fee, mocker, testdatadir) -> None assert len(results['results']) == 1 +def test_backtest_trim_no_data_left(default_conf, fee, mocker, testdatadir) -> None: + default_conf['use_exit_signal'] = False + mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) + mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001) + mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf')) + patch_exchange(mocker) + backtesting = Backtesting(default_conf) + backtesting._set_strategy(backtesting.strategylist[0]) + timerange = TimeRange('date', None, 1517227800, 0) + backtesting.required_startup = 100 + backtesting.timerange = timerange + data = history.load_data(datadir=testdatadir, timeframe='5m', pairs=['UNITTEST/BTC'], + timerange=timerange) + df = data['UNITTEST/BTC'] + df.loc[:, 'date'] = df.loc[:, 'date'] - timedelta(days=1) + # Trimming 100 candles, so after 2nd trimming, no candle is left. + df = df.iloc[:100] + data['XRP/USDT'] = df + processed = backtesting.strategy.advise_all_indicators(data) + min_date, max_date = get_timerange(processed) + + backtesting.backtest( + processed=deepcopy(processed), + start_date=min_date, + end_date=max_date, + max_open_trades=10, + position_stacking=False, + ) + + def test_processed(default_conf, mocker, testdatadir) -> None: patch_exchange(mocker) backtesting = Backtesting(default_conf) @@ -848,7 +882,7 @@ def test_processed(default_conf, mocker, testdatadir) -> None: def test_backtest_dataprovider_analyzed_df(default_conf, fee, mocker, testdatadir) -> None: - default_conf['use_sell_signal'] = False + default_conf['use_exit_signal'] = False mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001) mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=100000) @@ -1121,10 +1155,10 @@ def test_backtest_start_timerange(default_conf, mocker, caplog, testdatadir): def test_backtest_start_multi_strat(default_conf, mocker, caplog, testdatadir): default_conf.update({ - "use_sell_signal": True, - "sell_profit_only": False, - "sell_profit_offset": 0.0, - "ignore_roi_if_buy_signal": False, + "use_exit_signal": True, + "exit_profit_only": False, + "exit_profit_offset": 0.0, + "ignore_roi_if_entry_signal": False, }) patch_exchange(mocker) backtestmock = MagicMock(return_value={ @@ -1148,7 +1182,7 @@ def test_backtest_start_multi_strat(default_conf, mocker, caplog, testdatadir): text_table_bt_results=text_table_mock, text_table_strategy=strattable_mock, generate_pair_metrics=MagicMock(), - generate_sell_reason_stats=sell_reason_mock, + generate_exit_reason_stats=sell_reason_mock, generate_strategy_comparison=strat_summary, generate_daily_stats=MagicMock(), ) @@ -1165,7 +1199,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) @@ -1188,20 +1222,19 @@ 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_sell_signal": True, - "sell_profit_only": False, - "sell_profit_offset": 0.0, - "ignore_roi_if_buy_signal": False, + "use_exit_signal": True, + "exit_profit_only": False, + "exit_profit_offset": 0.0, + "ignore_roi_if_entry_signal": False, }) patch_exchange(mocker) result1 = pd.DataFrame({'pair': ['XRP/BTC', 'LTC/BTC'], @@ -1219,7 +1252,7 @@ def test_backtest_start_multi_strat_nomock(default_conf, mocker, caplog, testdat 'close_rate': [0.104969, 0.103541], "is_short": [False, False], - 'sell_reason': [ExitType.ROI, ExitType.ROI] + 'exit_reason': [ExitType.ROI, ExitType.ROI] }) result2 = pd.DataFrame({'pair': ['XRP/BTC', 'LTC/BTC', 'ETH/BTC'], 'profit_ratio': [0.03, 0.01, 0.1], @@ -1237,7 +1270,7 @@ def test_backtest_start_multi_strat_nomock(default_conf, mocker, caplog, testdat 'open_rate': [0.104445, 0.10302485, 0.122541], 'close_rate': [0.104969, 0.103541, 0.123541], "is_short": [False, False, False], - 'sell_reason': [ExitType.ROI, ExitType.ROI, ExitType.STOP_LOSS] + 'exit_reason': [ExitType.ROI, ExitType.ROI, ExitType.STOP_LOSS] }) backtestmock = MagicMock(side_effect=[ { @@ -1277,7 +1310,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) @@ -1294,7 +1327,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: @@ -1309,6 +1342,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): @@ -1316,10 +1382,10 @@ def test_backtest_start_nomock_futures(default_conf_usdt, mocker, default_conf_usdt.update({ "trading_mode": "futures", "margin_mode": "isolated", - "use_sell_signal": True, - "sell_profit_only": False, - "sell_profit_offset": 0.0, - "ignore_roi_if_buy_signal": False, + "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) @@ -1337,7 +1403,7 @@ def test_backtest_start_nomock_futures(default_conf_usdt, mocker, 'stake_amount': [0.01, 0.01], 'open_rate': [0.104445, 0.10302485], 'close_rate': [0.104969, 0.103541], - 'sell_reason': [ExitType.ROI, ExitType.ROI] + 'exit_reason': [ExitType.ROI, ExitType.ROI] }) result2 = pd.DataFrame({'pair': ['XRP/USDT', 'XRP/USDT', 'XRP/USDT'], 'profit_ratio': [0.03, 0.01, 0.1], @@ -1355,7 +1421,7 @@ def test_backtest_start_nomock_futures(default_conf_usdt, mocker, 'stake_amount': [0.01, 0.01, 0.01], 'open_rate': [0.104445, 0.10302485, 0.122541], 'close_rate': [0.104969, 0.103541, 0.123541], - 'sell_reason': [ExitType.ROI, ExitType.ROI, ExitType.STOP_LOSS] + 'exit_reason': [ExitType.ROI, ExitType.ROI, ExitType.STOP_LOSS] }) backtestmock = MagicMock(side_effect=[ { @@ -1420,10 +1486,10 @@ def test_backtest_start_multi_strat_nomock_detail(default_conf, mocker, caplog, testdatadir, capsys): # Tests detail-data loading default_conf.update({ - "use_sell_signal": True, - "sell_profit_only": False, - "sell_profit_offset": 0.0, - "ignore_roi_if_buy_signal": False, + "use_exit_signal": True, + "exit_profit_only": False, + "exit_profit_offset": 0.0, + "ignore_roi_if_entry_signal": False, }) patch_exchange(mocker) result1 = pd.DataFrame({'pair': ['XRP/BTC', 'LTC/BTC'], @@ -1440,7 +1506,7 @@ def test_backtest_start_multi_strat_nomock_detail(default_conf, mocker, 'stake_amount': [0.01, 0.01], 'open_rate': [0.104445, 0.10302485], 'close_rate': [0.104969, 0.103541], - 'sell_reason': [ExitType.ROI, ExitType.ROI] + 'exit_reason': [ExitType.ROI, ExitType.ROI] }) result2 = pd.DataFrame({'pair': ['XRP/BTC', 'LTC/BTC', 'ETH/BTC'], 'profit_ratio': [0.03, 0.01, 0.1], @@ -1458,7 +1524,7 @@ def test_backtest_start_multi_strat_nomock_detail(default_conf, mocker, 'stake_amount': [0.01, 0.01, 0.01], 'open_rate': [0.104445, 0.10302485, 0.122541], 'close_rate': [0.104969, 0.103541, 0.123541], - 'sell_reason': [ExitType.ROI, ExitType.ROI, ExitType.STOP_LOSS] + 'exit_reason': [ExitType.ROI, ExitType.ROI, ExitType.STOP_LOSS] }) backtestmock = MagicMock(side_effect=[ { @@ -1527,10 +1593,10 @@ def test_backtest_start_multi_strat_nomock_detail(default_conf, mocker, def test_backtest_start_multi_strat_caching(default_conf, mocker, caplog, testdatadir, run_id, start_delta, cache): default_conf.update({ - "use_sell_signal": True, - "sell_profit_only": False, - "sell_profit_offset": 0.0, - "ignore_roi_if_buy_signal": False, + "use_exit_signal": True, + "exit_profit_only": False, + "exit_profit_offset": 0.0, + "ignore_roi_if_entry_signal": False, }) patch_exchange(mocker) backtestmock = MagicMock(return_value={ @@ -1559,7 +1625,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=[ { @@ -1568,9 +1634,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=[ @@ -1594,7 +1660,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) @@ -1616,7 +1682,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).', ] @@ -1624,12 +1690,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/optimize/test_backtesting_adjust_position.py b/tests/optimize/test_backtesting_adjust_position.py index 95847c660..5babfb548 100644 --- a/tests/optimize/test_backtesting_adjust_position.py +++ b/tests/optimize/test_backtesting_adjust_position.py @@ -14,7 +14,7 @@ from tests.conftest import patch_exchange def test_backtest_position_adjustment(default_conf, fee, mocker, testdatadir) -> None: - default_conf['use_sell_signal'] = False + default_conf['use_exit_signal'] = False mocker.patch('freqtrade.exchange.Exchange.get_fee', fee) mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001) mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf')) @@ -60,7 +60,7 @@ def test_backtest_position_adjustment(default_conf, fee, mocker, testdatadir) -> 'trade_duration': [200, 40], 'profit_ratio': [0.0, 0.0], 'profit_abs': [0.0, 0.0], - 'sell_reason': [ExitType.ROI.value, ExitType.ROI.value], + 'exit_reason': [ExitType.ROI.value, ExitType.ROI.value], 'initial_stop_loss_abs': [0.0940005, 0.09272236], 'initial_stop_loss_ratio': [-0.1, -0.1], 'stop_loss_abs': [0.0940005, 0.09272236], diff --git a/tests/optimize/test_edge_cli.py b/tests/optimize/test_edge_cli.py index f0f436a43..8241a5362 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_cli.strategy.bot_started is True def test_edge_init_fee(mocker, edge_conf) -> None: diff --git a/tests/optimize/test_hyperopt.py b/tests/optimize/test_hyperopt.py index 3a6fe9293..75944390e 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 } ) @@ -357,8 +359,8 @@ def test_hyperopt_format_results(hyperopt): "is_open": [False, False, False, True], "is_short": [False, False, False, False], "stake_amount": [0.01, 0.01, 0.01, 0.01], - "sell_reason": [ExitType.ROI, ExitType.STOP_LOSS, - ExitType.ROI, ExitType.FORCE_SELL] + "exit_reason": [ExitType.ROI, ExitType.STOP_LOSS, + ExitType.ROI, ExitType.FORCE_EXIT] }), 'config': hyperopt.config, 'locks': [], @@ -428,8 +430,8 @@ def test_generate_optimizer(mocker, hyperopt_conf) -> None: "is_open": [False, False, False, True], "is_short": [False, False, False, False], "stake_amount": [0.01, 0.01, 0.01, 0.01], - "sell_reason": [ExitType.ROI, ExitType.STOP_LOSS, - ExitType.ROI, ExitType.FORCE_SELL] + "exit_reason": [ExitType.ROI, ExitType.STOP_LOSS, + ExitType.ROI, ExitType.FORCE_EXIT] }), 'config': hyperopt_conf, 'locks': [], diff --git a/tests/optimize/test_hyperoptloss.py b/tests/optimize/test_hyperoptloss.py index e3f6daf6c..be1c313f6 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 @@ -85,6 +85,7 @@ def test_loss_calculation_has_limited_profit(hyperopt_conf, hyperopt_results) -> "SharpeHyperOptLoss", "SharpeHyperOptLossDaily", "MaxDrawDownHyperOptLoss", + "MaxDrawDownRelativeHyperOptLoss", "CalmarHyperOptLoss", "ProfitDrawDownHyperOptLoss", diff --git a/tests/optimize/test_optimize_reports.py b/tests/optimize/test_optimize_reports.py index 3ff8d5870..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 @@ -15,11 +16,11 @@ from freqtrade.edge import PairInfo from freqtrade.enums import ExitType from freqtrade.optimize.optimize_reports import (_get_resample_from_period, generate_backtest_stats, generate_daily_stats, generate_edge_table, - generate_pair_metrics, + generate_exit_reason_stats, generate_pair_metrics, generate_periodic_breakdown_stats, - generate_sell_reason_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 @@ -77,8 +78,8 @@ def test_generate_backtest_stats(default_conf, testdatadir, tmpdir): "is_open": [False, False, False, True], "is_short": [False, False, False, False], "stake_amount": [0.01, 0.01, 0.01, 0.01], - "sell_reason": [ExitType.ROI, ExitType.STOP_LOSS, - ExitType.ROI, ExitType.FORCE_SELL] + "exit_reason": [ExitType.ROI, ExitType.STOP_LOSS, + ExitType.ROI, ExitType.FORCE_EXIT] }), 'config': default_conf, 'locks': [], @@ -129,8 +130,8 @@ def test_generate_backtest_stats(default_conf, testdatadir, tmpdir): "is_open": [False, False, False, True], "is_short": [False, False, False, False], "stake_amount": [0.01, 0.01, 0.01, 0.01], - "sell_reason": [ExitType.ROI, ExitType.ROI, - ExitType.STOP_LOSS, ExitType.FORCE_SELL] + "exit_reason": [ExitType.ROI, ExitType.ROI, + ExitType.STOP_LOSS, ExitType.FORCE_EXIT] }), 'config': default_conf, 'locks': [], @@ -191,7 +192,7 @@ def test_store_backtest_stats(testdatadir, mocker): assert dump_mock.call_count == 3 assert isinstance(dump_mock.call_args_list[0][0][0], Path) - assert str(dump_mock.call_args_list[0][0][0]).startswith(str(testdatadir/'backtest-result')) + assert str(dump_mock.call_args_list[0][0][0]).startswith(str(testdatadir / 'backtest-result')) dump_mock.reset_mock() filename = testdatadir / 'testresult.json' @@ -202,6 +203,62 @@ 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_joblib') + + 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() + # 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(): results = pd.DataFrame( @@ -229,7 +286,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) @@ -249,7 +306,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) @@ -265,7 +322,7 @@ def test_generate_trading_stats(testdatadir): assert res['losses'] == 0 -def test_text_table_sell_reason(): +def test_text_table_exit_reason(): results = pd.DataFrame( { @@ -276,7 +333,7 @@ def test_text_table_sell_reason(): 'wins': [2, 0, 0], 'draws': [0, 0, 0], 'losses': [0, 0, 1], - 'sell_reason': [ExitType.ROI, ExitType.ROI, ExitType.STOP_LOSS] + 'exit_reason': [ExitType.ROI, ExitType.ROI, ExitType.STOP_LOSS] } ) @@ -291,9 +348,9 @@ def test_text_table_sell_reason(): ' -0.2 | -5 |' ) - sell_reason_stats = generate_sell_reason_stats(max_open_trades=2, + exit_reason_stats = generate_exit_reason_stats(max_open_trades=2, results=results) - assert text_table_exit_reason(sell_reason_stats=sell_reason_stats, + assert text_table_exit_reason(exit_reason_stats=exit_reason_stats, stake_currency='BTC') == result_str @@ -308,23 +365,23 @@ def test_generate_sell_reason_stats(): 'wins': [2, 0, 0], 'draws': [0, 0, 0], 'losses': [0, 0, 1], - 'sell_reason': [ExitType.ROI.value, ExitType.ROI.value, ExitType.STOP_LOSS.value] + 'exit_reason': [ExitType.ROI.value, ExitType.ROI.value, ExitType.STOP_LOSS.value] } ) - sell_reason_stats = generate_sell_reason_stats(max_open_trades=2, + exit_reason_stats = generate_exit_reason_stats(max_open_trades=2, results=results) - roi_result = sell_reason_stats[0] - assert roi_result['sell_reason'] == 'roi' + roi_result = exit_reason_stats[0] + assert roi_result['exit_reason'] == 'roi' assert roi_result['trades'] == 2 assert pytest.approx(roi_result['profit_mean']) == 0.15 assert roi_result['profit_mean_pct'] == round(roi_result['profit_mean'] * 100, 2) assert pytest.approx(roi_result['profit_mean']) == 0.15 assert roi_result['profit_mean_pct'] == round(roi_result['profit_mean'] * 100, 2) - stop_result = sell_reason_stats[1] + stop_result = exit_reason_stats[1] - assert stop_result['sell_reason'] == 'stop_loss' + assert stop_result['exit_reason'] == 'stop_loss' assert stop_result['trades'] == 1 assert pytest.approx(stop_result['profit_mean']) == -0.1 assert stop_result['profit_mean_pct'] == round(stop_result['profit_mean'] * 100, 2) @@ -333,7 +390,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') @@ -365,7 +422,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') @@ -393,7 +450,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/plugins/test_pairlist.py b/tests/plugins/test_pairlist.py index d80f23c8a..c29e619b1 100644 --- a/tests/plugins/test_pairlist.py +++ b/tests/plugins/test_pairlist.py @@ -470,12 +470,16 @@ def test_VolumePairList_refresh_empty(mocker, markets_empty, whitelist_conf): "BTC", ['ETH/BTC', 'TKN/BTC']), # VolumePairList with no offset = unchanged pairlist ([{"method": "VolumePairList", "number_assets": 20, "sort_key": "quoteVolume"}, - {"method": "OffsetFilter", "offset": 0}], + {"method": "OffsetFilter", "offset": 0, "number_assets": 0}], "USDT", ['ETH/USDT', 'NANO/USDT', 'ADAHALF/USDT', 'ADADOUBLE/USDT']), # VolumePairList with offset = 2 ([{"method": "VolumePairList", "number_assets": 20, "sort_key": "quoteVolume"}, {"method": "OffsetFilter", "offset": 2}], "USDT", ['ADAHALF/USDT', 'ADADOUBLE/USDT']), + # VolumePairList with offset and limit + ([{"method": "VolumePairList", "number_assets": 20, "sort_key": "quoteVolume"}, + {"method": "OffsetFilter", "offset": 1, "number_assets": 2}], + "USDT", ['NANO/USDT', 'ADAHALF/USDT']), # VolumePairList with higher offset, than total pairlist ([{"method": "VolumePairList", "number_assets": 20, "sort_key": "quoteVolume"}, {"method": "OffsetFilter", "offset": 100}], @@ -1152,6 +1156,10 @@ def test_spreadfilter_invalid_data(mocker, default_conf, markets, tickers, caplo "0.01 and above 0.99 over the last days.'}]", None ), + ({"method": "OffsetFilter", "offset": 5, "number_assets": 10}, + "[{'OffsetFilter': 'OffsetFilter - Taking 10 Pairs, starting from 5.'}]", + None + ), ]) def test_pricefilter_desc(mocker, whitelist_conf, markets, pairlistconfig, desc_expected, exception_expected): diff --git a/tests/plugins/test_pairlocks.py b/tests/plugins/test_pairlocks.py index f9e5583ed..0ba9bb746 100644 --- a/tests/plugins/test_pairlocks.py +++ b/tests/plugins/test_pairlocks.py @@ -21,8 +21,22 @@ def test_PairLocks(use_db): pair = 'ETH/BTC' assert not PairLocks.is_pair_locked(pair) PairLocks.lock_pair(pair, arrow.utcnow().shift(minutes=4).datetime) - # ETH/BTC locked for 4 minutes + # ETH/BTC locked for 4 minutes (on both sides) assert PairLocks.is_pair_locked(pair) + assert PairLocks.is_pair_locked(pair, side='long') + assert PairLocks.is_pair_locked(pair, side='short') + + pair = 'BNB/BTC' + PairLocks.lock_pair(pair, arrow.utcnow().shift(minutes=4).datetime, side='long') + assert not PairLocks.is_pair_locked(pair) + assert PairLocks.is_pair_locked(pair, side='long') + assert not PairLocks.is_pair_locked(pair, side='short') + + pair = 'BNB/USDT' + PairLocks.lock_pair(pair, arrow.utcnow().shift(minutes=4).datetime, side='short') + assert not PairLocks.is_pair_locked(pair) + assert not PairLocks.is_pair_locked(pair, side='long') + assert PairLocks.is_pair_locked(pair, side='short') # XRP/BTC should not be locked now pair = 'XRP/BTC' diff --git a/tests/plugins/test_protections.py b/tests/plugins/test_protections.py index 69c42c93d..172e1f077 100644 --- a/tests/plugins/test_protections.py +++ b/tests/plugins/test_protections.py @@ -11,9 +11,10 @@ from tests.conftest import get_patched_freqtradebot, log_has_re def generate_mock_trade(pair: str, fee: float, is_open: bool, - sell_reason: str = ExitType.SELL_SIGNAL, + exit_reason: str = ExitType.EXIT_SIGNAL, min_ago_open: int = None, min_ago_close: int = None, - profit_rate: float = 0.9 + profit_rate: float = 0.9, + is_short: bool = False, ): open_rate = random.random() @@ -28,11 +29,12 @@ def generate_mock_trade(pair: str, fee: float, is_open: bool, is_open=is_open, amount=0.01 / open_rate, exchange='binance', + is_short=is_short, ) trade.recalc_open_trade_value() if not is_open: - trade.close(open_rate * profit_rate) - trade.sell_reason = sell_reason + trade.close(open_rate * (2 - profit_rate if is_short else profit_rate)) + trade.exit_reason = exit_reason return trade @@ -45,9 +47,9 @@ def test_protectionmanager(mocker, default_conf): for handler in freqtrade.protections._protection_handlers: assert handler.name in constants.AVAILABLE_PROTECTIONS if not handler.has_global_stop: - assert handler.global_stop(datetime.utcnow()) == (False, None, None) + assert handler.global_stop(datetime.utcnow(), '*') is None if not handler.has_local_stop: - assert handler.stop_per_pair('XRP/BTC', datetime.utcnow()) == (False, None, None) + assert handler.stop_per_pair('XRP/BTC', datetime.utcnow(), '*') is None @pytest.mark.parametrize('timeframe,expected,protconf', [ @@ -68,7 +70,7 @@ def test_protectionmanager(mocker, default_conf): ('1h', [60, 540], [{"method": "StoplossGuard", "lookback_period_candles": 1, "stop_duration_candles": 9}]), ]) -def test_protections_init(mocker, default_conf, timeframe, expected, protconf): +def test_protections_init(default_conf, timeframe, expected, protconf): default_conf['timeframe'] = timeframe man = ProtectionManager(default_conf, protconf) assert len(man._protection_handlers) == len(protconf) @@ -76,8 +78,10 @@ def test_protections_init(mocker, default_conf, timeframe, expected, protconf): assert man._protection_handlers[0]._stop_duration == expected[1] +@pytest.mark.parametrize('is_short', [False, True]) @pytest.mark.usefixtures("init_persistence") -def test_stoploss_guard(mocker, default_conf, fee, caplog): +def test_stoploss_guard(mocker, default_conf, fee, caplog, is_short): + # Active for both sides (long and short) default_conf['protections'] = [{ "method": "StoplossGuard", "lookback_period": 60, @@ -91,8 +95,8 @@ def test_stoploss_guard(mocker, default_conf, fee, caplog): caplog.clear() Trade.query.session.add(generate_mock_trade( - 'XRP/BTC', fee.return_value, False, sell_reason=ExitType.STOP_LOSS.value, - min_ago_open=200, min_ago_close=30, + 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, + min_ago_open=200, min_ago_close=30, is_short=is_short, )) assert not freqtrade.protections.global_stop() @@ -100,13 +104,13 @@ def test_stoploss_guard(mocker, default_conf, fee, caplog): caplog.clear() # This trade does not count, as it's closed too long ago Trade.query.session.add(generate_mock_trade( - 'BCH/BTC', fee.return_value, False, sell_reason=ExitType.STOP_LOSS.value, - min_ago_open=250, min_ago_close=100, + 'BCH/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, + min_ago_open=250, min_ago_close=100, is_short=is_short, )) Trade.query.session.add(generate_mock_trade( - 'ETH/BTC', fee.return_value, False, sell_reason=ExitType.STOP_LOSS.value, - min_ago_open=240, min_ago_close=30, + 'ETH/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, + min_ago_open=240, min_ago_close=30, is_short=is_short, )) # 3 Trades closed - but the 2nd has been closed too long ago. assert not freqtrade.protections.global_stop() @@ -114,8 +118,8 @@ def test_stoploss_guard(mocker, default_conf, fee, caplog): caplog.clear() Trade.query.session.add(generate_mock_trade( - 'LTC/BTC', fee.return_value, False, sell_reason=ExitType.STOP_LOSS.value, - min_ago_open=180, min_ago_close=30, + 'LTC/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, + min_ago_open=180, min_ago_close=30, is_short=is_short, )) assert freqtrade.protections.global_stop() @@ -130,15 +134,19 @@ def test_stoploss_guard(mocker, default_conf, fee, caplog): @pytest.mark.parametrize('only_per_pair', [False, True]) +@pytest.mark.parametrize('only_per_side', [False, True]) @pytest.mark.usefixtures("init_persistence") -def test_stoploss_guard_perpair(mocker, default_conf, fee, caplog, only_per_pair): +def test_stoploss_guard_perpair(mocker, default_conf, fee, caplog, only_per_pair, only_per_side): default_conf['protections'] = [{ "method": "StoplossGuard", "lookback_period": 60, "trade_limit": 2, "stop_duration": 60, - "only_per_pair": only_per_pair + "only_per_pair": only_per_pair, + "only_per_side": only_per_side, }] + check_side = 'long' if only_per_side else '*' + is_short = False freqtrade = get_patched_freqtradebot(mocker, default_conf) message = r"Trading stopped due to .*" pair = 'XRP/BTC' @@ -148,8 +156,8 @@ def test_stoploss_guard_perpair(mocker, default_conf, fee, caplog, only_per_pair caplog.clear() Trade.query.session.add(generate_mock_trade( - pair, fee.return_value, False, sell_reason=ExitType.STOP_LOSS.value, - min_ago_open=200, min_ago_close=30, profit_rate=0.9, + pair, fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, + min_ago_open=200, min_ago_close=30, profit_rate=0.9, is_short=is_short )) assert not freqtrade.protections.stop_per_pair(pair) @@ -158,13 +166,13 @@ def test_stoploss_guard_perpair(mocker, default_conf, fee, caplog, only_per_pair caplog.clear() # This trade does not count, as it's closed too long ago Trade.query.session.add(generate_mock_trade( - pair, fee.return_value, False, sell_reason=ExitType.STOP_LOSS.value, - min_ago_open=250, min_ago_close=100, profit_rate=0.9, + pair, fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, + min_ago_open=250, min_ago_close=100, profit_rate=0.9, is_short=is_short )) # Trade does not count for per pair stop as it's the wrong pair. Trade.query.session.add(generate_mock_trade( - 'ETH/BTC', fee.return_value, False, sell_reason=ExitType.STOP_LOSS.value, - min_ago_open=240, min_ago_close=30, profit_rate=0.9, + 'ETH/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, + min_ago_open=240, min_ago_close=30, profit_rate=0.9, is_short=is_short )) # 3 Trades closed - but the 2nd has been closed too long ago. assert not freqtrade.protections.stop_per_pair(pair) @@ -176,16 +184,34 @@ def test_stoploss_guard_perpair(mocker, default_conf, fee, caplog, only_per_pair caplog.clear() + # Trade does not count potentially, as it's in the wrong direction + Trade.query.session.add(generate_mock_trade( + pair, fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, + min_ago_open=150, min_ago_close=25, profit_rate=0.9, is_short=not is_short + )) + freqtrade.protections.stop_per_pair(pair) + assert freqtrade.protections.global_stop() != only_per_pair + assert PairLocks.is_pair_locked(pair, side=check_side) != (only_per_side and only_per_pair) + assert PairLocks.is_global_lock(side=check_side) != only_per_pair + if only_per_side: + assert not PairLocks.is_pair_locked(pair, side='*') + assert not PairLocks.is_global_lock(side='*') + + caplog.clear() + # 2nd Trade that counts with correct pair Trade.query.session.add(generate_mock_trade( - pair, fee.return_value, False, sell_reason=ExitType.STOP_LOSS.value, - min_ago_open=180, min_ago_close=30, profit_rate=0.9, + pair, fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, + min_ago_open=180, min_ago_close=30, profit_rate=0.9, is_short=is_short )) freqtrade.protections.stop_per_pair(pair) assert freqtrade.protections.global_stop() != only_per_pair - assert PairLocks.is_pair_locked(pair) - assert PairLocks.is_global_lock() != only_per_pair + assert PairLocks.is_pair_locked(pair, side=check_side) + assert PairLocks.is_global_lock(side=check_side) != only_per_pair + if only_per_side: + assert not PairLocks.is_pair_locked(pair, side='*') + assert not PairLocks.is_global_lock(side='*') @pytest.mark.usefixtures("init_persistence") @@ -203,7 +229,7 @@ def test_CooldownPeriod(mocker, default_conf, fee, caplog): caplog.clear() Trade.query.session.add(generate_mock_trade( - 'XRP/BTC', fee.return_value, False, sell_reason=ExitType.STOP_LOSS.value, + 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=200, min_ago_close=30, )) @@ -213,7 +239,7 @@ def test_CooldownPeriod(mocker, default_conf, fee, caplog): assert not PairLocks.is_global_lock() Trade.query.session.add(generate_mock_trade( - 'ETH/BTC', fee.return_value, False, sell_reason=ExitType.ROI.value, + 'ETH/BTC', fee.return_value, False, exit_reason=ExitType.ROI.value, min_ago_open=205, min_ago_close=35, )) @@ -224,14 +250,16 @@ def test_CooldownPeriod(mocker, default_conf, fee, caplog): assert not PairLocks.is_global_lock() +@pytest.mark.parametrize('only_per_side', [False, True]) @pytest.mark.usefixtures("init_persistence") -def test_LowProfitPairs(mocker, default_conf, fee, caplog): +def test_LowProfitPairs(mocker, default_conf, fee, caplog, only_per_side): default_conf['protections'] = [{ "method": "LowProfitPairs", "lookback_period": 400, "stop_duration": 60, "trade_limit": 2, "required_profit": 0.0, + "only_per_side": only_per_side, }] freqtrade = get_patched_freqtradebot(mocker, default_conf) message = r"Trading stopped due to .*" @@ -242,7 +270,7 @@ def test_LowProfitPairs(mocker, default_conf, fee, caplog): caplog.clear() Trade.query.session.add(generate_mock_trade( - 'XRP/BTC', fee.return_value, False, sell_reason=ExitType.STOP_LOSS.value, + 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=800, min_ago_close=450, profit_rate=0.9, )) @@ -253,7 +281,7 @@ def test_LowProfitPairs(mocker, default_conf, fee, caplog): assert not PairLocks.is_global_lock() Trade.query.session.add(generate_mock_trade( - 'XRP/BTC', fee.return_value, False, sell_reason=ExitType.STOP_LOSS.value, + 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=200, min_ago_close=120, profit_rate=0.9, )) @@ -265,21 +293,23 @@ def test_LowProfitPairs(mocker, default_conf, fee, caplog): # Add positive trade Trade.query.session.add(generate_mock_trade( - 'XRP/BTC', fee.return_value, False, sell_reason=ExitType.ROI.value, - min_ago_open=20, min_ago_close=10, profit_rate=1.15, + 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.ROI.value, + min_ago_open=20, min_ago_close=10, profit_rate=1.15, is_short=True )) - assert not freqtrade.protections.stop_per_pair('XRP/BTC') - assert not PairLocks.is_pair_locked('XRP/BTC') + assert freqtrade.protections.stop_per_pair('XRP/BTC') != only_per_side + assert not PairLocks.is_pair_locked('XRP/BTC', side='*') + assert PairLocks.is_pair_locked('XRP/BTC', side='long') == only_per_side Trade.query.session.add(generate_mock_trade( - 'XRP/BTC', fee.return_value, False, sell_reason=ExitType.STOP_LOSS.value, + 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=110, min_ago_close=20, profit_rate=0.8, )) # Locks due to 2nd trade - assert not freqtrade.protections.global_stop() - assert freqtrade.protections.stop_per_pair('XRP/BTC') - assert PairLocks.is_pair_locked('XRP/BTC') + assert freqtrade.protections.global_stop() != only_per_side + assert freqtrade.protections.stop_per_pair('XRP/BTC') != only_per_side + assert PairLocks.is_pair_locked('XRP/BTC', side='long') + assert PairLocks.is_pair_locked('XRP/BTC', side='*') != only_per_side assert not PairLocks.is_global_lock() @@ -300,15 +330,15 @@ def test_MaxDrawdown(mocker, default_conf, fee, caplog): caplog.clear() Trade.query.session.add(generate_mock_trade( - 'XRP/BTC', fee.return_value, False, sell_reason=ExitType.STOP_LOSS.value, + 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=1000, min_ago_close=900, profit_rate=1.1, )) Trade.query.session.add(generate_mock_trade( - 'ETH/BTC', fee.return_value, False, sell_reason=ExitType.STOP_LOSS.value, + 'ETH/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=1000, min_ago_close=900, profit_rate=1.1, )) Trade.query.session.add(generate_mock_trade( - 'NEO/BTC', fee.return_value, False, sell_reason=ExitType.STOP_LOSS.value, + 'NEO/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=1000, min_ago_close=900, profit_rate=1.1, )) # No losing trade yet ... so max_drawdown will raise exception @@ -316,7 +346,7 @@ def test_MaxDrawdown(mocker, default_conf, fee, caplog): assert not freqtrade.protections.stop_per_pair('XRP/BTC') Trade.query.session.add(generate_mock_trade( - 'XRP/BTC', fee.return_value, False, sell_reason=ExitType.STOP_LOSS.value, + 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=500, min_ago_close=400, profit_rate=0.9, )) # Not locked with one trade @@ -326,7 +356,7 @@ def test_MaxDrawdown(mocker, default_conf, fee, caplog): assert not PairLocks.is_global_lock() Trade.query.session.add(generate_mock_trade( - 'XRP/BTC', fee.return_value, False, sell_reason=ExitType.STOP_LOSS.value, + 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.STOP_LOSS.value, min_ago_open=1200, min_ago_close=1100, profit_rate=0.5, )) @@ -339,7 +369,7 @@ def test_MaxDrawdown(mocker, default_conf, fee, caplog): # Winning trade ... (should not lock, does not change drawdown!) Trade.query.session.add(generate_mock_trade( - 'XRP/BTC', fee.return_value, False, sell_reason=ExitType.ROI.value, + 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.ROI.value, min_ago_open=320, min_ago_close=410, profit_rate=1.5, )) assert not freqtrade.protections.global_stop() @@ -349,7 +379,7 @@ def test_MaxDrawdown(mocker, default_conf, fee, caplog): # Add additional negative trade, causing a loss of > 15% Trade.query.session.add(generate_mock_trade( - 'XRP/BTC', fee.return_value, False, sell_reason=ExitType.ROI.value, + 'XRP/BTC', fee.return_value, False, exit_reason=ExitType.ROI.value, min_ago_open=20, min_ago_close=10, profit_rate=0.8, )) assert not freqtrade.protections.stop_per_pair('XRP/BTC') diff --git a/tests/rpc/test_fiat_convert.py b/tests/rpc/test_fiat_convert.py index c87cea259..0dfa20185 100644 --- a/tests/rpc/test_fiat_convert.py +++ b/tests/rpc/test_fiat_convert.py @@ -137,7 +137,7 @@ def test_fiat_too_many_requests_response(mocker, caplog): assert len(fiat_convert._coinlistings) == 0 assert fiat_convert._backoff > datetime.datetime.now().timestamp() assert log_has( - 'Too many requests for Coingecko API, backing off and trying again later.', + 'Too many requests for CoinGecko API, backing off and trying again later.', caplog ) @@ -156,7 +156,7 @@ def test_fiat_multiple_coins(mocker, caplog): assert fiat_convert._get_gekko_id('hnt') is None assert fiat_convert._get_gekko_id('eth') == 'ethereum' - assert log_has('Found multiple mappings in goingekko for hnt.', caplog) + assert log_has('Found multiple mappings in CoinGecko for hnt.', caplog) def test_fiat_invalid_response(mocker, caplog): diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py index 580ee5c84..95645c8ba 100644 --- a/tests/rpc/test_rpc.py +++ b/tests/rpc/test_rpc.py @@ -52,7 +52,8 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None: assert results[0] == { 'trade_id': 1, 'pair': 'ETH/BTC', - 'base_currency': 'BTC', + 'base_currency': 'ETH', + 'quote_currency': 'BTC', 'open_date': ANY, 'open_timestamp': ANY, 'is_open': ANY, @@ -66,7 +67,8 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None: 'open_trade_value': 0.0010025, 'close_rate_requested': ANY, 'sell_reason': ANY, - 'sell_order_status': ANY, + 'exit_reason': ANY, + 'exit_order_status': ANY, 'min_rate': ANY, 'max_rate': ANY, 'strategy': ANY, @@ -134,7 +136,8 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None: assert results[0] == { 'trade_id': 1, 'pair': 'ETH/BTC', - 'base_currency': 'BTC', + 'base_currency': 'ETH', + 'quote_currency': 'BTC', 'open_date': ANY, 'open_timestamp': ANY, 'is_open': ANY, @@ -148,7 +151,8 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None: 'open_trade_value': ANY, 'close_rate_requested': ANY, 'sell_reason': ANY, - 'sell_order_status': ANY, + 'exit_reason': ANY, + 'exit_order_status': ANY, 'min_rate': ANY, 'max_rate': ANY, 'strategy': ANY, @@ -229,9 +233,20 @@ def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None: freqtradebot.state = State.RUNNING with pytest.raises(RPCException, match=r'.*no active trade*'): rpc._rpc_status_table(default_conf['stake_currency'], 'USD') - + mocker.patch('freqtrade.exchange.Exchange._is_dry_limit_order_filled', return_value=False) freqtradebot.enter_positions() + result, headers, fiat_profit_sum = rpc._rpc_status_table(default_conf['stake_currency'], 'USD') + assert "Since" in headers + assert "Pair" in headers + assert 'instantly' == result[0][2] + assert 'ETH/BTC' in result[0][1] + assert '0.00' == result[0][3] + assert isnan(fiat_profit_sum) + + mocker.patch('freqtrade.exchange.Exchange._is_dry_limit_order_filled', return_value=True) + freqtradebot.process() + result, headers, fiat_profit_sum = rpc._rpc_status_table(default_conf['stake_currency'], 'USD') assert "Since" in headers assert "Pair" in headers @@ -239,8 +254,8 @@ def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None: assert 'ETH/BTC' in result[0][1] assert '-0.41%' == result[0][3] assert isnan(fiat_profit_sum) - # Test with fiatconvert + # Test with fiatconvert rpc._fiat_converter = CryptoToFiatConverter() result, headers, fiat_profit_sum = rpc._rpc_status_table(default_conf['stake_currency'], 'USD') assert "Since" in headers @@ -769,7 +784,7 @@ def test_rpc_stopbuy(mocker, default_conf) -> None: assert freqtradebot.config['max_open_trades'] == 0 -def test_rpc_forceexit(default_conf, ticker, fee, mocker) -> None: +def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None: mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock()) cancel_order_mock = MagicMock() @@ -796,29 +811,29 @@ def test_rpc_forceexit(default_conf, ticker, fee, mocker) -> None: freqtradebot.state = State.STOPPED with pytest.raises(RPCException, match=r'.*trader is not running*'): - rpc._rpc_forceexit(None) + rpc._rpc_force_exit(None) freqtradebot.state = State.RUNNING with pytest.raises(RPCException, match=r'.*invalid argument*'): - rpc._rpc_forceexit(None) + rpc._rpc_force_exit(None) - msg = rpc._rpc_forceexit('all') + msg = rpc._rpc_force_exit('all') assert msg == {'result': 'Created sell orders for all open trades.'} freqtradebot.enter_positions() - msg = rpc._rpc_forceexit('all') + msg = rpc._rpc_force_exit('all') assert msg == {'result': 'Created sell orders for all open trades.'} freqtradebot.enter_positions() - msg = rpc._rpc_forceexit('2') + msg = rpc._rpc_force_exit('2') assert msg == {'result': 'Created sell order for trade 2.'} freqtradebot.state = State.STOPPED with pytest.raises(RPCException, match=r'.*trader is not running*'): - rpc._rpc_forceexit(None) + rpc._rpc_force_exit(None) with pytest.raises(RPCException, match=r'.*trader is not running*'): - rpc._rpc_forceexit('all') + rpc._rpc_force_exit('all') freqtradebot.state = State.RUNNING assert cancel_order_mock.call_count == 0 @@ -847,7 +862,7 @@ def test_rpc_forceexit(default_conf, ticker, fee, mocker) -> None: ) # check that the trade is called, which is done by ensuring exchange.cancel_order is called # and trade amount is updated - rpc._rpc_forceexit('3') + rpc._rpc_force_exit('3') assert cancel_order_mock.call_count == 1 assert trade.amount == filled_amount @@ -875,7 +890,7 @@ def test_rpc_forceexit(default_conf, ticker, fee, mocker) -> None: } ) # check that the trade is called, which is done by ensuring exchange.cancel_order is called - msg = rpc._rpc_forceexit('4') + msg = rpc._rpc_force_exit('4') assert msg == {'result': 'Created sell order for trade 4.'} assert cancel_order_mock.call_count == 2 assert trade.amount == amount @@ -892,7 +907,7 @@ def test_rpc_forceexit(default_conf, ticker, fee, mocker) -> None: 'filled': 0.0 } ) - msg = rpc._rpc_forceexit('3') + msg = rpc._rpc_force_exit('3') assert msg == {'result': 'Created sell order for trade 3.'} # status quo, no exchange calls assert cancel_order_mock.call_count == 3 @@ -1008,7 +1023,7 @@ def test_enter_tag_performance_handle_2(mocker, default_conf, markets, fee): assert prec_satoshi(res[0]['profit_pct'], 0.5) -def test_sell_reason_performance_handle(default_conf, ticker, limit_buy_order, fee, +def test_exit_reason_performance_handle(default_conf, ticker, limit_buy_order, fee, limit_sell_order, mocker) -> None: mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock()) mocker.patch.multiple( @@ -1037,23 +1052,23 @@ def test_sell_reason_performance_handle(default_conf, ticker, limit_buy_order, f trade.close_date = datetime.utcnow() trade.is_open = False - res = rpc._rpc_sell_reason_performance(None) + res = rpc._rpc_exit_reason_performance(None) assert len(res) == 1 - assert res[0]['sell_reason'] == 'Other' + assert res[0]['exit_reason'] == 'Other' assert res[0]['count'] == 1 assert prec_satoshi(res[0]['profit_pct'], 6.2) - trade.sell_reason = "TEST1" - res = rpc._rpc_sell_reason_performance(None) + trade.exit_reason = "TEST1" + res = rpc._rpc_exit_reason_performance(None) assert len(res) == 1 - assert res[0]['sell_reason'] == 'TEST1' + assert res[0]['exit_reason'] == 'TEST1' assert res[0]['count'] == 1 assert prec_satoshi(res[0]['profit_pct'], 6.2) -def test_sell_reason_performance_handle_2(mocker, default_conf, markets, fee): +def test_exit_reason_performance_handle_2(mocker, default_conf, markets, fee): mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock()) mocker.patch.multiple( 'freqtrade.exchange.Exchange', @@ -1064,21 +1079,21 @@ def test_sell_reason_performance_handle_2(mocker, default_conf, markets, fee): create_mock_trades(fee) rpc = RPC(freqtradebot) - res = rpc._rpc_sell_reason_performance(None) + res = rpc._rpc_exit_reason_performance(None) assert len(res) == 2 - assert res[0]['sell_reason'] == 'sell_signal' + assert res[0]['exit_reason'] == 'sell_signal' assert res[0]['count'] == 1 assert prec_satoshi(res[0]['profit_pct'], 0.5) - assert res[1]['sell_reason'] == 'roi' + assert res[1]['exit_reason'] == 'roi' assert res[1]['count'] == 1 assert prec_satoshi(res[1]['profit_pct'], 1.0) # Test for a specific pair - res = rpc._rpc_sell_reason_performance('ETC/BTC') + res = rpc._rpc_exit_reason_performance('ETC/BTC') assert len(res) == 1 assert res[0]['count'] == 1 - assert res[0]['sell_reason'] == 'sell_signal' + assert res[0]['exit_reason'] == 'sell_signal' assert prec_satoshi(res[0]['profit_pct'], 0.5) @@ -1119,7 +1134,7 @@ def test_mix_tag_performance_handle(default_conf, ticker, limit_buy_order, fee, assert prec_satoshi(res[0]['profit_pct'], 6.2) trade.enter_tag = "TESTBUY" - trade.sell_reason = "TESTSELL" + trade.exit_reason = "TESTSELL" res = rpc._rpc_mix_tag_performance(None) assert len(res) == 1 @@ -1180,8 +1195,8 @@ def test_rpc_count(mocker, default_conf, ticker, fee) -> None: assert counts["current"] == 1 -def test_rpc_forceentry(mocker, default_conf, ticker, fee, limit_buy_order_open) -> None: - default_conf['forcebuy_enable'] = True +def test_rpc_force_entry(mocker, default_conf, ticker, fee, limit_buy_order_open) -> None: + default_conf['force_entry_enable'] = True mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock()) buy_mm = MagicMock(return_value=limit_buy_order_open) mocker.patch.multiple( @@ -1219,7 +1234,7 @@ def test_rpc_forceentry(mocker, default_conf, ticker, fee, limit_buy_order_open) pair = 'LTC/BTC' trade = rpc._rpc_force_entry(pair, 0.0001, order_type='limit', stake_amount=0.05) assert trade.stake_amount == 0.05 - assert trade.buy_tag == 'forceentry' + assert trade.buy_tag == 'force_entry' # Test not buying pair = 'XRP/BTC' @@ -1228,12 +1243,12 @@ def test_rpc_forceentry(mocker, default_conf, ticker, fee, limit_buy_order_open) patch_get_signal(freqtradebot) rpc = RPC(freqtradebot) pair = 'TKN/BTC' - trade = rpc._rpc_force_entry(pair, None) - assert trade is None + with pytest.raises(RPCException, match=r"Failed to enter position for TKN/BTC."): + trade = rpc._rpc_force_entry(pair, None) -def test_rpc_forceentry_stopped(mocker, default_conf) -> None: - default_conf['forcebuy_enable'] = True +def test_rpc_force_entry_stopped(mocker, default_conf) -> None: + default_conf['force_entry_enable'] = True default_conf['initial_state'] = 'stopped' mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock()) @@ -1245,19 +1260,19 @@ def test_rpc_forceentry_stopped(mocker, default_conf) -> None: rpc._rpc_force_entry(pair, None) -def test_rpc_forceentry_disabled(mocker, default_conf) -> None: +def test_rpc_force_entry_disabled(mocker, default_conf) -> None: mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock()) freqtradebot = get_patched_freqtradebot(mocker, default_conf) patch_get_signal(freqtradebot) rpc = RPC(freqtradebot) pair = 'ETH/BTC' - with pytest.raises(RPCException, match=r'Forceentry not enabled.'): + with pytest.raises(RPCException, match=r'Force_entry not enabled.'): rpc._rpc_force_entry(pair, None) -def test_rpc_forceentry_wrong_mode(mocker, default_conf) -> None: - default_conf['forcebuy_enable'] = True +def test_rpc_force_entry_wrong_mode(mocker, default_conf) -> None: + default_conf['force_entry_enable'] = True mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock()) freqtradebot = get_patched_freqtradebot(mocker, default_conf) diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index 167f644c6..ac2f1c3ec 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__ @@ -822,14 +821,14 @@ def test_api_stats(botclient, mocker, ticker, fee, markets, is_short): rc = client_get(client, f"{BASE_URI}/stats") assert_response(rc, 200) assert 'durations' in rc.json() - assert 'sell_reasons' in rc.json() + assert 'exit_reasons' in rc.json() create_mock_trades(fee, is_short=is_short) rc = client_get(client, f"{BASE_URI}/stats") assert_response(rc, 200) assert 'durations' in rc.json() - assert 'sell_reasons' in rc.json() + assert 'exit_reasons' in rc.json() assert 'wins' in rc.json()['durations'] assert 'losses' in rc.json()['durations'] @@ -931,6 +930,8 @@ def test_api_status(botclient, mocker, ticker, fee, markets, is_short, 'open_order': None, 'open_rate': 0.123, 'pair': 'ETH/BTC', + 'base_currency': 'ETH', + 'quote_currency': 'BTC', 'stake_amount': 0.001, 'stop_loss_abs': ANY, 'stop_loss_pct': ANY, @@ -962,7 +963,8 @@ def test_api_status(botclient, mocker, ticker, fee, markets, is_short, 'open_rate_requested': ANY, 'open_trade_value': open_trade_value, 'sell_reason': None, - 'sell_order_status': None, + 'exit_reason': None, + 'exit_order_status': None, 'strategy': CURRENT_TEST_STRATEGY, 'buy_tag': None, 'enter_tag': None, @@ -982,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): @@ -1076,16 +1078,16 @@ def test_api_whitelist(botclient): 'forcebuy', 'forceenter', ]) -def test_api_forceentry(botclient, mocker, fee, endpoint): +def test_api_force_entry(botclient, mocker, fee, endpoint): ftbot, client = botclient rc = client_post(client, f"{BASE_URI}/{endpoint}", data='{"pair": "ETH/BTC"}') assert_response(rc, 502) - assert rc.json() == {"error": f"Error querying /api/v1/{endpoint}: Forceentry not enabled."} + assert rc.json() == {"error": f"Error querying /api/v1/{endpoint}: Force_entry not enabled."} # enable forcebuy - ftbot.config['forcebuy_enable'] = True + ftbot.config['force_entry_enable'] = True fbuy_mock = MagicMock(return_value=None) mocker.patch("freqtrade.rpc.RPC._rpc_force_entry", fbuy_mock) @@ -1096,7 +1098,7 @@ def test_api_forceentry(botclient, mocker, fee, endpoint): # Test creating trade fbuy_mock = MagicMock(return_value=Trade( - pair='ETH/ETH', + pair='ETH/BTC', amount=1, amount_requested=1, exchange='binance', @@ -1129,7 +1131,9 @@ def test_api_forceentry(botclient, mocker, fee, endpoint): 'open_date': ANY, 'open_timestamp': ANY, 'open_rate': 0.245441, - 'pair': 'ETH/ETH', + 'pair': 'ETH/BTC', + 'base_currency': 'ETH', + 'quote_currency': 'BTC', 'stake_amount': 1, 'stop_loss_abs': None, 'stop_loss_pct': None, @@ -1162,7 +1166,8 @@ def test_api_forceentry(botclient, mocker, fee, endpoint): 'open_rate_requested': None, 'open_trade_value': 0.24605460, 'sell_reason': None, - 'sell_order_status': None, + 'exit_reason': None, + 'exit_order_status': None, 'strategy': CURRENT_TEST_STRATEGY, 'buy_tag': None, 'enter_tag': None, @@ -1176,7 +1181,7 @@ def test_api_forceentry(botclient, mocker, fee, endpoint): } -def test_api_forcesell(botclient, mocker, ticker, fee, markets): +def test_api_forceexit(botclient, mocker, ticker, fee, markets): ftbot, client = botclient mocker.patch.multiple( 'freqtrade.exchange.Exchange', @@ -1188,15 +1193,15 @@ def test_api_forcesell(botclient, mocker, ticker, fee, markets): ) patch_get_signal(ftbot) - rc = client_post(client, f"{BASE_URI}/forcesell", + rc = client_post(client, f"{BASE_URI}/forceexit", data='{"tradeid": "1"}') assert_response(rc, 502) - assert rc.json() == {"error": "Error querying /api/v1/forcesell: invalid argument"} + assert rc.json() == {"error": "Error querying /api/v1/forceexit: invalid argument"} Trade.query.session.rollback() ftbot.enter_positions() - rc = client_post(client, f"{BASE_URI}/forcesell", + rc = client_post(client, f"{BASE_URI}/forceexit", data='{"tradeid": "1"}') assert_response(rc) assert rc.json() == {'result': 'Created sell order for trade 1.'} @@ -1383,7 +1388,6 @@ def test_api_strategies(botclient): 'StrategyTestV2', 'StrategyTestV3', 'StrategyTestV3Futures', - 'TestStrategyLegacyV1', ]} @@ -1479,7 +1483,7 @@ def test_api_backtesting(botclient, mocker, fee, caplog, tmpdir): assert not result['running'] assert result['status_msg'] == 'Backtest reset' ftbot.config['export'] = 'trades' - ftbot.config['backtest_cache'] = 'none' + ftbot.config['backtest_cache'] = 'day' ftbot.config['user_data_dir'] = Path(tmpdir) ftbot.config['exportfilename'] = Path(tmpdir) / "backtest_results" ftbot.config['exportfilename'].mkdir() @@ -1552,19 +1556,19 @@ def test_api_backtesting(botclient, mocker, fee, caplog, tmpdir): ApiServer._bgtask_running = False - mocker.patch('freqtrade.optimize.backtesting.Backtesting.backtest_one_strategy', - side_effect=DependencyException()) - rc = client_post(client, f"{BASE_URI}/backtest", data=json.dumps(data)) - assert log_has("Backtesting caused an error: ", caplog) - - ftbot.config['backtest_cache'] = 'day' - # Rerun backtest (should get previous result) rc = client_post(client, f"{BASE_URI}/backtest", data=json.dumps(data)) assert_response(rc) result = rc.json() assert log_has_re('Reusing result of previous backtest.*', caplog) + data['stake_amount'] = 101 + + mocker.patch('freqtrade.optimize.backtesting.Backtesting.backtest_one_strategy', + side_effect=DependencyException()) + rc = client_post(client, f"{BASE_URI}/backtest", data=json.dumps(data)) + assert log_has("Backtesting caused an error: ", caplog) + # Delete backtesting to avoid leakage since the backtest-object may stick around. rc = client_delete(client, f"{BASE_URI}/backtest") assert_response(rc) @@ -1575,6 +1579,38 @@ 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) == 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) + result2 = rc.json() + assert result2 + assert result2['status'] == 'ended' + assert not result2['running'] + assert result2['progress'] == 1 + # 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): ftbot, client = botclient diff --git a/tests/rpc/test_rpc_telegram.py b/tests/rpc/test_rpc_telegram.py index db93a6ec4..2bc4fc5c3 100644 --- a/tests/rpc/test_rpc_telegram.py +++ b/tests/rpc/test_rpc_telegram.py @@ -95,9 +95,9 @@ def test_telegram_init(default_conf, mocker, caplog) -> None: message_str = ("rpc.telegram is listening for following commands: [['status'], ['profit'], " "['balance'], ['start'], ['stop'], " - "['forcesell', 'forceexit'], ['forcebuy', 'forcelong'], ['forceshort'], " + "['forcesell', 'forceexit', 'fx'], ['forcebuy', 'forcelong'], ['forceshort'], " "['trades'], ['delete'], ['performance'], " - "['buys', 'entries'], ['sells'], ['mix_tags'], " + "['buys', 'entries'], ['sells', 'exits'], ['mix_tags'], " "['stats'], ['daily'], ['weekly'], ['monthly'], " "['count'], ['locks'], ['unlock', 'delete_locks'], " "['reload_config', 'reload_conf'], ['show_config', 'show_conf'], " @@ -184,7 +184,8 @@ def test_telegram_status(default_conf, update, mocker) -> None: _rpc_trade_status=MagicMock(return_value=[{ 'trade_id': 1, 'pair': 'ETH/BTC', - 'base_currency': 'BTC', + 'base_currency': 'ETH', + 'quote_currency': 'BTC', 'open_date': arrow.utcnow(), 'close_date': None, 'open_rate': 1.099e-05, @@ -199,7 +200,7 @@ def test_telegram_status(default_conf, update, mocker) -> None: 'profit_ratio': -0.0059, 'initial_stop_loss_abs': 1.098e-05, 'stop_loss_abs': 1.099e-05, - 'sell_order_status': None, + 'exit_order_status': None, 'initial_stop_loss_ratio': -0.0005, 'stoploss_current_dist': 1e-08, 'stoploss_current_dist_ratio': -0.0002, @@ -398,8 +399,8 @@ def test_status_table_handle(default_conf, update, ticker, fee, mocker) -> None: fields = re.sub('[ ]+', ' ', line[2].strip()).split(' ') assert int(fields[0]) == 1 - assert 'L' in fields[1] - assert 'ETH/BTC' in fields[2] + # assert 'L' in fields[1] + assert 'ETH/BTC' in fields[1] assert msg_mock.call_count == 1 @@ -837,7 +838,7 @@ def test_telegram_stats(default_conf, update, ticker, ticker_sell_up, fee, telegram._stats(update=update, context=MagicMock()) assert msg_mock.call_count == 1 - assert 'Sell Reason' in msg_mock.call_args_list[-1][0][0] + assert 'Exit Reason' in msg_mock.call_args_list[-1][0][0] assert 'ROI' in msg_mock.call_args_list[-1][0][0] assert 'Avg. Duration' in msg_mock.call_args_list[-1][0][0] msg_mock.reset_mock() @@ -1004,7 +1005,7 @@ def test_reload_config_handle(default_conf, update, mocker) -> None: assert 'Reloading config' in msg_mock.call_args_list[0][0][0] -def test_telegram_forcesell_handle(default_conf, update, ticker, fee, +def test_telegram_forceexit_handle(default_conf, update, ticker, fee, ticker_sell_up, mocker) -> None: mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0) msg_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg', MagicMock()) @@ -1032,15 +1033,15 @@ def test_telegram_forcesell_handle(default_conf, update, ticker, fee, # Increase the price and sell it mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', ticker_sell_up) - # /forcesell 1 + # /forceexit 1 context = MagicMock() context.args = ["1"] - telegram._forceexit(update=update, context=context) + telegram._force_exit(update=update, context=context) assert msg_mock.call_count == 4 last_msg = msg_mock.call_args_list[-2][0][0] assert { - 'type': RPCMessageType.SELL, + 'type': RPCMessageType.EXIT, 'trade_id': 1, 'exchange': 'Binance', 'pair': 'ETH/BTC', @@ -1059,15 +1060,16 @@ def test_telegram_forcesell_handle(default_conf, update, ticker, fee, 'fiat_currency': 'USD', 'buy_tag': ANY, 'enter_tag': ANY, - 'sell_reason': ExitType.FORCE_SELL.value, + 'sell_reason': ExitType.FORCE_EXIT.value, + 'exit_reason': ExitType.FORCE_EXIT.value, 'open_date': ANY, 'close_date': ANY, 'close_rate': ANY, } == last_msg -def test_telegram_forcesell_down_handle(default_conf, update, ticker, fee, - ticker_sell_down, mocker) -> None: +def test_telegram_force_exit_down_handle(default_conf, update, ticker, fee, + ticker_sell_down, mocker) -> None: mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._find_price', return_value=15000.0) msg_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg', MagicMock()) @@ -1099,16 +1101,16 @@ def test_telegram_forcesell_down_handle(default_conf, update, ticker, fee, trade = Trade.query.first() assert trade - # /forcesell 1 + # /forceexit 1 context = MagicMock() context.args = ["1"] - telegram._forceexit(update=update, context=context) + telegram._force_exit(update=update, context=context) assert msg_mock.call_count == 4 last_msg = msg_mock.call_args_list[-2][0][0] assert { - 'type': RPCMessageType.SELL, + 'type': RPCMessageType.EXIT, 'trade_id': 1, 'exchange': 'Binance', 'pair': 'ETH/BTC', @@ -1127,14 +1129,15 @@ def test_telegram_forcesell_down_handle(default_conf, update, ticker, fee, 'fiat_currency': 'USD', 'buy_tag': ANY, 'enter_tag': ANY, - 'sell_reason': ExitType.FORCE_SELL.value, + 'sell_reason': ExitType.FORCE_EXIT.value, + 'exit_reason': ExitType.FORCE_EXIT.value, 'open_date': ANY, 'close_date': ANY, 'close_rate': ANY, } == last_msg -def test_forcesell_all_handle(default_conf, update, ticker, fee, mocker) -> None: +def test_forceexit_all_handle(default_conf, update, ticker, fee, mocker) -> None: patch_exchange(mocker) mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._find_price', return_value=15000.0) @@ -1157,16 +1160,16 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, mocker) -> None freqtradebot.enter_positions() msg_mock.reset_mock() - # /forcesell all + # /forceexit all context = MagicMock() context.args = ["all"] - telegram._forceexit(update=update, context=context) + telegram._force_exit(update=update, context=context) # Called for each trade 2 times assert msg_mock.call_count == 8 msg = msg_mock.call_args_list[0][0][0] assert { - 'type': RPCMessageType.SELL, + 'type': RPCMessageType.EXIT, 'trade_id': 1, 'exchange': 'Binance', 'pair': 'ETH/BTC', @@ -1185,14 +1188,15 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, mocker) -> None 'fiat_currency': 'USD', 'buy_tag': ANY, 'enter_tag': ANY, - 'sell_reason': ExitType.FORCE_SELL.value, + 'sell_reason': ExitType.FORCE_EXIT.value, + 'exit_reason': ExitType.FORCE_EXIT.value, 'open_date': ANY, 'close_date': ANY, 'close_rate': ANY, } == msg -def test_forcesell_handle_invalid(default_conf, update, mocker) -> None: +def test_forceexit_handle_invalid(default_conf, update, mocker) -> None: mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._find_price', return_value=15000.0) @@ -1201,34 +1205,78 @@ def test_forcesell_handle_invalid(default_conf, update, mocker) -> None: # Trader is not running freqtradebot.state = State.STOPPED - # /forcesell 1 + # /forceexit 1 context = MagicMock() context.args = ["1"] - telegram._forceexit(update=update, context=context) + telegram._force_exit(update=update, context=context) assert msg_mock.call_count == 1 assert 'not running' in msg_mock.call_args_list[0][0][0] - # No argument - msg_mock.reset_mock() - freqtradebot.state = State.RUNNING - context = MagicMock() - context.args = [] - telegram._forceexit(update=update, context=context) - assert msg_mock.call_count == 1 - assert "You must specify a trade-id or 'all'." in msg_mock.call_args_list[0][0][0] - # Invalid argument msg_mock.reset_mock() freqtradebot.state = State.RUNNING - # /forcesell 123456 + # /forceexit 123456 context = MagicMock() context.args = ["123456"] - telegram._forceexit(update=update, context=context) + telegram._force_exit(update=update, context=context) assert msg_mock.call_count == 1 assert 'invalid argument' in msg_mock.call_args_list[0][0][0] -def test_forceenter_handle(default_conf, update, mocker) -> None: +def test_force_exit_no_pair(default_conf, update, ticker, fee, mocker) -> None: + default_conf['max_open_trades'] = 4 + mocker.patch.multiple( + 'freqtrade.exchange.Exchange', + fetch_ticker=ticker, + get_fee=fee, + _is_dry_limit_order_filled=MagicMock(return_value=True), + ) + femock = mocker.patch('freqtrade.rpc.rpc.RPC._rpc_force_exit') + telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) + + patch_get_signal(freqtradebot) + + # /forceexit + context = MagicMock() + context.args = [] + telegram._force_exit(update=update, context=context) + # No pair + assert msg_mock.call_args_list[0][1]['msg'] == 'No open trade found.' + + # Create some test data + freqtradebot.enter_positions() + msg_mock.reset_mock() + + # /forceexit + telegram._force_exit(update=update, context=context) + keyboard = msg_mock.call_args_list[0][1]['keyboard'] + # 4 pairs + cancel + assert reduce(lambda acc, x: acc + len(x), keyboard, 0) == 5 + assert keyboard[-1][0].text == "Cancel" + + assert keyboard[1][0].callback_data == 'force_exit__2 ' + update = MagicMock() + update.callback_query = MagicMock() + update.callback_query.data = keyboard[1][0].callback_data + telegram._force_exit_inline(update, None) + assert update.callback_query.answer.call_count == 1 + assert update.callback_query.edit_message_text.call_count == 1 + assert femock.call_count == 1 + assert femock.call_args_list[0][0][0] == '2' + + # Retry exiting - but cancel instead + update.callback_query.reset_mock() + telegram._force_exit(update=update, context=context) + # Use cancel button + update.callback_query.data = keyboard[-1][0].callback_data + telegram._force_exit_inline(update, None) + query = update.callback_query + assert query.answer.call_count == 1 + assert query.edit_message_text.call_count == 1 + assert query.edit_message_text.call_args_list[-1][1]['text'] == "Force exit canceled." + + +def test_force_enter_handle(default_conf, update, mocker) -> None: mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0) fbuy_mock = MagicMock(return_value=None) @@ -1240,7 +1288,7 @@ def test_forceenter_handle(default_conf, update, mocker) -> None: # /forcelong ETH/BTC context = MagicMock() context.args = ["ETH/BTC"] - telegram._forceenter(update=update, context=context, order_side=SignalDirection.LONG) + telegram._force_enter(update=update, context=context, order_side=SignalDirection.LONG) assert fbuy_mock.call_count == 1 assert fbuy_mock.call_args_list[0][0][0] == 'ETH/BTC' @@ -1253,7 +1301,7 @@ def test_forceenter_handle(default_conf, update, mocker) -> None: # /forcelong ETH/BTC 0.055 context = MagicMock() context.args = ["ETH/BTC", "0.055"] - telegram._forceenter(update=update, context=context, order_side=SignalDirection.LONG) + telegram._force_enter(update=update, context=context, order_side=SignalDirection.LONG) assert fbuy_mock.call_count == 1 assert fbuy_mock.call_args_list[0][0][0] == 'ETH/BTC' @@ -1261,20 +1309,20 @@ def test_forceenter_handle(default_conf, update, mocker) -> None: assert fbuy_mock.call_args_list[0][0][1] == 0.055 -def test_forceenter_handle_exception(default_conf, update, mocker) -> None: +def test_force_enter_handle_exception(default_conf, update, mocker) -> None: mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0) telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf) patch_get_signal(freqtradebot) update.message.text = '/forcebuy ETH/Nonepair' - telegram._forceenter(update=update, context=MagicMock(), order_side=SignalDirection.LONG) + telegram._force_enter(update=update, context=MagicMock(), order_side=SignalDirection.LONG) assert msg_mock.call_count == 1 - assert msg_mock.call_args_list[0][0][0] == 'Forceentry not enabled.' + assert msg_mock.call_args_list[0][0][0] == 'Force_entry not enabled.' -def test_forceenter_no_pair(default_conf, update, mocker) -> None: +def test_force_enter_no_pair(default_conf, update, mocker) -> None: mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0) fbuy_mock = MagicMock(return_value=None) @@ -1286,7 +1334,7 @@ def test_forceenter_no_pair(default_conf, update, mocker) -> None: context = MagicMock() context.args = [] - telegram._forceenter(update=update, context=context, order_side=SignalDirection.LONG) + telegram._force_enter(update=update, context=context, order_side=SignalDirection.LONG) assert fbuy_mock.call_count == 0 assert msg_mock.call_count == 1 @@ -1298,7 +1346,7 @@ def test_forceenter_no_pair(default_conf, update, mocker) -> None: update = MagicMock() update.callback_query = MagicMock() update.callback_query.data = 'XRP/USDT_||_long' - telegram._forceenter_inline(update, None) + telegram._force_enter_inline(update, None) assert fbuy_mock.call_count == 1 @@ -1334,8 +1382,8 @@ def test_telegram_performance_handle(default_conf, update, ticker, fee, assert 'ETH/BTC\t0.00006217 BTC (6.20%) (1)' in msg_mock.call_args_list[0][0][0] -def test_telegram_buy_tag_performance_handle(default_conf, update, ticker, fee, - limit_buy_order, limit_sell_order, mocker) -> None: +def test_telegram_entry_tag_performance_handle( + default_conf, update, ticker, fee, limit_buy_order, limit_sell_order, mocker) -> None: mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker, @@ -1363,7 +1411,7 @@ def test_telegram_buy_tag_performance_handle(default_conf, update, ticker, fee, context = MagicMock() telegram._enter_tag_performance(update=update, context=context) assert msg_mock.call_count == 1 - assert 'Buy Tag Performance' in msg_mock.call_args_list[0][0][0] + assert 'Entry Tag Performance' in msg_mock.call_args_list[0][0][0] assert 'TESTBUY\t0.00006217 BTC (6.20%) (1)' in msg_mock.call_args_list[0][0][0] context.args = [trade.pair] @@ -1379,7 +1427,7 @@ def test_telegram_buy_tag_performance_handle(default_conf, update, ticker, fee, assert "Error" in msg_mock.call_args_list[0][0][0] -def test_telegram_sell_reason_performance_handle(default_conf, update, ticker, fee, +def test_telegram_exit_reason_performance_handle(default_conf, update, ticker, fee, limit_buy_order, limit_sell_order, mocker) -> None: mocker.patch.multiple( 'freqtrade.exchange.Exchange', @@ -1393,7 +1441,7 @@ def test_telegram_sell_reason_performance_handle(default_conf, update, ticker, f freqtradebot.enter_positions() trade = Trade.query.first() assert trade - trade.sell_reason = 'TESTSELL' + trade.exit_reason = 'TESTSELL' # Simulate fulfilled LIMIT_BUY order for trade oobj = Order.parse_from_ccxt_object(limit_buy_order, limit_buy_order['symbol'], 'buy') trade.update_trade(oobj) @@ -1405,19 +1453,19 @@ def test_telegram_sell_reason_performance_handle(default_conf, update, ticker, f trade.close_date = datetime.utcnow() trade.is_open = False context = MagicMock() - telegram._sell_reason_performance(update=update, context=context) + telegram._exit_reason_performance(update=update, context=context) assert msg_mock.call_count == 1 - assert 'Sell Reason Performance' in msg_mock.call_args_list[0][0][0] + assert 'Exit Reason Performance' in msg_mock.call_args_list[0][0][0] assert 'TESTSELL\t0.00006217 BTC (6.20%) (1)' in msg_mock.call_args_list[0][0][0] context.args = [trade.pair] - telegram._sell_reason_performance(update=update, context=context) + telegram._exit_reason_performance(update=update, context=context) assert msg_mock.call_count == 2 msg_mock.reset_mock() - mocker.patch('freqtrade.rpc.rpc.RPC._rpc_sell_reason_performance', + mocker.patch('freqtrade.rpc.rpc.RPC._rpc_exit_reason_performance', side_effect=RPCException('Error')) - telegram._sell_reason_performance(update=update, context=MagicMock()) + telegram._exit_reason_performance(update=update, context=MagicMock()) assert msg_mock.call_count == 1 assert "Error" in msg_mock.call_args_list[0][0][0] @@ -1439,7 +1487,7 @@ def test_telegram_mix_tag_performance_handle(default_conf, update, ticker, fee, assert trade trade.enter_tag = "TESTBUY" - trade.sell_reason = "TESTSELL" + trade.exit_reason = "TESTSELL" # Simulate fulfilled LIMIT_BUY order for trade oobj = Order.parse_from_ccxt_object(limit_buy_order, limit_buy_order['symbol'], 'buy') @@ -1768,10 +1816,10 @@ def test_show_config_handle(default_conf, update, mocker) -> None: @pytest.mark.parametrize('message_type,enter,enter_signal,leverage', [ - (RPCMessageType.BUY, 'Long', 'long_signal_01', None), - (RPCMessageType.BUY, 'Long', 'long_signal_01', 1.0), - (RPCMessageType.BUY, 'Long', 'long_signal_01', 5.0), - (RPCMessageType.SHORT, 'Short', 'short_signal_01', 2.0)]) + (RPCMessageType.ENTRY, 'Long', 'long_signal_01', None), + (RPCMessageType.ENTRY, 'Long', 'long_signal_01', 1.0), + (RPCMessageType.ENTRY, 'Long', 'long_signal_01', 5.0), + (RPCMessageType.ENTRY, 'Short', 'short_signal_01', 2.0)]) def test_send_msg_buy_notification(default_conf, mocker, caplog, message_type, enter, enter_signal, leverage) -> None: @@ -1784,6 +1832,7 @@ def test_send_msg_buy_notification(default_conf, mocker, caplog, message_type, 'leverage': leverage, 'limit': 1.099e-05, 'order_type': 'limit', + 'direction': enter, 'stake_amount': 0.01465333, 'stake_amount_fiat': 0.0, 'stake_currency': 'BTC', @@ -1824,8 +1873,8 @@ def test_send_msg_buy_notification(default_conf, mocker, caplog, message_type, @pytest.mark.parametrize('message_type,enter_signal', [ - (RPCMessageType.BUY_CANCEL, 'long_signal_01'), - (RPCMessageType.SHORT_CANCEL, 'short_signal_01')]) + (RPCMessageType.ENTRY_CANCEL, 'long_signal_01'), + (RPCMessageType.ENTRY_CANCEL, 'short_signal_01')]) def test_send_msg_buy_cancel_notification(default_conf, mocker, message_type, enter_signal) -> None: telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf) @@ -1872,14 +1921,14 @@ def test_send_msg_protection_notification(default_conf, mocker, time_machine) -> @pytest.mark.parametrize('message_type,entered,enter_signal,leverage', [ - (RPCMessageType.BUY_FILL, 'Longed', 'long_signal_01', 1.0), - (RPCMessageType.BUY_FILL, 'Longed', 'long_signal_02', 2.0), - (RPCMessageType.SHORT_FILL, 'Shorted', 'short_signal_01', 2.0), + (RPCMessageType.ENTRY_FILL, 'Long', 'long_signal_01', 1.0), + (RPCMessageType.ENTRY_FILL, 'Long', 'long_signal_02', 2.0), + (RPCMessageType.ENTRY_FILL, 'Short', 'short_signal_01', 2.0), ]) -def test_send_msg_buy_fill_notification(default_conf, mocker, message_type, entered, - enter_signal, leverage) -> None: +def test_send_msg_entry_fill_notification(default_conf, mocker, message_type, entered, + enter_signal, leverage) -> None: - default_conf['telegram']['notification_settings']['buy_fill'] = 'on' + default_conf['telegram']['notification_settings']['entry_fill'] = 'on' telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf) telegram.send_msg({ @@ -1890,6 +1939,7 @@ def test_send_msg_buy_fill_notification(default_conf, mocker, message_type, ente 'pair': 'ETH/BTC', 'leverage': leverage, 'stake_amount': 0.01465333, + 'direction': entered, # 'stake_amount_fiat': 0.0, 'stake_currency': 'BTC', 'fiat_currency': 'USD', @@ -1899,7 +1949,7 @@ def test_send_msg_buy_fill_notification(default_conf, mocker, message_type, ente }) leverage_text = f'*Leverage:* `{leverage}`\n' if leverage != 1.0 else '' assert msg_mock.call_args[0][0] == ( - f'\N{CHECK MARK} *Binance:* {entered} ETH/BTC (#1)\n' + f'\N{CHECK MARK} *Binance:* {entered}ed ETH/BTC (#1)\n' f'*Enter Tag:* `{enter_signal}`\n' '*Amount:* `1333.33333333`\n' f"{leverage_text}" @@ -1915,7 +1965,7 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None: old_convamount = telegram._rpc._fiat_converter.convert_amount telegram._rpc._fiat_converter.convert_amount = lambda a, b, c: -24.812 telegram.send_msg({ - 'type': RPCMessageType.SELL, + 'type': RPCMessageType.EXIT, 'trade_id': 1, 'exchange': 'Binance', 'pair': 'KEY/ETH', @@ -1932,7 +1982,7 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None: 'stake_currency': 'ETH', 'fiat_currency': 'USD', 'enter_tag': 'buy_signal1', - 'sell_reason': ExitType.STOP_LOSS.value, + 'exit_reason': ExitType.STOP_LOSS.value, 'open_date': arrow.utcnow().shift(hours=-1), 'close_date': arrow.utcnow(), }) @@ -1951,7 +2001,7 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None: msg_mock.reset_mock() telegram.send_msg({ - 'type': RPCMessageType.SELL, + 'type': RPCMessageType.EXIT, 'trade_id': 1, 'exchange': 'Binance', 'pair': 'KEY/ETH', @@ -1966,7 +2016,7 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None: 'profit_ratio': -0.57405275, 'stake_currency': 'ETH', 'enter_tag': 'buy_signal1', - 'sell_reason': ExitType.STOP_LOSS.value, + 'exit_reason': ExitType.STOP_LOSS.value, 'open_date': arrow.utcnow().shift(days=-1, hours=-2, minutes=-30), 'close_date': arrow.utcnow(), }) @@ -1993,7 +2043,7 @@ def test_send_msg_sell_cancel_notification(default_conf, mocker) -> None: old_convamount = telegram._rpc._fiat_converter.convert_amount telegram._rpc._fiat_converter.convert_amount = lambda a, b, c: -24.812 telegram.send_msg({ - 'type': RPCMessageType.SELL_CANCEL, + 'type': RPCMessageType.EXIT_CANCEL, 'trade_id': 1, 'exchange': 'Binance', 'pair': 'KEY/ETH', @@ -2005,7 +2055,7 @@ def test_send_msg_sell_cancel_notification(default_conf, mocker) -> None: msg_mock.reset_mock() telegram.send_msg({ - 'type': RPCMessageType.SELL_CANCEL, + 'type': RPCMessageType.EXIT_CANCEL, 'trade_id': 1, 'exchange': 'Binance', 'pair': 'KEY/ETH', @@ -2025,11 +2075,11 @@ def test_send_msg_sell_cancel_notification(default_conf, mocker) -> None: def test_send_msg_sell_fill_notification(default_conf, mocker, direction, enter_signal, leverage) -> None: - default_conf['telegram']['notification_settings']['sell_fill'] = 'on' + default_conf['telegram']['notification_settings']['exit_fill'] = 'on' telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf) telegram.send_msg({ - 'type': RPCMessageType.SELL_FILL, + 'type': RPCMessageType.EXIT_FILL, 'trade_id': 1, 'exchange': 'Binance', 'pair': 'KEY/ETH', @@ -2045,7 +2095,7 @@ def test_send_msg_sell_fill_notification(default_conf, mocker, direction, 'profit_ratio': -0.57405275, 'stake_currency': 'ETH', 'enter_tag': enter_signal, - 'sell_reason': ExitType.STOP_LOSS.value, + 'exit_reason': ExitType.STOP_LOSS.value, 'open_date': arrow.utcnow().shift(days=-1, hours=-2, minutes=-30), 'close_date': arrow.utcnow(), }) @@ -2102,9 +2152,9 @@ def test_send_msg_unknown_type(default_conf, mocker) -> None: @pytest.mark.parametrize('message_type,enter,enter_signal,leverage', [ - (RPCMessageType.BUY, 'Long', 'long_signal_01', None), - (RPCMessageType.BUY, 'Long', 'long_signal_01', 2.0), - (RPCMessageType.SHORT, 'Short', 'short_signal_01', 2.0)]) + (RPCMessageType.ENTRY, 'Long', 'long_signal_01', None), + (RPCMessageType.ENTRY, 'Long', 'long_signal_01', 2.0), + (RPCMessageType.ENTRY, 'Short', 'short_signal_01', 2.0)]) def test_send_msg_buy_notification_no_fiat( default_conf, mocker, message_type, enter, enter_signal, leverage) -> None: del default_conf['fiat_display_currency'] @@ -2119,6 +2169,7 @@ def test_send_msg_buy_notification_no_fiat( 'leverage': leverage, 'limit': 1.099e-05, 'order_type': 'limit', + 'direction': enter, 'stake_amount': 0.01465333, 'stake_amount_fiat': 0.0, 'stake_currency': 'BTC', @@ -2152,7 +2203,7 @@ def test_send_msg_sell_notification_no_fiat( telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf) telegram.send_msg({ - 'type': RPCMessageType.SELL, + 'type': RPCMessageType.EXIT, 'trade_id': 1, 'exchange': 'Binance', 'pair': 'KEY/ETH', @@ -2169,7 +2220,7 @@ def test_send_msg_sell_notification_no_fiat( 'stake_currency': 'ETH', 'fiat_currency': 'USD', 'enter_tag': enter_signal, - 'sell_reason': ExitType.STOP_LOSS.value, + 'exit_reason': ExitType.STOP_LOSS.value, 'open_date': arrow.utcnow().shift(hours=-2, minutes=-35, seconds=-3), 'close_date': arrow.utcnow(), }) @@ -2191,13 +2242,13 @@ def test_send_msg_sell_notification_no_fiat( @pytest.mark.parametrize('msg,expected', [ - ({'profit_percent': 20.1, 'sell_reason': 'roi'}, "\N{ROCKET}"), - ({'profit_percent': 5.1, 'sell_reason': 'roi'}, "\N{ROCKET}"), - ({'profit_percent': 2.56, 'sell_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"), - ({'profit_percent': 1.0, 'sell_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"), - ({'profit_percent': 0.0, 'sell_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"), - ({'profit_percent': -5.0, 'sell_reason': 'stop_loss'}, "\N{WARNING SIGN}"), - ({'profit_percent': -2.0, 'sell_reason': 'sell_signal'}, "\N{CROSS MARK}"), + ({'profit_percent': 20.1, 'exit_reason': 'roi'}, "\N{ROCKET}"), + ({'profit_percent': 5.1, 'exit_reason': 'roi'}, "\N{ROCKET}"), + ({'profit_percent': 2.56, 'exit_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"), + ({'profit_percent': 1.0, 'exit_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"), + ({'profit_percent': 0.0, 'exit_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"), + ({'profit_percent': -5.0, 'exit_reason': 'stop_loss'}, "\N{WARNING SIGN}"), + ({'profit_percent': -2.0, 'exit_reason': 'sell_signal'}, "\N{CROSS MARK}"), ]) def test__sell_emoji(default_conf, mocker, msg, expected): del default_conf['fiat_display_currency'] diff --git a/tests/rpc/test_rpc_webhook.py b/tests/rpc/test_rpc_webhook.py index 1d80b58e5..db357f80f 100644 --- a/tests/rpc/test_rpc_webhook.py +++ b/tests/rpc/test_rpc_webhook.py @@ -15,38 +15,38 @@ def get_webhook_dict() -> dict: return { "enabled": True, "url": "https://maker.ifttt.com/trigger/freqtrade_test/with/key/c764udvJ5jfSlswVRukZZ2/", - "webhookbuy": { + "webhookentry": { "value1": "Buying {pair}", "value2": "limit {limit:8f}", "value3": "{stake_amount:8f} {stake_currency}", "value4": "leverage {leverage:.1f}", "value5": "direction {direction}" }, - "webhookbuycancel": { + "webhookentrycancel": { "value1": "Cancelling Open Buy Order for {pair}", "value2": "limit {limit:8f}", "value3": "{stake_amount:8f} {stake_currency}", "value4": "leverage {leverage:.1f}", "value5": "direction {direction}" }, - "webhookbuyfill": { + "webhookentryfill": { "value1": "Buy Order for {pair} filled", "value2": "at {open_rate:8f}", "value3": "{stake_amount:8f} {stake_currency}", "value4": "leverage {leverage:.1f}", "value5": "direction {direction}" }, - "webhooksell": { + "webhookexit": { "value1": "Selling {pair}", "value2": "limit {limit:8f}", "value3": "profit: {profit_amount:8f} {stake_currency} ({profit_ratio})" }, - "webhooksellcancel": { + "webhookexitcancel": { "value1": "Cancelling Open Sell Order for {pair}", "value2": "limit {limit:8f}", "value3": "profit: {profit_amount:8f} {stake_currency} ({profit_ratio})" }, - "webhooksellfill": { + "webhookexitfill": { "value1": "Sell Order for {pair} filled", "value2": "at {close_rate:8f}", "value3": "" @@ -74,7 +74,7 @@ def test_send_msg_webhook(default_conf, mocker): msg_mock = MagicMock() mocker.patch("freqtrade.rpc.webhook.Webhook._send_msg", msg_mock) msg = { - 'type': RPCMessageType.BUY, + 'type': RPCMessageType.ENTRY, 'exchange': 'Binance', 'pair': 'ETH/BTC', 'leverage': 1.0, @@ -88,20 +88,20 @@ def test_send_msg_webhook(default_conf, mocker): webhook.send_msg(msg=msg) assert msg_mock.call_count == 1 assert (msg_mock.call_args[0][0]["value1"] == - default_conf["webhook"]["webhookbuy"]["value1"].format(**msg)) + default_conf["webhook"]["webhookentry"]["value1"].format(**msg)) assert (msg_mock.call_args[0][0]["value2"] == - default_conf["webhook"]["webhookbuy"]["value2"].format(**msg)) + default_conf["webhook"]["webhookentry"]["value2"].format(**msg)) assert (msg_mock.call_args[0][0]["value3"] == - default_conf["webhook"]["webhookbuy"]["value3"].format(**msg)) + default_conf["webhook"]["webhookentry"]["value3"].format(**msg)) assert (msg_mock.call_args[0][0]["value4"] == - default_conf["webhook"]["webhookbuy"]["value4"].format(**msg)) + default_conf["webhook"]["webhookentry"]["value4"].format(**msg)) assert (msg_mock.call_args[0][0]["value5"] == - default_conf["webhook"]["webhookbuy"]["value5"].format(**msg)) + default_conf["webhook"]["webhookentry"]["value5"].format(**msg)) # Test short msg_mock.reset_mock() msg = { - 'type': RPCMessageType.SHORT, + 'type': RPCMessageType.ENTRY, 'exchange': 'Binance', 'pair': 'ETH/BTC', 'leverage': 2.0, @@ -115,20 +115,20 @@ def test_send_msg_webhook(default_conf, mocker): webhook.send_msg(msg=msg) assert msg_mock.call_count == 1 assert (msg_mock.call_args[0][0]["value1"] == - default_conf["webhook"]["webhookbuy"]["value1"].format(**msg)) + default_conf["webhook"]["webhookentry"]["value1"].format(**msg)) assert (msg_mock.call_args[0][0]["value2"] == - default_conf["webhook"]["webhookbuy"]["value2"].format(**msg)) + default_conf["webhook"]["webhookentry"]["value2"].format(**msg)) assert (msg_mock.call_args[0][0]["value3"] == - default_conf["webhook"]["webhookbuy"]["value3"].format(**msg)) + default_conf["webhook"]["webhookentry"]["value3"].format(**msg)) assert (msg_mock.call_args[0][0]["value4"] == - default_conf["webhook"]["webhookbuy"]["value4"].format(**msg)) + default_conf["webhook"]["webhookentry"]["value4"].format(**msg)) assert (msg_mock.call_args[0][0]["value5"] == - default_conf["webhook"]["webhookbuy"]["value5"].format(**msg)) + default_conf["webhook"]["webhookentry"]["value5"].format(**msg)) # Test buy cancel msg_mock.reset_mock() msg = { - 'type': RPCMessageType.BUY_CANCEL, + 'type': RPCMessageType.ENTRY_CANCEL, 'exchange': 'Binance', 'pair': 'ETH/BTC', 'leverage': 1.0, @@ -142,16 +142,16 @@ def test_send_msg_webhook(default_conf, mocker): webhook.send_msg(msg=msg) assert msg_mock.call_count == 1 assert (msg_mock.call_args[0][0]["value1"] == - default_conf["webhook"]["webhookbuycancel"]["value1"].format(**msg)) + default_conf["webhook"]["webhookentrycancel"]["value1"].format(**msg)) assert (msg_mock.call_args[0][0]["value2"] == - default_conf["webhook"]["webhookbuycancel"]["value2"].format(**msg)) + default_conf["webhook"]["webhookentrycancel"]["value2"].format(**msg)) assert (msg_mock.call_args[0][0]["value3"] == - default_conf["webhook"]["webhookbuycancel"]["value3"].format(**msg)) + default_conf["webhook"]["webhookentrycancel"]["value3"].format(**msg)) # Test short cancel msg_mock.reset_mock() msg = { - 'type': RPCMessageType.SHORT_CANCEL, + 'type': RPCMessageType.ENTRY_CANCEL, 'exchange': 'Binance', 'pair': 'ETH/BTC', 'leverage': 2.0, @@ -165,20 +165,20 @@ def test_send_msg_webhook(default_conf, mocker): webhook.send_msg(msg=msg) assert msg_mock.call_count == 1 assert (msg_mock.call_args[0][0]["value1"] == - default_conf["webhook"]["webhookbuycancel"]["value1"].format(**msg)) + default_conf["webhook"]["webhookentrycancel"]["value1"].format(**msg)) assert (msg_mock.call_args[0][0]["value2"] == - default_conf["webhook"]["webhookbuycancel"]["value2"].format(**msg)) + default_conf["webhook"]["webhookentrycancel"]["value2"].format(**msg)) assert (msg_mock.call_args[0][0]["value3"] == - default_conf["webhook"]["webhookbuycancel"]["value3"].format(**msg)) + default_conf["webhook"]["webhookentrycancel"]["value3"].format(**msg)) assert (msg_mock.call_args[0][0]["value4"] == - default_conf["webhook"]["webhookbuycancel"]["value4"].format(**msg)) + default_conf["webhook"]["webhookentrycancel"]["value4"].format(**msg)) assert (msg_mock.call_args[0][0]["value5"] == - default_conf["webhook"]["webhookbuycancel"]["value5"].format(**msg)) + default_conf["webhook"]["webhookentrycancel"]["value5"].format(**msg)) # Test buy fill msg_mock.reset_mock() msg = { - 'type': RPCMessageType.BUY_FILL, + 'type': RPCMessageType.ENTRY_FILL, 'exchange': 'Binance', 'pair': 'ETH/BTC', 'leverage': 1.0, @@ -192,20 +192,20 @@ def test_send_msg_webhook(default_conf, mocker): webhook.send_msg(msg=msg) assert msg_mock.call_count == 1 assert (msg_mock.call_args[0][0]["value1"] == - default_conf["webhook"]["webhookbuyfill"]["value1"].format(**msg)) + default_conf["webhook"]["webhookentryfill"]["value1"].format(**msg)) assert (msg_mock.call_args[0][0]["value2"] == - default_conf["webhook"]["webhookbuyfill"]["value2"].format(**msg)) + default_conf["webhook"]["webhookentryfill"]["value2"].format(**msg)) assert (msg_mock.call_args[0][0]["value3"] == - default_conf["webhook"]["webhookbuyfill"]["value3"].format(**msg)) + default_conf["webhook"]["webhookentryfill"]["value3"].format(**msg)) assert (msg_mock.call_args[0][0]["value4"] == - default_conf["webhook"]["webhookbuycancel"]["value4"].format(**msg)) + default_conf["webhook"]["webhookentrycancel"]["value4"].format(**msg)) assert (msg_mock.call_args[0][0]["value5"] == - default_conf["webhook"]["webhookbuycancel"]["value5"].format(**msg)) + default_conf["webhook"]["webhookentrycancel"]["value5"].format(**msg)) # Test short fill msg_mock.reset_mock() msg = { - 'type': RPCMessageType.SHORT_FILL, + 'type': RPCMessageType.ENTRY_FILL, 'exchange': 'Binance', 'pair': 'ETH/BTC', 'leverage': 2.0, @@ -219,20 +219,20 @@ def test_send_msg_webhook(default_conf, mocker): webhook.send_msg(msg=msg) assert msg_mock.call_count == 1 assert (msg_mock.call_args[0][0]["value1"] == - default_conf["webhook"]["webhookbuyfill"]["value1"].format(**msg)) + default_conf["webhook"]["webhookentryfill"]["value1"].format(**msg)) assert (msg_mock.call_args[0][0]["value2"] == - default_conf["webhook"]["webhookbuyfill"]["value2"].format(**msg)) + default_conf["webhook"]["webhookentryfill"]["value2"].format(**msg)) assert (msg_mock.call_args[0][0]["value3"] == - default_conf["webhook"]["webhookbuyfill"]["value3"].format(**msg)) + default_conf["webhook"]["webhookentryfill"]["value3"].format(**msg)) assert (msg_mock.call_args[0][0]["value4"] == - default_conf["webhook"]["webhookbuycancel"]["value4"].format(**msg)) + default_conf["webhook"]["webhookentrycancel"]["value4"].format(**msg)) assert (msg_mock.call_args[0][0]["value5"] == - default_conf["webhook"]["webhookbuycancel"]["value5"].format(**msg)) + default_conf["webhook"]["webhookentrycancel"]["value5"].format(**msg)) # Test sell msg_mock.reset_mock() msg = { - 'type': RPCMessageType.SELL, + 'type': RPCMessageType.EXIT, 'exchange': 'Binance', 'pair': 'ETH/BTC', 'gain': "profit", @@ -249,15 +249,15 @@ def test_send_msg_webhook(default_conf, mocker): webhook.send_msg(msg=msg) assert msg_mock.call_count == 1 assert (msg_mock.call_args[0][0]["value1"] == - default_conf["webhook"]["webhooksell"]["value1"].format(**msg)) + default_conf["webhook"]["webhookexit"]["value1"].format(**msg)) assert (msg_mock.call_args[0][0]["value2"] == - default_conf["webhook"]["webhooksell"]["value2"].format(**msg)) + default_conf["webhook"]["webhookexit"]["value2"].format(**msg)) assert (msg_mock.call_args[0][0]["value3"] == - default_conf["webhook"]["webhooksell"]["value3"].format(**msg)) + default_conf["webhook"]["webhookexit"]["value3"].format(**msg)) # Test sell cancel msg_mock.reset_mock() msg = { - 'type': RPCMessageType.SELL_CANCEL, + 'type': RPCMessageType.EXIT_CANCEL, 'exchange': 'Binance', 'pair': 'ETH/BTC', 'gain': "profit", @@ -274,15 +274,15 @@ def test_send_msg_webhook(default_conf, mocker): webhook.send_msg(msg=msg) assert msg_mock.call_count == 1 assert (msg_mock.call_args[0][0]["value1"] == - default_conf["webhook"]["webhooksellcancel"]["value1"].format(**msg)) + default_conf["webhook"]["webhookexitcancel"]["value1"].format(**msg)) assert (msg_mock.call_args[0][0]["value2"] == - default_conf["webhook"]["webhooksellcancel"]["value2"].format(**msg)) + default_conf["webhook"]["webhookexitcancel"]["value2"].format(**msg)) assert (msg_mock.call_args[0][0]["value3"] == - default_conf["webhook"]["webhooksellcancel"]["value3"].format(**msg)) + default_conf["webhook"]["webhookexitcancel"]["value3"].format(**msg)) # Test Sell fill msg_mock.reset_mock() msg = { - 'type': RPCMessageType.SELL_FILL, + 'type': RPCMessageType.EXIT_FILL, 'exchange': 'Binance', 'pair': 'ETH/BTC', 'gain': "profit", @@ -299,11 +299,11 @@ def test_send_msg_webhook(default_conf, mocker): webhook.send_msg(msg=msg) assert msg_mock.call_count == 1 assert (msg_mock.call_args[0][0]["value1"] == - default_conf["webhook"]["webhooksellfill"]["value1"].format(**msg)) + default_conf["webhook"]["webhookexitfill"]["value1"].format(**msg)) assert (msg_mock.call_args[0][0]["value2"] == - default_conf["webhook"]["webhooksellfill"]["value2"].format(**msg)) + default_conf["webhook"]["webhookexitfill"]["value2"].format(**msg)) assert (msg_mock.call_args[0][0]["value3"] == - default_conf["webhook"]["webhooksellfill"]["value3"].format(**msg)) + default_conf["webhook"]["webhookexitfill"]["value3"].format(**msg)) for msgtype in [RPCMessageType.STATUS, RPCMessageType.WARNING, @@ -327,20 +327,20 @@ def test_send_msg_webhook(default_conf, mocker): def test_exception_send_msg(default_conf, mocker, caplog): default_conf["webhook"] = get_webhook_dict() - del default_conf["webhook"]["webhookbuy"] + del default_conf["webhook"]["webhookentry"] webhook = Webhook(RPC(get_patched_freqtradebot(mocker, default_conf)), default_conf) - webhook.send_msg({'type': RPCMessageType.BUY}) - assert log_has(f"Message type '{RPCMessageType.BUY}' not configured for webhooks", + webhook.send_msg({'type': RPCMessageType.ENTRY}) + assert log_has(f"Message type '{RPCMessageType.ENTRY}' not configured for webhooks", caplog) default_conf["webhook"] = get_webhook_dict() - default_conf["webhook"]["webhookbuy"]["value1"] = "{DEADBEEF:8f}" + default_conf["webhook"]["webhookentry"]["value1"] = "{DEADBEEF:8f}" msg_mock = MagicMock() mocker.patch("freqtrade.rpc.webhook.Webhook._send_msg", msg_mock) webhook = Webhook(RPC(get_patched_freqtradebot(mocker, default_conf)), default_conf) msg = { - 'type': RPCMessageType.BUY, + 'type': RPCMessageType.ENTRY, 'exchange': 'Binance', 'pair': 'ETH/BTC', 'limit': 0.005, diff --git a/tests/strategy/strats/broken_strats/legacy_strategy_v1.py b/tests/strategy/strats/broken_strats/legacy_strategy_v1.py new file mode 100644 index 000000000..f3b8c2696 --- /dev/null +++ b/tests/strategy/strats/broken_strats/legacy_strategy_v1.py @@ -0,0 +1,30 @@ +# type: ignore +from pandas import DataFrame + +from freqtrade.strategy import IStrategy + + +# Dummy strategy - no longer loads but raises an exception. +class TestStrategyLegacyV1(IStrategy): + + minimal_roi = { + "40": 0.0, + "30": 0.01, + "20": 0.02, + "0": 0.04 + } + stoploss = -0.10 + + timeframe = '5m' + + def populate_indicators(self, dataframe: DataFrame) -> DataFrame: + + return dataframe + + def populate_buy_trend(self, dataframe: DataFrame) -> DataFrame: + + return dataframe + + def populate_sell_trend(self, dataframe: DataFrame) -> DataFrame: + + return dataframe diff --git a/tests/strategy/strats/legacy_strategy_v1.py b/tests/strategy/strats/legacy_strategy_v1.py deleted file mode 100644 index bad2aa40d..000000000 --- a/tests/strategy/strats/legacy_strategy_v1.py +++ /dev/null @@ -1,85 +0,0 @@ - -# --- 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. -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/strats/strategy_test_v2.py b/tests/strategy/strats/strategy_test_v2.py index a9ca7d9e2..85ff856e1 100644 --- a/tests/strategy/strats/strategy_test_v2.py +++ b/tests/strategy/strats/strategy_test_v2.py @@ -50,23 +50,12 @@ class StrategyTestV2(IStrategy): 'entry': 'gtc', 'exit': 'gtc', } + # Test legacy use_sell_signal definition + use_sell_signal = False # 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 diff --git a/tests/strategy/strats/strategy_test_v3.py b/tests/strategy/strats/strategy_test_v3.py index 168545bbb..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 [] @@ -183,7 +188,7 @@ class StrategyTestV3(IStrategy): current_profit: float, min_stake: float, max_stake: float, **kwargs): if current_profit < -0.0075: - orders = trade.select_filled_orders(trade.enter_side) + orders = trade.select_filled_orders(trade.entry_side) return round(orders[0].cost, 0) return None diff --git a/tests/strategy/test_interface.py b/tests/strategy/test_interface.py index a5325a680..6e57a3182 100644 --- a/tests/strategy/test_interface.py +++ b/tests/strategy/test_interface.py @@ -503,15 +503,15 @@ def test_custom_exit(default_conf, fee, caplog) -> None: enter=False, exit_=False, low=None, high=None) assert res.exit_flag is True - assert res.exit_type == ExitType.CUSTOM_SELL - assert res.exit_reason == 'custom_sell' + assert res.exit_type == ExitType.CUSTOM_EXIT + assert res.exit_reason == 'custom_exit' strategy.custom_exit = MagicMock(return_value='hello world') res = strategy.should_exit(trade, 1, now, enter=False, exit_=False, low=None, high=None) - assert res.exit_type == ExitType.CUSTOM_SELL + assert res.exit_type == ExitType.CUSTOM_EXIT assert res.exit_flag is True assert res.exit_reason == 'hello world' @@ -520,10 +520,10 @@ def test_custom_exit(default_conf, fee, caplog) -> None: res = strategy.should_exit(trade, 1, now, enter=False, exit_=False, low=None, high=None) - assert res.exit_type == ExitType.CUSTOM_SELL + assert res.exit_type == ExitType.CUSTOM_EXIT assert res.exit_flag is True assert res.exit_reason == 'h' * 64 - assert log_has_re('Custom sell reason returned from custom_exit is too long.*', caplog) + assert log_has_re('Custom exit reason returned from custom_exit is too long.*', caplog) @pytest.mark.parametrize('side', TRADE_SIDES) @@ -666,27 +666,27 @@ def test_is_pair_locked(default_conf): assert not strategy.is_pair_locked(pair) # latest candle is from 14:20, lock goes to 14:30 - assert strategy.is_pair_locked(pair, lock_time + timedelta(minutes=-10)) - assert strategy.is_pair_locked(pair, lock_time + timedelta(minutes=-50)) + assert strategy.is_pair_locked(pair, candle_date=lock_time + timedelta(minutes=-10)) + assert strategy.is_pair_locked(pair, candle_date=lock_time + timedelta(minutes=-50)) # latest candle is from 14:25 (lock should be lifted) # Since this is the "new candle" available at 14:30 - assert not strategy.is_pair_locked(pair, lock_time + timedelta(minutes=-4)) + assert not strategy.is_pair_locked(pair, candle_date=lock_time + timedelta(minutes=-4)) # Should not be locked after time expired - assert not strategy.is_pair_locked(pair, lock_time + timedelta(minutes=10)) + assert not strategy.is_pair_locked(pair, candle_date=lock_time + timedelta(minutes=10)) # Change timeframe to 15m strategy.timeframe = '15m' # Candle from 14:14 - lock goes until 14:30 - assert strategy.is_pair_locked(pair, lock_time + timedelta(minutes=-16)) - assert strategy.is_pair_locked(pair, lock_time + timedelta(minutes=-15, seconds=-2)) + assert strategy.is_pair_locked(pair, candle_date=lock_time + timedelta(minutes=-16)) + assert strategy.is_pair_locked(pair, candle_date=lock_time + timedelta(minutes=-15, seconds=-2)) # Candle from 14:15 - lock goes until 14:30 - assert not strategy.is_pair_locked(pair, lock_time + timedelta(minutes=-15)) + assert not strategy.is_pair_locked(pair, candle_date=lock_time + timedelta(minutes=-15)) 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_helpers.py b/tests/strategy/test_strategy_helpers.py index 205fb4dac..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) @@ -164,7 +179,7 @@ def test_stoploss_from_absolute(): assert pytest.approx(stoploss_from_absolute(90, 100, True)) == 0 assert pytest.approx(stoploss_from_absolute(100, 100, True)) == 0 - assert pytest.approx(stoploss_from_absolute(110, 100, True)) == -(1 - (110/100)) + assert pytest.approx(stoploss_from_absolute(110, 100, True)) == -(1 - (110 / 100)) assert pytest.approx(stoploss_from_absolute(110, 100, True)) == 0.1 assert pytest.approx(stoploss_from_absolute(105, 100, True)) == 0.05 assert pytest.approx(stoploss_from_absolute(100, 0, True)) == 1 diff --git a/tests/strategy/test_strategy_loading.py b/tests/strategy/test_strategy_loading.py index b1b67dcf0..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 @@ -100,7 +99,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}) @@ -143,16 +142,6 @@ def test_strategy_can_short(caplog, default_conf): assert isinstance(strat, IStrategy) -def test_strategy_implements_populate_entry(caplog, default_conf): - caplog.set_level(logging.INFO) - default_conf.update({ - 'strategy': "StrategyTestV2", - }) - default_conf['trading_mode'] = 'futures' - with pytest.raises(OperationalException, match="`populate_entry_trend` must be implemented."): - StrategyResolver.load_strategy(default_conf) - - def test_strategy_override_minimal_roi(caplog, default_conf): caplog.set_level(logging.INFO) default_conf.update({ @@ -310,88 +299,69 @@ def test_strategy_override_order_tif(caplog, default_conf): StrategyResolver.load_strategy(default_conf) -def test_strategy_override_use_sell_signal(caplog, default_conf): +def test_strategy_override_use_exit_signal(caplog, default_conf): caplog.set_level(logging.INFO) default_conf.update({ 'strategy': CURRENT_TEST_STRATEGY, }) strategy = StrategyResolver.load_strategy(default_conf) - assert strategy.use_sell_signal - assert isinstance(strategy.use_sell_signal, bool) + assert strategy.use_exit_signal + assert isinstance(strategy.use_exit_signal, bool) # must be inserted to configuration - assert 'use_sell_signal' in default_conf - assert default_conf['use_sell_signal'] + assert 'use_exit_signal' in default_conf + assert default_conf['use_exit_signal'] default_conf.update({ 'strategy': CURRENT_TEST_STRATEGY, - 'use_sell_signal': False, + 'use_exit_signal': False, }) strategy = StrategyResolver.load_strategy(default_conf) - assert not strategy.use_sell_signal - assert isinstance(strategy.use_sell_signal, bool) - assert log_has("Override strategy 'use_sell_signal' with value in config file: False.", caplog) + assert not strategy.use_exit_signal + assert isinstance(strategy.use_exit_signal, bool) + assert log_has("Override strategy 'use_exit_signal' with value in config file: False.", caplog) -def test_strategy_override_use_sell_profit_only(caplog, default_conf): +def test_strategy_override_use_exit_profit_only(caplog, default_conf): caplog.set_level(logging.INFO) default_conf.update({ 'strategy': CURRENT_TEST_STRATEGY, }) strategy = StrategyResolver.load_strategy(default_conf) - assert not strategy.sell_profit_only - assert isinstance(strategy.sell_profit_only, bool) + assert not strategy.exit_profit_only + assert isinstance(strategy.exit_profit_only, bool) # must be inserted to configuration - assert 'sell_profit_only' in default_conf - assert not default_conf['sell_profit_only'] + assert 'exit_profit_only' in default_conf + assert not default_conf['exit_profit_only'] default_conf.update({ 'strategy': CURRENT_TEST_STRATEGY, - 'sell_profit_only': True, + 'exit_profit_only': True, }) strategy = StrategyResolver.load_strategy(default_conf) - assert strategy.sell_profit_only - assert isinstance(strategy.sell_profit_only, bool) - assert log_has("Override strategy 'sell_profit_only' with value in config file: True.", caplog) + assert strategy.exit_profit_only + assert isinstance(strategy.exit_profit_only, bool) + 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): +def test_missing_implements(default_conf, caplog): + default_location = Path(__file__).parent / "strats" - default_conf.update({'strategy': 'TestStrategyLegacyV1', + default_conf.update({'strategy': 'StrategyTestV2', '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) + StrategyResolver.load_strategy(default_conf) - 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) + log_has_re(r"DEPRECATED: .*use_sell_signal.*use_exit_signal.", caplog) - 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) + default_conf['trading_mode'] = 'futures' + with pytest.raises(OperationalException, + match=r"DEPRECATED: .*use_sell_signal.*use_exit_signal."): + StrategyResolver.load_strategy(default_conf) + default_conf['trading_mode'] = 'spot' -@pytest.mark.filterwarnings("ignore:deprecated") -def test_missing_implements(default_conf): default_location = Path(__file__).parent / "strats/broken_strats" default_conf.update({'strategy': 'TestStrategyNoImplements', 'strategy_path': default_location}) @@ -433,33 +403,14 @@ def test_missing_implements(default_conf): StrategyResolver.load_strategy(default_conf) -@pytest.mark.filterwarnings("ignore:deprecated") -def test_call_deprecated_function(result, default_conf, caplog): - default_location = Path(__file__).parent / "strats" +def test_call_deprecated_function(default_conf): + default_location = Path(__file__).parent / "strats/broken_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): @@ -467,10 +418,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) diff --git a/tests/test_configuration.py b/tests/test_configuration.py index 3783e30a1..db87c405f 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -18,7 +18,8 @@ from freqtrade.configuration.deprecated_settings import (check_conflicting_setti process_removed_setting, process_temporary_deprecated_settings) from freqtrade.configuration.environment_vars import flat_vars_to_nested_dict -from freqtrade.configuration.load_config import load_config_file, load_file, log_config_error_range +from freqtrade.configuration.load_config import (load_config_file, load_file, load_from_files, + log_config_error_range) from freqtrade.constants import DEFAULT_DB_DRYRUN_URL, DEFAULT_DB_PROD_URL, ENV_VAR_PREFIX from freqtrade.enums import RunMode from freqtrade.exceptions import OperationalException @@ -160,7 +161,7 @@ def test_load_config_combine_dicts(default_conf, mocker, caplog) -> None: configsmock = MagicMock(side_effect=config_files) mocker.patch( - 'freqtrade.configuration.configuration.load_config_file', + 'freqtrade.configuration.load_config.load_config_file', configsmock ) @@ -191,7 +192,7 @@ def test_from_config(default_conf, mocker, caplog) -> None: mocker.patch('freqtrade.configuration.configuration.create_datadir', lambda c, x: x) configsmock = MagicMock(side_effect=config_files) - mocker.patch('freqtrade.configuration.configuration.load_config_file', configsmock) + mocker.patch('freqtrade.configuration.load_config.load_config_file', configsmock) validated_conf = Configuration.from_files(['test_conf.json', 'test2_conf.json']) @@ -206,6 +207,33 @@ def test_from_config(default_conf, mocker, caplog) -> None: assert isinstance(validated_conf['user_data_dir'], Path) +def test_from_recursive_files(testdatadir) -> None: + files = testdatadir / "testconfigs/testconfig.json" + + conf = Configuration.from_files([files]) + + assert conf + # Exchange comes from "the first config" + assert conf['exchange'] + # Pricing comes from the 2nd config + assert conf['entry_pricing'] + assert conf['entry_pricing']['price_side'] == "same" + assert conf['exit_pricing'] + # The other key comes from pricing2, which is imported by pricing.json. + # pricing.json is a level higher, therefore wins. + assert conf['exit_pricing']['price_side'] == "same" + + assert len(conf['config_files']) == 4 + assert 'testconfig.json' in conf['config_files'][0] + assert 'test_pricing_conf.json' in conf['config_files'][1] + assert 'test_base_config.json' in conf['config_files'][2] + assert 'test_pricing2_conf.json' in conf['config_files'][3] + + files = testdatadir / "testconfigs/recursive.json" + with pytest.raises(OperationalException, match="Config loop detected."): + load_from_files([files]) + + def test_print_config(default_conf, mocker, caplog) -> None: conf1 = deepcopy(default_conf) # Delete non-json elements from default_conf @@ -214,7 +242,7 @@ def test_print_config(default_conf, mocker, caplog) -> None: configsmock = MagicMock(side_effect=config_files) mocker.patch('freqtrade.configuration.configuration.create_datadir', lambda c, x: x) - mocker.patch('freqtrade.configuration.configuration.load_config_file', configsmock) + mocker.patch('freqtrade.configuration.configuration.load_from_files', configsmock) validated_conf = Configuration.from_files(['test_conf.json']) @@ -772,15 +800,15 @@ def test_set_logfile(default_conf, mocker, tmpdir): def test_load_config_warn_forcebuy(default_conf, mocker, caplog) -> None: - default_conf['forcebuy_enable'] = True + default_conf['force_entry_enable'] = True patched_configuration_load_config_file(mocker, default_conf) args = Arguments(['trade']).get_parsed_arg() configuration = Configuration(args) validated_conf = configuration.load_config() - assert validated_conf.get('forcebuy_enable') - assert log_has('`forcebuy` RPC message enabled.', caplog) + assert validated_conf.get('force_entry_enable') + assert log_has('`force_entry_enable` RPC message enabled.', caplog) def test_validate_default_conf(default_conf) -> None: @@ -868,15 +896,15 @@ def test_validate_tsl(default_conf): def test_validate_edge2(edge_conf): edge_conf.update({ - "use_sell_signal": True, + "use_exit_signal": True, }) # Passes test validate_config_consistency(edge_conf) edge_conf.update({ - "use_sell_signal": False, + "use_exit_signal": False, }) - with pytest.raises(OperationalException, match="Edge requires `use_sell_signal` to be True, " + with pytest.raises(OperationalException, match="Edge requires `use_exit_signal` to be True, " "otherwise no sells will happen."): validate_config_consistency(edge_conf) @@ -977,7 +1005,7 @@ def test__validate_order_types(default_conf, caplog) -> None: assert log_has_re(r"DEPRECATED: Using 'buy' and 'sell' for order_types is.*", caplog) assert conf['order_types']['entry'] == 'limit' assert conf['order_types']['exit'] == 'market' - assert conf['order_types']['forceentry'] == 'limit' + assert conf['order_types']['force_entry'] == 'limit' assert 'buy' not in conf['order_types'] assert 'sell' not in conf['order_types'] assert 'forcebuy' not in conf['order_types'] @@ -1238,14 +1266,8 @@ def test_pairlist_resolving_fallback(mocker): @pytest.mark.parametrize("setting", [ - ("ask_strategy", "use_sell_signal", True, - None, "use_sell_signal", False), - ("ask_strategy", "sell_profit_only", True, - None, "sell_profit_only", False), - ("ask_strategy", "sell_profit_offset", 0.1, - None, "sell_profit_offset", 0.01), - ("ask_strategy", "ignore_roi_if_buy_signal", True, - None, "ignore_roi_if_buy_signal", False), + ("webhook", "webhookbuy", 'testWEbhook', + "webhook", "webhookentry", 'testWEbhook'), ("ask_strategy", "ignore_buying_expired_candle_after", 5, None, "ignore_buying_expired_candle_after", 6), ]) diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index 8de94d249..e19d5f36a 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -21,11 +21,12 @@ from freqtrade.exceptions import (DependencyException, ExchangeError, Insufficie from freqtrade.freqtradebot import FreqtradeBot from freqtrade.persistence import Order, PairLocks, Trade from freqtrade.persistence.models import PairLock +from freqtrade.plugins.protections.iprotection import ProtectionReturn from freqtrade.worker import Worker from tests.conftest import (create_mock_trades, get_patched_freqtradebot, get_patched_worker, log_has, log_has_re, patch_edge, patch_exchange, patch_get_signal, patch_wallet, patch_whitelist) -from tests.conftest_trades import (MOCK_TRADE_COUNT, enter_side, exit_side, mock_order_1, +from tests.conftest_trades import (MOCK_TRADE_COUNT, entry_side, exit_side, mock_order_1, mock_order_2, mock_order_2_sell, mock_order_3, mock_order_3_sell, mock_order_4, mock_order_5_stoploss, mock_order_6_sell) @@ -236,6 +237,8 @@ def test_edge_overrides_stoploss(limit_order, fee, caplog, mocker, assert freqtrade.handle_trade(trade) is not ignore_strat_sl if not ignore_strat_sl: assert log_has_re('Exit for NEO/BTC detected. Reason: stop_loss.*', caplog) + assert trade.exit_reason == ExitType.STOP_LOSS.value + # Test compatibility ... assert trade.sell_reason == ExitType.STOP_LOSS.value @@ -301,7 +304,7 @@ def test_create_trade(default_conf_usdt, ticker_usdt, limit_order, # Simulate fulfilled LIMIT_BUY order for trade oobj = Order.parse_from_ccxt_object( - limit_order[enter_side(is_short)], 'ADA/USDT', enter_side(is_short)) + limit_order[entry_side(is_short)], 'ADA/USDT', entry_side(is_short)) trade.update_trade(oobj) assert trade.open_rate == open_rate @@ -339,7 +342,7 @@ def test_create_trade_minimal_amount( ) -> None: patch_RPCManager(mocker) patch_exchange(mocker) - enter_mock = MagicMock(return_value=limit_order_open[enter_side(is_short)]) + enter_mock = MagicMock(return_value=limit_order_open[entry_side(is_short)]) mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker_usdt, @@ -418,7 +421,7 @@ def test_enter_positions_global_pairlock(default_conf_usdt, ticker_usdt, limit_b assert not log_has_re(message, caplog) caplog.clear() - PairLocks.lock_pair('*', arrow.utcnow().shift(minutes=20).datetime, 'Just because') + PairLocks.lock_pair('*', arrow.utcnow().shift(minutes=20).datetime, 'Just because', side='*') n = freqtrade.enter_positions() assert n == 0 assert log_has_re(message, caplog) @@ -439,9 +442,9 @@ def test_handle_protections(mocker, default_conf_usdt, fee, is_short): freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt) freqtrade.protections._protection_handlers[1].global_stop = MagicMock( - return_value=(True, arrow.utcnow().shift(hours=1).datetime, "asdf")) + return_value=ProtectionReturn(True, arrow.utcnow().shift(hours=1).datetime, "asdf")) create_mock_trades(fee, is_short) - freqtrade.handle_protections('ETC/BTC') + freqtrade.handle_protections('ETC/BTC', '*') send_msg_mock = freqtrade.rpc.send_msg assert send_msg_mock.call_count == 2 assert send_msg_mock.call_args_list[0][0][0]['type'] == RPCMessageType.PROTECTION_TRIGGER @@ -535,8 +538,8 @@ def test_process_trade_creation(default_conf_usdt, ticker_usdt, limit_order, lim mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker_usdt, - create_order=MagicMock(return_value=limit_order_open[enter_side(is_short)]), - fetch_order=MagicMock(return_value=limit_order[enter_side(is_short)]), + create_order=MagicMock(return_value=limit_order_open[entry_side(is_short)]), + fetch_order=MagicMock(return_value=limit_order[entry_side(is_short)]), get_fee=fee, ) freqtrade = FreqtradeBot(default_conf_usdt) @@ -715,12 +718,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), @@ -749,8 +752,8 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order, (10 - (2 / 1)) / (1 - (0.01 + 0.0006)) = 8.085708510208207 """ # TODO: Split this test into multiple tests to improve readability - open_order = limit_order_open[enter_side(is_short)] - order = limit_order[enter_side(is_short)] + open_order = limit_order_open[entry_side(is_short)] + order = limit_order[entry_side(is_short)] default_conf_usdt['trading_mode'] = trading_mode default_conf_usdt['liquidation_buffer'] = liq_buffer leverage = 1.0 if trading_mode == 'spot' else 5.0 @@ -843,6 +846,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' @@ -930,8 +934,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" @@ -944,7 +946,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 @@ -973,7 +974,7 @@ def test_execute_entry_confirm_error(mocker, default_conf_usdt, fee, limit_order 'ask': 2.2, 'last': 1.9 }), - create_order=MagicMock(return_value=limit_order[enter_side(is_short)]), + create_order=MagicMock(return_value=limit_order[entry_side(is_short)]), get_rate=MagicMock(return_value=0.11), get_min_pair_stake_amount=MagicMock(return_value=1), get_fee=fee, @@ -984,11 +985,11 @@ def test_execute_entry_confirm_error(mocker, default_conf_usdt, fee, limit_order freqtrade.strategy.confirm_trade_entry = MagicMock(side_effect=ValueError) assert freqtrade.execute_entry(pair, stake_amount) - limit_order[enter_side(is_short)]['id'] = '222' + limit_order[entry_side(is_short)]['id'] = '222' freqtrade.strategy.confirm_trade_entry = MagicMock(side_effect=Exception) assert freqtrade.execute_entry(pair, stake_amount) - limit_order[enter_side(is_short)]['id'] = '2223' + limit_order[entry_side(is_short)]['id'] = '2223' freqtrade.strategy.confirm_trade_entry = MagicMock(return_value=True) assert freqtrade.execute_entry(pair, stake_amount) @@ -1008,7 +1009,7 @@ def test_execute_entry_min_leverage(mocker, default_conf_usdt, fee, limit_order, 'ask': 2.2, 'last': 1.9 }), - create_order=MagicMock(return_value=limit_order[enter_side(is_short)]), + create_order=MagicMock(return_value=limit_order[entry_side(is_short)]), get_rate=MagicMock(return_value=0.11), # Minimum stake-amount is ~5$ get_maintenance_ratio_and_amt=MagicMock(return_value=(0.0, 0.0)), @@ -1030,7 +1031,7 @@ def test_execute_entry_min_leverage(mocker, default_conf_usdt, fee, limit_order, def test_add_stoploss_on_exchange(mocker, default_conf_usdt, limit_order, is_short) -> None: patch_RPCManager(mocker) patch_exchange(mocker) - order = limit_order[enter_side(is_short)] + order = limit_order[entry_side(is_short)] mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_trade', MagicMock(return_value=True)) mocker.patch('freqtrade.exchange.Exchange.fetch_order', return_value=order) mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=[]) @@ -1060,7 +1061,7 @@ def test_add_stoploss_on_exchange(mocker, default_conf_usdt, limit_order, is_sho def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_short, limit_order) -> None: stoploss = MagicMock(return_value={'id': 13434334}) - enter_order = limit_order[enter_side(is_short)] + enter_order = limit_order[entry_side(is_short)] exit_order = limit_order[exit_side(is_short)] patch_RPCManager(mocker) patch_exchange(mocker) @@ -1208,14 +1209,14 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_ assert freqtrade.handle_stoploss_on_exchange(trade) is False assert trade.stoploss_order_id is None assert trade.is_open is False - assert trade.sell_reason == str(ExitType.EMERGENCY_SELL) + assert trade.exit_reason == str(ExitType.EMERGENCY_EXIT) @pytest.mark.parametrize("is_short", [False, True]) def test_handle_sle_cancel_cant_recreate(mocker, default_conf_usdt, fee, caplog, is_short, limit_order) -> None: # Sixth case: stoploss order was cancelled but couldn't create new one - enter_order = limit_order[enter_side(is_short)] + enter_order = limit_order[entry_side(is_short)] exit_order = limit_order[exit_side(is_short)] patch_RPCManager(mocker) patch_exchange(mocker) @@ -1258,7 +1259,7 @@ def test_handle_sle_cancel_cant_recreate(mocker, default_conf_usdt, fee, caplog, def test_create_stoploss_order_invalid_order( mocker, default_conf_usdt, caplog, fee, is_short, limit_order, limit_order_open ): - open_order = limit_order_open[enter_side(is_short)] + open_order = limit_order_open[entry_side(is_short)] order = limit_order[exit_side(is_short)] rpc_mock = patch_RPCManager(mocker) patch_exchange(mocker) @@ -1291,7 +1292,7 @@ def test_create_stoploss_order_invalid_order( caplog.clear() freqtrade.create_stoploss_order(trade, 200) assert trade.stoploss_order_id is None - assert trade.sell_reason == ExitType.EMERGENCY_SELL.value + assert trade.exit_reason == ExitType.EMERGENCY_EXIT.value assert log_has("Unable to place a stoploss order on exchange. ", caplog) assert log_has("Exiting the trade forcefully", caplog) @@ -1303,7 +1304,7 @@ def test_create_stoploss_order_invalid_order( # Rpc is sending first buy, then sell assert rpc_mock.call_count == 2 - assert rpc_mock.call_args_list[1][0][0]['sell_reason'] == ExitType.EMERGENCY_SELL.value + assert rpc_mock.call_args_list[1][0][0]['sell_reason'] == ExitType.EMERGENCY_EXIT.value assert rpc_mock.call_args_list[1][0][0]['order_type'] == 'market' @@ -1323,7 +1324,7 @@ def test_create_stoploss_order_insufficient_funds( 'last': 1.9 }), create_order=MagicMock(side_effect=[ - limit_order[enter_side(is_short)], + limit_order[entry_side(is_short)], exit_order, ]), get_fee=fee, @@ -1362,7 +1363,7 @@ def test_handle_stoploss_on_exchange_trailing( mocker, default_conf_usdt, fee, is_short, bid, ask, limit_order, stop_price, amt, hang_price ) -> None: # When trailing stoploss is set - enter_order = limit_order[enter_side(is_short)] + enter_order = limit_order[entry_side(is_short)] exit_order = limit_order[exit_side(is_short)] stoploss = MagicMock(return_value={'id': 13434334}) patch_RPCManager(mocker) @@ -1483,7 +1484,7 @@ def test_handle_stoploss_on_exchange_trailing( def test_handle_stoploss_on_exchange_trailing_error( mocker, default_conf_usdt, fee, caplog, limit_order, is_short ) -> None: - enter_order = limit_order[enter_side(is_short)] + enter_order = limit_order[entry_side(is_short)] exit_order = limit_order[exit_side(is_short)] # When trailing stoploss is set stoploss = MagicMock(return_value={'id': 13434334}) @@ -1591,7 +1592,7 @@ def test_stoploss_on_exchange_price_rounding( def test_handle_stoploss_on_exchange_custom_stop( mocker, default_conf_usdt, fee, is_short, limit_order ) -> None: - enter_order = limit_order[enter_side(is_short)] + enter_order = limit_order[entry_side(is_short)] exit_order = limit_order[exit_side(is_short)] # When trailing stoploss is set stoploss = MagicMock(return_value={'id': 13434334}) @@ -1858,10 +1859,10 @@ def test_exit_positions(mocker, default_conf_usdt, limit_order, is_short, caplog mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_trade', MagicMock(return_value=True)) mocker.patch('freqtrade.exchange.Exchange.fetch_order', - return_value=limit_order[enter_side(is_short)]) + return_value=limit_order[entry_side(is_short)]) mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=[]) mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_real_amount', - return_value=limit_order[enter_side(is_short)]['amount']) + return_value=limit_order[entry_side(is_short)]['amount']) trade = MagicMock() trade.is_short = is_short @@ -1884,7 +1885,7 @@ def test_exit_positions(mocker, default_conf_usdt, limit_order, is_short, caplog @pytest.mark.parametrize("is_short", [False, True]) def test_exit_positions_exception(mocker, default_conf_usdt, limit_order, caplog, is_short) -> None: freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt) - order = limit_order[enter_side(is_short)] + order = limit_order[entry_side(is_short)] mocker.patch('freqtrade.exchange.Exchange.fetch_order', return_value=order) trade = MagicMock() @@ -1907,7 +1908,7 @@ def test_exit_positions_exception(mocker, default_conf_usdt, limit_order, caplog @pytest.mark.parametrize("is_short", [False, True]) def test_update_trade_state(mocker, default_conf_usdt, limit_order, is_short, caplog) -> None: freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt) - order = limit_order[enter_side(is_short)] + order = limit_order[entry_side(is_short)] mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_trade', MagicMock(return_value=True)) mocker.patch('freqtrade.exchange.Exchange.fetch_order', return_value=order) @@ -1928,7 +1929,7 @@ def test_update_trade_state(mocker, default_conf_usdt, limit_order, is_short, ca leverage=1, ) trade.orders.append(Order( - ft_order_side=enter_side(is_short), + ft_order_side=entry_side(is_short), price=0.01, order_id=order_id, @@ -1978,7 +1979,7 @@ def test_update_trade_state_withorderdict( default_conf_usdt, trades_for_order, limit_order, fee, mocker, initial_amount, has_rounding_fee, is_short, caplog ): - order = limit_order[enter_side(is_short)] + order = limit_order[entry_side(is_short)] trades_for_order[0]['amount'] = initial_amount order_id = "oid_123456" order['id'] = order_id @@ -2004,7 +2005,7 @@ def test_update_trade_state_withorderdict( ) trade.orders.append( Order( - ft_order_side=enter_side(is_short), + ft_order_side=entry_side(is_short), ft_pair=trade.pair, ft_is_open=True, order_id=order_id, @@ -2024,7 +2025,7 @@ def test_update_trade_state_withorderdict( @pytest.mark.parametrize("is_short", [False, True]) def test_update_trade_state_exception(mocker, default_conf_usdt, is_short, limit_order, caplog) -> None: - order = limit_order[enter_side(is_short)] + order = limit_order[entry_side(is_short)] freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt) mocker.patch('freqtrade.exchange.Exchange.fetch_order', return_value=order) @@ -2105,7 +2106,7 @@ def test_handle_trade( default_conf_usdt, limit_order_open, limit_order, fee, mocker, is_short, close_profit ) -> None: open_order = limit_order_open[exit_side(is_short)] - enter_order = limit_order[enter_side(is_short)] + enter_order = limit_order[entry_side(is_short)] exit_order = limit_order[exit_side(is_short)] patch_RPCManager(mocker) patch_exchange(mocker) @@ -2132,7 +2133,7 @@ def test_handle_trade( assert trade time.sleep(0.01) # Race condition fix - oobj = Order.parse_from_ccxt_object(enter_order, enter_order['symbol'], enter_side(is_short)) + oobj = Order.parse_from_ccxt_object(enter_order, enter_order['symbol'], entry_side(is_short)) trade.update_trade(oobj) assert trade.is_open is True freqtrade.wallets.update() @@ -2150,7 +2151,7 @@ def test_handle_trade( assert trade.close_profit == close_profit assert trade.calc_profit() == 5.685 assert trade.close_date is not None - assert trade.sell_reason == 'sell_signal1' + assert trade.exit_reason == 'sell_signal1' @pytest.mark.parametrize("is_short", [False, True]) @@ -2233,7 +2234,7 @@ def test_handle_overlapping_signals( def test_handle_trade_roi(default_conf_usdt, ticker_usdt, limit_order_open, fee, mocker, caplog, is_short) -> None: - open_order = limit_order_open[enter_side(is_short)] + open_order = limit_order_open[entry_side(is_short)] caplog.set_level(logging.DEBUG) @@ -2266,19 +2267,19 @@ def test_handle_trade_roi(default_conf_usdt, ticker_usdt, limit_order_open, fee, caplog.clear() patch_get_signal(freqtrade) assert freqtrade.handle_trade(trade) - assert log_has("ETH/USDT - Required profit reached. sell_type=ExitType.ROI", + assert log_has("ETH/USDT - Required profit reached. exit_type=ExitType.ROI", caplog) @pytest.mark.parametrize("is_short", [False, True]) -def test_handle_trade_use_sell_signal( +def test_handle_trade_use_exit_signal( default_conf_usdt, ticker_usdt, limit_order_open, fee, mocker, caplog, is_short ) -> None: enter_open_order = limit_order_open[exit_side(is_short)] - exit_open_order = limit_order_open[enter_side(is_short)] + exit_open_order = limit_order_open[entry_side(is_short)] - # use_sell_signal is True buy default + # use_exit_signal is True buy default caplog.set_level(logging.DEBUG) patch_RPCManager(mocker) mocker.patch.multiple( @@ -2308,7 +2309,7 @@ def test_handle_trade_use_sell_signal( else: patch_get_signal(freqtrade, enter_long=False, exit_long=True) assert freqtrade.handle_trade(trade) - assert log_has("ETH/USDT - Sell signal received. sell_type=ExitType.SELL_SIGNAL", + assert log_has("ETH/USDT - Sell signal received. exit_type=ExitType.EXIT_SIGNAL", caplog) @@ -2318,7 +2319,7 @@ def test_close_trade( ) -> None: open_order = limit_order_open[exit_side(is_short)] enter_order = limit_order[exit_side(is_short)] - exit_order = limit_order[enter_side(is_short)] + exit_order = limit_order[entry_side(is_short)] patch_RPCManager(mocker) patch_exchange(mocker) mocker.patch.multiple( @@ -2361,7 +2362,7 @@ def test_bot_loop_start_called_once(mocker, default_conf_usdt, caplog): @pytest.mark.parametrize("is_short", [False, True]) -def test_check_handle_timedout_entry_usercustom( +def test_manage_open_orders_entry_usercustom( default_conf_usdt, ticker_usdt, limit_buy_order_old, open_trade, limit_sell_order_old, fee, mocker, is_short ) -> None: @@ -2393,12 +2394,12 @@ def test_check_handle_timedout_entry_usercustom( Trade.query.session.add(open_trade) # Ensure default is to return empty (so not mocked yet) - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() assert cancel_order_mock.call_count == 0 # Return false - trade remains open freqtrade.strategy.check_entry_timeout = MagicMock(return_value=False) - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() assert cancel_order_mock.call_count == 0 trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all() nb_trades = len(trades) @@ -2406,7 +2407,7 @@ def test_check_handle_timedout_entry_usercustom( assert freqtrade.strategy.check_entry_timeout.call_count == 1 freqtrade.strategy.check_entry_timeout = MagicMock(side_effect=KeyError) - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() assert cancel_order_mock.call_count == 0 trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all() nb_trades = len(trades) @@ -2415,7 +2416,7 @@ def test_check_handle_timedout_entry_usercustom( freqtrade.strategy.check_entry_timeout = MagicMock(return_value=True) # Trade should be closed since the function returns true - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() assert cancel_order_wr_mock.call_count == 1 assert rpc_mock.call_count == 1 trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all() @@ -2425,7 +2426,7 @@ def test_check_handle_timedout_entry_usercustom( @pytest.mark.parametrize("is_short", [False, True]) -def test_check_handle_timedout_entry( +def test_manage_open_orders_entry( default_conf_usdt, ticker_usdt, limit_buy_order_old, open_trade, limit_sell_order_old, fee, mocker, is_short ) -> None: @@ -2449,8 +2450,9 @@ def test_check_handle_timedout_entry( Trade.query.session.add(open_trade) freqtrade.strategy.check_entry_timeout = MagicMock(return_value=False) + freqtrade.strategy.adjust_entry_price = MagicMock(return_value=1234) # check it does cancel buy orders over the time limit - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() assert cancel_order_mock.call_count == 1 assert rpc_mock.call_count == 1 trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all() @@ -2458,6 +2460,99 @@ def test_check_handle_timedout_entry( assert nb_trades == 0 # Custom user buy-timeout is never called assert freqtrade.strategy.check_entry_timeout.call_count == 0 + # Entry adjustment is never called + assert freqtrade.strategy.adjust_entry_price.call_count == 0 + + +@pytest.mark.parametrize("is_short", [False, True]) +def test_adjust_entry_cancel( + default_conf_usdt, ticker_usdt, limit_buy_order_old, open_trade, + limit_sell_order_old, fee, mocker, caplog, is_short +) -> None: + freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt) + old_order = limit_sell_order_old if is_short else limit_buy_order_old + old_order['id'] = open_trade.open_order_id + limit_buy_cancel = deepcopy(old_order) + limit_buy_cancel['status'] = 'canceled' + cancel_order_mock = MagicMock(return_value=limit_buy_cancel) + mocker.patch.multiple( + 'freqtrade.exchange.Exchange', + fetch_ticker=ticker_usdt, + fetch_order=MagicMock(return_value=old_order), + cancel_order_with_result=cancel_order_mock, + get_fee=fee + ) + + open_trade.is_short = is_short + Trade.query.session.add(open_trade) + + # Timeout to not interfere + freqtrade.strategy.ft_check_timed_out = MagicMock(return_value=False) + + # check that order is cancelled + freqtrade.strategy.adjust_entry_price = MagicMock(return_value=None) + freqtrade.manage_open_orders() + trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all() + assert len(trades) == 0 + assert len(Order.query.all()) == 0 + assert log_has_re( + f"{'Sell' if is_short else 'Buy'} order user requested order cancel*", caplog) + assert log_has_re( + f"{'Sell' if is_short else 'Buy'} order fully cancelled.*", caplog) + + # Entry adjustment is called + assert freqtrade.strategy.adjust_entry_price.call_count == 1 + + +@pytest.mark.parametrize("is_short", [False, True]) +def test_adjust_entry_maintain_replace( + default_conf_usdt, ticker_usdt, limit_buy_order_old, open_trade, + limit_sell_order_old, fee, mocker, caplog, is_short +) -> None: + freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt) + old_order = limit_sell_order_old if is_short else limit_buy_order_old + old_order['id'] = open_trade.open_order_id + limit_buy_cancel = deepcopy(old_order) + limit_buy_cancel['status'] = 'canceled' + cancel_order_mock = MagicMock(return_value=limit_buy_cancel) + mocker.patch.multiple( + 'freqtrade.exchange.Exchange', + fetch_ticker=ticker_usdt, + fetch_order=MagicMock(return_value=old_order), + cancel_order_with_result=cancel_order_mock, + get_fee=fee + ) + + open_trade.is_short = is_short + Trade.query.session.add(open_trade) + + # Timeout to not interfere + freqtrade.strategy.ft_check_timed_out = MagicMock(return_value=False) + + # Check that order is maintained + freqtrade.strategy.adjust_entry_price = MagicMock(return_value=old_order['price']) + freqtrade.manage_open_orders() + trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all() + assert len(trades) == 1 + assert len(Order.get_open_orders()) == 1 + # Entry adjustment is called + assert freqtrade.strategy.adjust_entry_price.call_count == 1 + + # Check that order is replaced + freqtrade.get_valid_enter_price_and_stake = MagicMock(return_value={100, 10, 1}) + freqtrade.strategy.adjust_entry_price = MagicMock(return_value=1234) + freqtrade.manage_open_orders() + trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all() + assert len(trades) == 1 + nb_all_orders = len(Order.query.all()) + assert nb_all_orders == 2 + # New order seems to be in closed status? + # nb_open_orders = len(Order.get_open_orders()) + # assert nb_open_orders == 1 + assert log_has_re( + f"{'Sell' if is_short else 'Buy'} order cancelled to be replaced*", caplog) + # Entry adjustment is called + assert freqtrade.strategy.adjust_entry_price.call_count == 1 @pytest.mark.parametrize("is_short", [False, True]) @@ -2483,18 +2578,17 @@ def test_check_handle_cancelled_buy( Trade.query.session.add(open_trade) # check it does cancel buy orders over the time limit - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() assert cancel_order_mock.call_count == 0 assert rpc_mock.call_count == 1 trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all() - nb_trades = len(trades) - assert nb_trades == 0 + assert len(trades) == 0 assert log_has_re( f"{'Sell' if is_short else 'Buy'} order cancelled on exchange for Trade.*", caplog) @pytest.mark.parametrize("is_short", [False, True]) -def test_check_handle_timedout_buy_exception( +def test_manage_open_orders_buy_exception( default_conf_usdt, ticker_usdt, open_trade, is_short, fee, mocker ) -> None: rpc_mock = patch_RPCManager(mocker) @@ -2514,7 +2608,7 @@ def test_check_handle_timedout_buy_exception( Trade.query.session.add(open_trade) # check it does cancel buy orders over the time limit - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() assert cancel_order_mock.call_count == 0 assert rpc_mock.call_count == 0 trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all() @@ -2523,7 +2617,7 @@ def test_check_handle_timedout_buy_exception( @pytest.mark.parametrize("is_short", [False, True]) -def test_check_handle_timedout_exit_usercustom( +def test_manage_open_orders_exit_usercustom( default_conf_usdt, ticker_usdt, limit_sell_order_old, mocker, is_short, open_trade_usdt, caplog ) -> None: @@ -2552,13 +2646,13 @@ def test_check_handle_timedout_exit_usercustom( Trade.query.session.add(open_trade_usdt) # Ensure default is false - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() assert cancel_order_mock.call_count == 0 freqtrade.strategy.check_exit_timeout = MagicMock(return_value=False) freqtrade.strategy.check_entry_timeout = MagicMock(return_value=False) # Return false - No impact - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() assert cancel_order_mock.call_count == 0 assert rpc_mock.call_count == 0 assert open_trade_usdt.is_open is False @@ -2568,7 +2662,7 @@ def test_check_handle_timedout_exit_usercustom( freqtrade.strategy.check_exit_timeout = MagicMock(side_effect=KeyError) freqtrade.strategy.check_entry_timeout = MagicMock(side_effect=KeyError) # Return Error - No impact - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() assert cancel_order_mock.call_count == 0 assert rpc_mock.call_count == 0 assert open_trade_usdt.is_open is False @@ -2578,7 +2672,7 @@ def test_check_handle_timedout_exit_usercustom( # Return True - sells! freqtrade.strategy.check_exit_timeout = MagicMock(return_value=True) freqtrade.strategy.check_entry_timeout = MagicMock(return_value=True) - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() assert cancel_order_mock.call_count == 1 assert rpc_mock.call_count == 1 assert open_trade_usdt.is_open is True @@ -2591,7 +2685,7 @@ def test_check_handle_timedout_exit_usercustom( mocker.patch('freqtrade.persistence.Trade.get_exit_order_count', return_value=1) mocker.patch('freqtrade.freqtradebot.FreqtradeBot.execute_trade_exit', side_effect=DependencyException) - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() assert log_has_re('Unable to emergency sell .*', caplog) et_mock = mocker.patch('freqtrade.freqtradebot.FreqtradeBot.execute_trade_exit') @@ -2601,16 +2695,16 @@ def test_check_handle_timedout_exit_usercustom( # If cancelling fails - no emergency sell! with patch('freqtrade.freqtradebot.FreqtradeBot.handle_cancel_exit', return_value=False): - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() assert et_mock.call_count == 0 - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() assert log_has_re('Emergency exiting trade.*', caplog) assert et_mock.call_count == 1 @pytest.mark.parametrize("is_short", [False, True]) -def test_check_handle_timedout_exit( +def test_manage_open_orders_exit( default_conf_usdt, ticker_usdt, limit_sell_order_old, mocker, is_short, open_trade_usdt ) -> None: rpc_mock = patch_RPCManager(mocker) @@ -2637,7 +2731,7 @@ def test_check_handle_timedout_exit( freqtrade.strategy.check_exit_timeout = MagicMock(return_value=False) freqtrade.strategy.check_entry_timeout = MagicMock(return_value=False) # check it does cancel sell orders over the time limit - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() assert cancel_order_mock.call_count == 1 assert rpc_mock.call_count == 1 assert open_trade_usdt.is_open is True @@ -2673,7 +2767,7 @@ def test_check_handle_cancelled_exit( Trade.query.session.add(open_trade_usdt) # check it does cancel sell orders over the time limit - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() assert cancel_order_mock.call_count == 0 assert rpc_mock.call_count == 1 assert open_trade_usdt.is_open is True @@ -2683,7 +2777,7 @@ def test_check_handle_cancelled_exit( @pytest.mark.parametrize("is_short", [False, True]) @pytest.mark.parametrize("leverage", [1, 3, 5, 10]) -def test_check_handle_timedout_partial( +def test_manage_open_orders_partial( default_conf_usdt, ticker_usdt, limit_buy_order_old_partial, is_short, leverage, open_trade, mocker ) -> None: @@ -2709,7 +2803,7 @@ def test_check_handle_timedout_partial( # check it does cancel buy orders over the time limit # note this is for a partially-complete buy order - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() assert cancel_order_mock.call_count == 1 assert rpc_mock.call_count == 2 trades = Trade.query.filter(Trade.open_order_id.is_(open_trade.open_order_id)).all() @@ -2720,7 +2814,7 @@ def test_check_handle_timedout_partial( @pytest.mark.parametrize("is_short", [False, True]) -def test_check_handle_timedout_partial_fee( +def test_manage_open_orders_partial_fee( default_conf_usdt, ticker_usdt, open_trade, caplog, fee, is_short, limit_buy_order_old_partial, trades_for_order, limit_buy_order_old_partial_canceled, mocker @@ -2752,7 +2846,7 @@ def test_check_handle_timedout_partial_fee( Trade.query.session.add(open_trade) # cancelling a half-filled order should update the amount to the bought amount # and apply fees if necessary. - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() assert log_has_re(r"Applying fee on amount for Trade.*", caplog) @@ -2764,12 +2858,12 @@ def test_check_handle_timedout_partial_fee( assert trades[0].amount == (limit_buy_order_old_partial['amount'] - limit_buy_order_old_partial['remaining']) - 0.023 assert trades[0].open_order_id is None - assert trades[0].fee_updated(open_trade.enter_side) + assert trades[0].fee_updated(open_trade.entry_side) assert pytest.approx(trades[0].fee_open) == 0.001 @pytest.mark.parametrize("is_short", [False, True]) -def test_check_handle_timedout_partial_except( +def test_manage_open_orders_partial_except( default_conf_usdt, ticker_usdt, open_trade, caplog, fee, is_short, limit_buy_order_old_partial, trades_for_order, limit_buy_order_old_partial_canceled, mocker @@ -2800,7 +2894,7 @@ def test_check_handle_timedout_partial_except( Trade.query.session.add(open_trade) # cancelling a half-filled order should update the amount to the bought amount # and apply fees if necessary. - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() assert log_has_re(r"Could not update trade amount: .*", caplog) @@ -2816,8 +2910,8 @@ def test_check_handle_timedout_partial_except( assert trades[0].fee_open == fee() -def test_check_handle_timedout_exception(default_conf_usdt, ticker_usdt, open_trade_usdt, mocker, - caplog) -> None: +def test_manage_open_orders_exception(default_conf_usdt, ticker_usdt, open_trade_usdt, mocker, + caplog) -> None: patch_RPCManager(mocker) patch_exchange(mocker) cancel_order_mock = MagicMock() @@ -2838,7 +2932,7 @@ def test_check_handle_timedout_exception(default_conf_usdt, ticker_usdt, open_tr Trade.query.session.add(open_trade_usdt) caplog.clear() - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() assert log_has_re(r"Cannot query order for Trade\(id=1, pair=ADA/USDT, amount=30.00000000, " r"is_short=False, leverage=1.0, " r"open_rate=2.00000000, open_since=" @@ -2851,8 +2945,8 @@ def test_check_handle_timedout_exception(default_conf_usdt, ticker_usdt, open_tr def test_handle_cancel_enter(mocker, caplog, default_conf_usdt, limit_order, is_short) -> None: patch_RPCManager(mocker) patch_exchange(mocker) - l_order = limit_order[enter_side(is_short)] - cancel_buy_order = deepcopy(limit_order[enter_side(is_short)]) + l_order = limit_order[entry_side(is_short)] + cancel_buy_order = deepcopy(limit_order[entry_side(is_short)]) cancel_buy_order['status'] = 'canceled' del cancel_buy_order['filled'] @@ -2866,7 +2960,7 @@ def test_handle_cancel_enter(mocker, caplog, default_conf_usdt, limit_order, is_ trade.pair = 'LTC/USDT' trade.open_rate = 200 trade.is_short = False - trade.enter_side = "buy" + trade.entry_side = "buy" l_order['filled'] = 0.0 l_order['status'] = 'open' reason = CANCEL_REASON['TIMEOUT'] @@ -2894,7 +2988,7 @@ def test_handle_cancel_enter(mocker, caplog, default_conf_usdt, limit_order, is_ assert log_has_re(r"Order .* for .* not cancelled.", caplog) # min_pair_stake empty should not crash mocker.patch('freqtrade.exchange.Exchange.get_min_pair_stake_amount', return_value=None) - assert not freqtrade.handle_cancel_enter(trade, limit_order[enter_side(is_short)], reason) + assert not freqtrade.handle_cancel_enter(trade, limit_order[entry_side(is_short)], reason) @pytest.mark.parametrize("is_short", [False, True]) @@ -2913,11 +3007,11 @@ def test_handle_cancel_enter_exchanges(mocker, caplog, default_conf_usdt, is_sho reason = CANCEL_REASON['TIMEOUT'] trade = MagicMock() trade.pair = 'LTC/ETH' - trade.enter_side = "sell" if is_short else "buy" + trade.entry_side = "sell" if is_short else "buy" assert freqtrade.handle_cancel_enter(trade, limit_buy_order_canceled_empty, reason) assert cancel_order_mock.call_count == 0 assert log_has_re( - f'{trade.enter_side.capitalize()} order fully cancelled. ' + f'{trade.entry_side.capitalize()} order fully cancelled. ' r'Removing .* from database\.', caplog ) @@ -2935,7 +3029,7 @@ def test_handle_cancel_enter_corder_empty(mocker, default_conf_usdt, limit_order cancelorder) -> None: patch_RPCManager(mocker) patch_exchange(mocker) - l_order = limit_order[enter_side(is_short)] + l_order = limit_order[entry_side(is_short)] cancel_order_mock = MagicMock(return_value=cancelorder) mocker.patch.multiple( 'freqtrade.exchange.Exchange', @@ -2947,9 +3041,9 @@ def test_handle_cancel_enter_corder_empty(mocker, default_conf_usdt, limit_order trade = MagicMock() trade.pair = 'LTC/USDT' - trade.enter_side = "buy" + trade.entry_side = "buy" trade.open_rate = 200 - trade.enter_side = "buy" + trade.entry_side = "buy" l_order['filled'] = 0.0 l_order['status'] = 'open' reason = CANCEL_REASON['TIMEOUT'] @@ -2985,7 +3079,7 @@ def test_handle_cancel_exit_limit(mocker, default_conf_usdt, fee) -> None: fee_close=fee.return_value, close_rate=0.555, close_date=arrow.utcnow().datetime, - sell_reason="sell_reason_whatever", + exit_reason="sell_reason_whatever", ) order = {'remaining': 1, 'amount': 1, @@ -2995,7 +3089,7 @@ def test_handle_cancel_exit_limit(mocker, default_conf_usdt, fee) -> None: assert cancel_order_mock.call_count == 1 assert send_msg_mock.call_count == 1 assert trade.close_rate is None - assert trade.sell_reason is None + assert trade.exit_reason is None send_msg_mock.reset_mock() @@ -3012,7 +3106,7 @@ def test_handle_cancel_exit_limit(mocker, default_conf_usdt, fee) -> None: send_msg_mock.call_args_list[0][0][0]['reason'] = CANCEL_REASON['PARTIALLY_FILLED_KEEP_OPEN'] # Message should not be iterated again - assert trade.sell_order_status == CANCEL_REASON['PARTIALLY_FILLED_KEEP_OPEN'] + assert trade.exit_order_status == CANCEL_REASON['PARTIALLY_FILLED_KEEP_OPEN'] assert send_msg_mock.call_count == 1 @@ -3089,7 +3183,7 @@ def test_execute_trade_exit_up(default_conf_usdt, ticker_usdt, fee, ticker_usdt_ last_msg = rpc_mock.call_args_list[-1][0][0] assert { 'trade_id': 1, - 'type': RPCMessageType.SELL, + 'type': RPCMessageType.EXIT, 'exchange': 'Binance', 'pair': 'ETH/USDT', 'gain': 'profit', @@ -3107,6 +3201,7 @@ def test_execute_trade_exit_up(default_conf_usdt, ticker_usdt, fee, ticker_usdt_ 'stake_currency': 'USDT', 'fiat_currency': 'USD', 'sell_reason': ExitType.ROI.value, + 'exit_reason': ExitType.ROI.value, 'open_date': ANY, 'close_date': ANY, 'close_rate': ANY, @@ -3147,7 +3242,7 @@ def test_execute_trade_exit_down(default_conf_usdt, ticker_usdt, fee, ticker_usd assert rpc_mock.call_count == 2 last_msg = rpc_mock.call_args_list[-1][0][0] assert { - 'type': RPCMessageType.SELL, + 'type': RPCMessageType.EXIT, 'trade_id': 1, 'exchange': 'Binance', 'pair': 'ETH/USDT', @@ -3166,6 +3261,7 @@ def test_execute_trade_exit_down(default_conf_usdt, ticker_usdt, fee, ticker_usd 'stake_currency': 'USDT', 'fiat_currency': 'USD', 'sell_reason': ExitType.STOP_LOSS.value, + 'exit_reason': ExitType.STOP_LOSS.value, 'open_date': ANY, 'close_date': ANY, 'close_rate': ANY, @@ -3217,7 +3313,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.SELL_SIGNAL) + exit_check=ExitCheckTuple(exit_type=ExitType.EXIT_SIGNAL, exit_reason='foo') ) # Sell price must be different to default bid price @@ -3228,7 +3324,7 @@ def test_execute_trade_exit_custom_exit_price( last_msg = rpc_mock.call_args_list[-1][0][0] assert { 'trade_id': 1, - 'type': RPCMessageType.SELL, + 'type': RPCMessageType.EXIT, 'exchange': 'Binance', 'pair': 'ETH/USDT', 'direction': 'Short' if trade.is_short else 'Long', @@ -3245,7 +3341,8 @@ def test_execute_trade_exit_custom_exit_price( 'profit_ratio': profit_ratio, 'stake_currency': 'USDT', 'fiat_currency': 'USD', - 'sell_reason': ExitType.SELL_SIGNAL.value, + 'sell_reason': 'foo', + 'exit_reason': 'foo', 'open_date': ANY, 'close_date': ANY, 'close_rate': ANY, @@ -3294,7 +3391,7 @@ def test_execute_trade_exit_down_stoploss_on_exchange_dry_run( last_msg = rpc_mock.call_args_list[-1][0][0] assert { - 'type': RPCMessageType.SELL, + 'type': RPCMessageType.EXIT, 'trade_id': 1, 'exchange': 'Binance', 'pair': 'ETH/USDT', @@ -3313,6 +3410,7 @@ def test_execute_trade_exit_down_stoploss_on_exchange_dry_run( 'stake_currency': 'USDT', 'fiat_currency': 'USD', 'sell_reason': ExitType.STOP_LOSS.value, + 'exit_reason': ExitType.STOP_LOSS.value, 'open_date': ANY, 'close_date': ANY, 'close_rate': ANY, @@ -3391,7 +3489,7 @@ def test_execute_trade_exit_with_stoploss_on_exchange( assert trade trades = [trade] - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() freqtrade.exit_positions(trades) # Increase the price and sell it @@ -3443,7 +3541,7 @@ def test_may_execute_trade_exit_after_stoploss_on_exchange_hit( # Create some test data freqtrade.enter_positions() - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() trade = Trade.query.first() trades = [trade] assert trade.stoploss_order_id is None @@ -3479,17 +3577,11 @@ def test_may_execute_trade_exit_after_stoploss_on_exchange_hit( freqtrade.exit_positions(trades) assert trade.stoploss_order_id is None assert trade.is_open is False - assert trade.sell_reason == ExitType.STOPLOSS_ON_EXCHANGE.value + assert trade.exit_reason == ExitType.STOPLOSS_ON_EXCHANGE.value assert rpc_mock.call_count == 3 - if is_short: - assert rpc_mock.call_args_list[0][0][0]['type'] == RPCMessageType.SHORT - assert rpc_mock.call_args_list[1][0][0]['type'] == RPCMessageType.SHORT_FILL - assert rpc_mock.call_args_list[2][0][0]['type'] == RPCMessageType.SELL - - else: - assert rpc_mock.call_args_list[0][0][0]['type'] == RPCMessageType.BUY - assert rpc_mock.call_args_list[1][0][0]['type'] == RPCMessageType.BUY_FILL - assert rpc_mock.call_args_list[2][0][0]['type'] == RPCMessageType.SELL + assert rpc_mock.call_args_list[0][0][0]['type'] == RPCMessageType.ENTRY + assert rpc_mock.call_args_list[1][0][0]['type'] == RPCMessageType.ENTRY_FILL + assert rpc_mock.call_args_list[2][0][0]['type'] == RPCMessageType.EXIT @pytest.mark.parametrize( @@ -3557,7 +3649,7 @@ def test_execute_trade_exit_market_order( assert rpc_mock.call_count == 3 last_msg = rpc_mock.call_args_list[-2][0][0] assert { - 'type': RPCMessageType.SELL, + 'type': RPCMessageType.EXIT, 'trade_id': 1, 'exchange': 'Binance', 'pair': 'ETH/USDT', @@ -3576,6 +3668,7 @@ def test_execute_trade_exit_market_order( 'stake_currency': 'USDT', 'fiat_currency': 'USD', 'sell_reason': ExitType.ROI.value, + 'exit_reason': ExitType.ROI.value, 'open_date': ANY, 'close_date': ANY, 'close_rate': ANY, @@ -3621,27 +3714,27 @@ def test_execute_trade_exit_insufficient_funds_error(default_conf_usdt, ticker_u assert mock_insuf.call_count == 1 -@pytest.mark.parametrize('profit_only,bid,ask,handle_first,handle_second,sell_type,is_short', [ +@pytest.mark.parametrize('profit_only,bid,ask,handle_first,handle_second,exit_type,is_short', [ # Enable profit - (True, 2.18, 2.2, False, True, ExitType.SELL_SIGNAL.value, False), - (True, 2.18, 2.2, False, True, ExitType.SELL_SIGNAL.value, True), + (True, 2.18, 2.2, False, True, ExitType.EXIT_SIGNAL.value, False), + (True, 2.18, 2.2, False, True, ExitType.EXIT_SIGNAL.value, True), # # Disable profit - (False, 3.19, 3.2, True, False, ExitType.SELL_SIGNAL.value, False), - (False, 3.19, 3.2, True, False, ExitType.SELL_SIGNAL.value, True), + (False, 3.19, 3.2, True, False, ExitType.EXIT_SIGNAL.value, False), + (False, 3.19, 3.2, True, False, ExitType.EXIT_SIGNAL.value, True), # # Enable loss # # * Shouldn't this be ExitType.STOP_LOSS.value (True, 0.21, 0.22, False, False, None, False), (True, 2.41, 2.42, False, False, None, True), # Disable loss - (False, 0.10, 0.22, True, False, ExitType.SELL_SIGNAL.value, False), - (False, 0.10, 0.22, True, False, ExitType.SELL_SIGNAL.value, True), + (False, 0.10, 0.22, True, False, ExitType.EXIT_SIGNAL.value, False), + (False, 0.10, 0.22, True, False, ExitType.EXIT_SIGNAL.value, True), ]) -def test_sell_profit_only( +def test_exit_profit_only( default_conf_usdt, limit_order, limit_order_open, is_short, - fee, mocker, profit_only, bid, ask, handle_first, handle_second, sell_type) -> None: + fee, mocker, profit_only, bid, ask, handle_first, handle_second, exit_type) -> None: patch_RPCManager(mocker) patch_exchange(mocker) - eside = enter_side(is_short) + eside = entry_side(is_short) mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=MagicMock(return_value={ @@ -3656,13 +3749,14 @@ def test_sell_profit_only( get_fee=fee, ) default_conf_usdt.update({ - 'use_sell_signal': True, - 'sell_profit_only': profit_only, - 'sell_profit_offset': 0.1, + 'use_exit_signal': True, + 'exit_profit_only': profit_only, + 'exit_profit_offset': 0.1, }) freqtrade = FreqtradeBot(default_conf_usdt) patch_get_signal(freqtrade, enter_short=is_short, enter_long=not is_short) - if sell_type == ExitType.SELL_SIGNAL.value: + freqtrade.strategy.custom_exit = MagicMock(return_value=None) + if exit_type == ExitType.EXIT_SIGNAL.value: freqtrade.strategy.min_roi_reached = MagicMock(return_value=False) else: freqtrade.strategy.stop_loss_reached = MagicMock(return_value=ExitCheckTuple( @@ -3670,15 +3764,20 @@ def test_sell_profit_only( freqtrade.enter_positions() trade = Trade.query.first() - trade.is_short = is_short + assert trade.is_short == is_short oobj = Order.parse_from_ccxt_object(limit_order[eside], limit_order[eside]['symbol'], eside) trade.update_trade(oobj) freqtrade.wallets.update() + if profit_only: + assert freqtrade.handle_trade(trade) is False + # Custom-exit is called + freqtrade.strategy.custom_exit.call_count == 1 + patch_get_signal(freqtrade, enter_long=False, exit_short=is_short, exit_long=not is_short) assert freqtrade.handle_trade(trade) is handle_first if handle_second: - freqtrade.strategy.sell_profit_offset = 0.0 + freqtrade.strategy.exit_profit_offset = 0.0 assert freqtrade.handle_trade(trade) is True @@ -3788,21 +3887,24 @@ def test_locked_pairs(default_conf_usdt, ticker_usdt, fee, exit_check=ExitCheckTuple(exit_type=ExitType.STOP_LOSS) ) trade.close(ticker_usdt_sell_down()['bid']) - assert freqtrade.strategy.is_pair_locked(trade.pair) + assert freqtrade.strategy.is_pair_locked(trade.pair, side='*') + # Boths sides are locked + assert freqtrade.strategy.is_pair_locked(trade.pair, side='long') + assert freqtrade.strategy.is_pair_locked(trade.pair, side='short') # reinit - should buy other pair. caplog.clear() freqtrade.enter_positions() - assert log_has_re(f"Pair {trade.pair} is still locked.*", caplog) + assert log_has_re(fr"Pair {trade.pair} \* is locked.*", caplog) @pytest.mark.parametrize("is_short", [False, True]) -def test_ignore_roi_if_buy_signal(default_conf_usdt, limit_order, limit_order_open, is_short, - fee, mocker) -> None: +def test_ignore_roi_if_entry_signal(default_conf_usdt, limit_order, limit_order_open, is_short, + fee, mocker) -> None: patch_RPCManager(mocker) patch_exchange(mocker) - eside = enter_side(is_short) + eside = entry_side(is_short) mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=MagicMock(return_value={ @@ -3816,7 +3918,7 @@ def test_ignore_roi_if_buy_signal(default_conf_usdt, limit_order, limit_order_op ]), get_fee=fee, ) - default_conf_usdt['ignore_roi_if_buy_signal'] = True + default_conf_usdt['ignore_roi_if_entry_signal'] = True freqtrade = FreqtradeBot(default_conf_usdt) patch_get_signal(freqtrade, enter_short=is_short, enter_long=not is_short) @@ -3843,7 +3945,7 @@ def test_ignore_roi_if_buy_signal(default_conf_usdt, limit_order, limit_order_op else: patch_get_signal(freqtrade, enter_long=False, exit_long=False) assert freqtrade.handle_trade(trade) is True - assert trade.sell_reason == ExitType.ROI.value + assert trade.exit_reason == ExitType.ROI.value @pytest.mark.parametrize("is_short,val1,val2", [ @@ -3862,7 +3964,7 @@ def test_trailing_stop_loss(default_conf_usdt, limit_order_open, 'last': 2.0 }), create_order=MagicMock(side_effect=[ - limit_order_open[enter_side(is_short)], + limit_order_open[entry_side(is_short)], {'id': 1234553382}, ]), get_fee=fee, @@ -3905,7 +4007,7 @@ def test_trailing_stop_loss(default_conf_usdt, limit_order_open, f"stoploss is {(2.0 * val1 * stop_multi):6f}, " f"initial stoploss was at {(2.0 * stop_multi):6f}, trade opened at 2.000000", caplog) - assert trade.sell_reason == ExitType.TRAILING_STOP_LOSS.value + assert trade.exit_reason == ExitType.TRAILING_STOP_LOSS.value @pytest.mark.parametrize('offset,trail_if_reached,second_sl,is_short', [ @@ -3920,10 +4022,10 @@ def test_trailing_stop_loss_positive( default_conf_usdt, limit_order, limit_order_open, offset, fee, caplog, mocker, trail_if_reached, second_sl, is_short ) -> None: - enter_price = limit_order[enter_side(is_short)]['price'] + enter_price = limit_order[entry_side(is_short)]['price'] patch_RPCManager(mocker) patch_exchange(mocker) - eside = enter_side(is_short) + eside = entry_side(is_short) mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=MagicMock(return_value={ @@ -4011,15 +4113,15 @@ def test_trailing_stop_loss_positive( f"initial stoploss was at {'2.42' if is_short else '1.80'}0000, " f"trade opened at {2.2 if is_short else 2.0}00000", caplog) - assert trade.sell_reason == ExitType.TRAILING_STOP_LOSS.value + assert trade.exit_reason == ExitType.TRAILING_STOP_LOSS.value @pytest.mark.parametrize("is_short", [False, True]) -def test_disable_ignore_roi_if_buy_signal(default_conf_usdt, limit_order, limit_order_open, - is_short, fee, mocker) -> None: +def test_disable_ignore_roi_if_entry_signal(default_conf_usdt, limit_order, limit_order_open, + is_short, fee, mocker) -> None: patch_RPCManager(mocker) patch_exchange(mocker) - eside = enter_side(is_short) + eside = entry_side(is_short) mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=MagicMock(return_value={ @@ -4036,7 +4138,7 @@ def test_disable_ignore_roi_if_buy_signal(default_conf_usdt, limit_order, limit_ _is_dry_limit_order_filled=MagicMock(return_value=False), ) default_conf_usdt['exit_pricing'] = { - 'ignore_roi_if_buy_signal': False + 'ignore_roi_if_entry_signal': False } freqtrade = FreqtradeBot(default_conf_usdt) patch_get_signal(freqtrade, enter_short=is_short, enter_long=not is_short) @@ -4057,7 +4159,7 @@ def test_disable_ignore_roi_if_buy_signal(default_conf_usdt, limit_order, limit_ # Test if entry-signal is absent patch_get_signal(freqtrade) assert freqtrade.handle_trade(trade) is True - assert trade.sell_reason == ExitType.ROI.value + assert trade.exit_reason == ExitType.ROI.value def test_get_real_amount_quote(default_conf_usdt, trades_for_order, buy_order_fee, fee, caplog, @@ -4423,7 +4525,7 @@ def test_order_book_depth_of_market( mocker.patch.multiple( 'freqtrade.exchange.Exchange', fetch_ticker=ticker_usdt, - create_order=MagicMock(return_value=limit_order_open[enter_side(is_short)]), + create_order=MagicMock(return_value=limit_order_open[entry_side(is_short)]), get_fee=fee, ) @@ -4448,7 +4550,7 @@ def test_order_book_depth_of_market( # Simulate fulfilled LIMIT_BUY order for trade oobj = Order.parse_from_ccxt_object( - limit_order_open[enter_side(is_short)], 'ADA/USDT', enter_side(is_short)) + limit_order_open[entry_side(is_short)], 'ADA/USDT', entry_side(is_short)) trade.update_trade(oobj) assert trade.open_rate == ticker_usdt.return_value[ticker_side] @@ -4637,7 +4739,7 @@ def test_cancel_all_open_orders(mocker, default_conf_usdt, fee, limit_order, lim side_effect=[ ExchangeError(), limit_order[exit_side(is_short)], - limit_order_open[enter_side(is_short)], + limit_order_open[entry_side(is_short)], limit_order_open[exit_side(is_short)], ] ) @@ -4750,7 +4852,7 @@ def test_update_closed_trades_without_assigned_fees(mocker, default_conf_usdt, f for trade in trades: if trade.is_open: # Exclude Trade 4 - as the order is still open. - if trade.select_order(enter_side(is_short), False): + if trade.select_order(entry_side(is_short), False): assert trade.fee_open_cost is not None assert trade.fee_open_currency is not None else: @@ -5007,7 +5109,7 @@ def test_update_funding_fees( # SETUP time_machine.move_to("2021-09-01 00:00:00 +00:00") - open_order = limit_order_open[enter_side(is_short)] + open_order = limit_order_open[entry_side(is_short)] open_exit_order = limit_order_open[exit_side(is_short)] bid = 0.11 enter_rate_mock = MagicMock(return_value=bid) @@ -5205,7 +5307,7 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None: assert trade.stake_amount == 110 assert not trade.fee_updated('buy') - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() trade = Trade.query.first() assert trade @@ -5311,7 +5413,7 @@ def test_position_adjust(mocker, default_conf_usdt, fee) -> None: MagicMock(return_value=closed_dca_order_1)) mocker.patch('freqtrade.exchange.Exchange.fetch_order_or_stoploss_order', MagicMock(return_value=closed_dca_order_1)) - freqtrade.check_handle_timedout() + freqtrade.manage_open_orders() # Assert trade is as expected (averaged dca) trade = Trade.query.first() diff --git a/tests/test_integration.py b/tests/test_integration.py index d1fac3d71..d2ad8c981 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -53,7 +53,7 @@ def test_may_execute_exit_stoploss_on_exchange_multi(default_conf, ticker, fee, # Sell 3rd trade (not called for the first trade) should_sell_mock = MagicMock(side_effect=[ ExitCheckTuple(exit_type=ExitType.NONE), - ExitCheckTuple(exit_type=ExitType.SELL_SIGNAL)] + ExitCheckTuple(exit_type=ExitType.EXIT_SIGNAL)] ) cancel_order_mock = MagicMock() mocker.patch('freqtrade.exchange.Binance.stoploss', stoploss) @@ -115,15 +115,15 @@ def test_may_execute_exit_stoploss_on_exchange_multi(default_conf, ticker, fee, assert wallets_mock.call_count == 4 trade = trades[0] - assert trade.sell_reason == ExitType.STOPLOSS_ON_EXCHANGE.value + assert trade.exit_reason == ExitType.STOPLOSS_ON_EXCHANGE.value assert not trade.is_open trade = trades[1] - assert not trade.sell_reason + assert not trade.exit_reason assert trade.is_open trade = trades[2] - assert trade.sell_reason == ExitType.SELL_SIGNAL.value + assert trade.exit_reason == ExitType.EXIT_SIGNAL.value assert not trade.is_open @@ -139,7 +139,7 @@ def test_forcebuy_last_unlimited(default_conf, ticker, fee, mocker, balance_rati one trade was sold at a loss. """ default_conf['max_open_trades'] = 5 - default_conf['forcebuy_enable'] = True + default_conf['force_entry_enable'] = True default_conf['stake_amount'] = 'unlimited' default_conf['tradable_balance_ratio'] = balance_ratio default_conf['dry_run_wallet'] = 1000 @@ -161,7 +161,7 @@ def test_forcebuy_last_unlimited(default_conf, ticker, fee, mocker, balance_rati ) should_sell_mock = MagicMock(side_effect=[ ExitCheckTuple(exit_type=ExitType.NONE), - ExitCheckTuple(exit_type=ExitType.SELL_SIGNAL), + ExitCheckTuple(exit_type=ExitType.EXIT_SIGNAL), ExitCheckTuple(exit_type=ExitType.NONE), ExitCheckTuple(exit_type=ExitType.NONE), ExitCheckTuple(exit_type=ExitType.NONE)] @@ -351,3 +351,107 @@ def test_dca_short(default_conf_usdt, ticker_usdt, fee, mocker) -> None: assert trade.nr_of_successful_entries == 2 assert trade.nr_of_successful_exits == 1 + + +def test_dca_order_adjust(default_conf_usdt, ticker_usdt, fee, mocker) -> None: + default_conf_usdt['position_adjustment_enable'] = True + + freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt) + mocker.patch.multiple( + 'freqtrade.exchange.Exchange', + fetch_ticker=ticker_usdt, + get_fee=fee, + amount_to_precision=lambda s, x, y: y, + price_to_precision=lambda s, x, y: y, + ) + mocker.patch('freqtrade.exchange.Exchange._is_dry_limit_order_filled', return_value=False) + + patch_get_signal(freqtrade) + freqtrade.strategy.custom_entry_price = lambda **kwargs: ticker_usdt['ask'] * 0.96 + + freqtrade.enter_positions() + + assert len(Trade.get_trades().all()) == 1 + trade: Trade = Trade.get_trades().first() + assert len(trade.orders) == 1 + assert trade.open_order_id is not None + assert pytest.approx(trade.stake_amount) == 60 + assert trade.open_rate == 1.96 + assert trade.stop_loss_pct is None + assert trade.stop_loss == 0.0 + assert trade.initial_stop_loss == 0.0 + assert trade.initial_stop_loss_pct is None + # No adjustment + freqtrade.process() + trade = Trade.get_trades().first() + assert len(trade.orders) == 1 + assert trade.open_order_id is not None + assert pytest.approx(trade.stake_amount) == 60 + + # Cancel order and place new one + freqtrade.strategy.adjust_entry_price = MagicMock(return_value=1.99) + freqtrade.process() + trade = Trade.get_trades().first() + assert len(trade.orders) == 2 + assert trade.open_order_id is not None + # Open rate is not adjusted yet + assert trade.open_rate == 1.96 + assert trade.stop_loss_pct is None + assert trade.stop_loss == 0.0 + assert trade.initial_stop_loss == 0.0 + assert trade.initial_stop_loss_pct is None + + # Fill order + mocker.patch('freqtrade.exchange.Exchange._is_dry_limit_order_filled', return_value=True) + freqtrade.process() + trade = Trade.get_trades().first() + assert len(trade.orders) == 2 + assert trade.open_order_id is None + # Open rate is not adjusted yet + assert trade.open_rate == 1.99 + assert trade.stop_loss_pct == -0.1 + assert trade.stop_loss == 1.99 * 0.9 + assert trade.initial_stop_loss == 1.99 * 0.9 + assert trade.initial_stop_loss_pct == -0.1 + + # 2nd order - not filling + freqtrade.strategy.adjust_trade_position = MagicMock(return_value=120) + mocker.patch('freqtrade.exchange.Exchange._is_dry_limit_order_filled', return_value=False) + + freqtrade.process() + trade = Trade.get_trades().first() + assert len(trade.orders) == 3 + assert trade.open_order_id is not None + assert trade.open_rate == 1.99 + assert trade.orders[-1].price == 1.96 + assert trade.orders[-1].cost == 120 + + # Replace new order with diff. order at a lower price + freqtrade.strategy.adjust_entry_price = MagicMock(return_value=1.95) + + freqtrade.process() + trade = Trade.get_trades().first() + assert len(trade.orders) == 4 + assert trade.open_order_id is not None + assert trade.open_rate == 1.99 + assert trade.orders[-1].price == 1.95 + assert pytest.approx(trade.orders[-1].cost) == 120 + + # Fill DCA order + freqtrade.strategy.adjust_trade_position = MagicMock(return_value=None) + mocker.patch('freqtrade.exchange.Exchange._is_dry_limit_order_filled', return_value=True) + freqtrade.strategy.adjust_entry_price = MagicMock(side_effect=ValueError) + + freqtrade.process() + trade = Trade.get_trades().first() + assert len(trade.orders) == 4 + assert trade.open_order_id is None + assert pytest.approx(trade.open_rate) == 1.963153456 + assert trade.orders[-1].price == 1.95 + assert pytest.approx(trade.orders[-1].cost) == 120 + assert trade.orders[-1].status == 'closed' + + assert pytest.approx(trade.amount) == 91.689215 + # Check the 2 filled orders equal the above amount + assert pytest.approx(trade.orders[1].amount) == 30.150753768 + assert pytest.approx(trade.orders[-1].amount) == 61.538461232 diff --git a/tests/test_persistence.py b/tests/test_persistence.py index 61aaf0fb7..d84415938 100644 --- a/tests/test_persistence.py +++ b/tests/test_persistence.py @@ -15,6 +15,7 @@ from freqtrade.enums import TradingMode from freqtrade.exceptions import DependencyException, OperationalException from freqtrade.persistence import LocalTrade, Order, Trade, clean_dry_run_db, init_db from freqtrade.persistence.migrations import get_last_sequence_ids, set_sequence_ids +from freqtrade.persistence.models import PairLock from tests.conftest import create_mock_trades, create_mock_trades_with_leverage, log_has, log_has_re @@ -76,7 +77,7 @@ def test_init_dryrun_db(default_conf, tmpdir): @pytest.mark.parametrize('is_short', [False, True]) @pytest.mark.usefixtures("init_persistence") def test_enter_exit_side(fee, is_short): - enter_side, exit_side = ("sell", "buy") if is_short else ("buy", "sell") + entry_side, exit_side = ("sell", "buy") if is_short else ("buy", "sell") trade = Trade( id=2, pair='ADA/USDT', @@ -92,7 +93,7 @@ def test_enter_exit_side(fee, is_short): leverage=2.0, trading_mode=margin ) - assert trade.enter_side == enter_side + assert trade.entry_side == entry_side assert trade.exit_side == exit_side assert trade.trade_direction == 'short' if is_short else 'long' @@ -119,7 +120,7 @@ def test_set_stop_loss_isolated_liq(fee): assert trade.stop_loss is None assert trade.initial_stop_loss is None - trade._set_stop_loss(0.1, (1.0/9.0)) + trade._set_stop_loss(0.1, (1.0 / 9.0)) assert trade.liquidation_price == 0.09 assert trade.stop_loss == 0.1 assert trade.initial_stop_loss == 0.1 @@ -160,7 +161,7 @@ def test_set_stop_loss_isolated_liq(fee): assert trade.stop_loss is None assert trade.initial_stop_loss is None - trade._set_stop_loss(0.08, (1.0/9.0)) + trade._set_stop_loss(0.08, (1.0 / 9.0)) assert trade.liquidation_price == 0.09 assert trade.stop_loss == 0.08 assert trade.initial_stop_loss == 0.08 @@ -171,13 +172,13 @@ def test_set_stop_loss_isolated_liq(fee): assert trade.initial_stop_loss == 0.08 trade.set_isolated_liq(0.07) - trade._set_stop_loss(0.1, (1.0/8.0)) + trade._set_stop_loss(0.1, (1.0 / 8.0)) assert trade.liquidation_price == 0.07 assert trade.stop_loss == 0.07 assert trade.initial_stop_loss == 0.08 # Stop doesn't move stop higher - trade._set_stop_loss(0.1, (1.0/9.0)) + trade._set_stop_loss(0.1, (1.0 / 9.0)) assert trade.liquidation_price == 0.07 assert trade.stop_loss == 0.07 assert trade.initial_stop_loss == 0.08 @@ -456,7 +457,7 @@ def test_update_limit_order(fee, caplog, limit_buy_order_usdt, limit_sell_order_ enter_order = limit_sell_order_usdt if is_short else limit_buy_order_usdt exit_order = limit_buy_order_usdt if is_short else limit_sell_order_usdt - enter_side, exit_side = ("sell", "buy") if is_short else ("buy", "sell") + entry_side, exit_side = ("sell", "buy") if is_short else ("buy", "sell") trade = Trade( id=2, @@ -479,13 +480,13 @@ def test_update_limit_order(fee, caplog, limit_buy_order_usdt, limit_sell_order_ assert trade.close_date is None trade.open_order_id = 'something' - oobj = Order.parse_from_ccxt_object(enter_order, 'ADA/USDT', enter_side) + oobj = Order.parse_from_ccxt_object(enter_order, 'ADA/USDT', entry_side) trade.update_trade(oobj) assert trade.open_order_id is None assert trade.open_rate == open_rate assert trade.close_profit is None assert trade.close_date is None - assert log_has_re(f"LIMIT_{enter_side.upper()} has been fulfilled for " + assert log_has_re(f"LIMIT_{entry_side.upper()} has been fulfilled for " r"Trade\(id=2, pair=ADA/USDT, amount=30.00000000, " f"is_short={is_short}, leverage={lev}, open_rate={open_rate}0000000, " r"open_since=.*\).", @@ -1209,6 +1210,27 @@ def test_migrate_new(mocker, default_conf, fee, caplog): PRIMARY KEY (id), CHECK (is_open IN (0, 1)) );""" + create_table_order = """CREATE TABLE orders ( + id INTEGER NOT NULL, + ft_trade_id INTEGER, + ft_order_side VARCHAR(25) NOT NULL, + ft_pair VARCHAR(25) NOT NULL, + ft_is_open BOOLEAN NOT NULL, + order_id VARCHAR(255) NOT NULL, + status VARCHAR(255), + symbol VARCHAR(25), + order_type VARCHAR(50), + side VARCHAR(25), + price FLOAT, + amount FLOAT, + filled FLOAT, + remaining FLOAT, + cost FLOAT, + order_date DATETIME, + order_filled_date DATETIME, + order_update_date DATETIME, + PRIMARY KEY (id) + );""" insert_table_old = """INSERT INTO trades (exchange, pair, is_open, fee, open_rate, stake_amount, amount, open_date, stop_loss, initial_stop_loss, max_rate, ticker_interval, @@ -1222,15 +1244,66 @@ def test_migrate_new(mocker, default_conf, fee, caplog): stake=default_conf.get("stake_amount"), amount=amount ) + insert_orders = f""" + insert into orders ( + ft_trade_id, + ft_order_side, + ft_pair, + ft_is_open, + order_id, + status, + symbol, + order_type, + side, + price, + amount, + filled, + remaining, + cost) + values ( + 1, + 'buy', + 'ETC/BTC', + 0, + 'buy_order', + 'closed', + 'ETC/BTC', + 'limit', + 'buy', + 0.00258580, + {amount}, + {amount}, + 0, + {amount * 0.00258580} + ), + ( + 1, + 'stoploss', + 'ETC/BTC', + 0, + 'stop_order_id222', + 'closed', + 'ETC/BTC', + 'limit', + 'sell', + 0.00258580, + {amount}, + {amount}, + 0, + {amount * 0.00258580} + ) + """ engine = create_engine('sqlite://') mocker.patch('freqtrade.persistence.models.create_engine', lambda *args, **kwargs: engine) # Create table using the old format with engine.begin() as connection: connection.execute(text(create_table_old)) + connection.execute(text(create_table_order)) connection.execute(text("create index ix_trades_is_open on trades(is_open)")) connection.execute(text("create index ix_trades_pair on trades(pair)")) connection.execute(text(insert_table_old)) + connection.execute(text(insert_orders)) # fake previous backup connection.execute(text("create table trades_bak as select * from trades")) @@ -1255,7 +1328,7 @@ def test_migrate_new(mocker, default_conf, fee, caplog): assert trade.min_rate is None assert trade.stop_loss == 0.0 assert trade.initial_stop_loss == 0.0 - assert trade.sell_reason is None + assert trade.exit_reason is None assert trade.strategy is None assert trade.timeframe == '5m' assert trade.stoploss_order_id == 'stop_order_id222' @@ -1267,8 +1340,7 @@ def test_migrate_new(mocker, default_conf, fee, caplog): assert trade.open_trade_value == trade._calc_open_trade_value() assert trade.close_profit_abs is None - assert log_has("Moving open orders to Orders table.", caplog) - orders = Order.query.all() + orders = trade.orders assert len(orders) == 2 assert orders[0].order_id == 'buy_order' assert orders[0].ft_order_side == 'buy' @@ -1277,7 +1349,7 @@ def test_migrate_new(mocker, default_conf, fee, caplog): assert orders[1].ft_order_side == 'stoploss' -def test_migrate_mid_state(mocker, default_conf, fee, caplog): +def test_migrate_too_old(mocker, default_conf, fee, caplog): """ Test Database migration (starting with new pairformat) """ @@ -1301,6 +1373,7 @@ def test_migrate_mid_state(mocker, default_conf, fee, caplog): PRIMARY KEY (id), CHECK (is_open IN (0, 1)) );""" + insert_table_old = """INSERT INTO trades (exchange, pair, is_open, fee_open, fee_close, open_rate, stake_amount, amount, open_date) VALUES ('binance', 'ETC/BTC', 1, {fee}, {fee}, @@ -1319,26 +1392,8 @@ def test_migrate_mid_state(mocker, default_conf, fee, caplog): connection.execute(text(insert_table_old)) # Run init to test migration - init_db(default_conf['db_url'], default_conf['dry_run']) - - assert len(Trade.query.filter(Trade.id == 1).all()) == 1 - trade = Trade.query.filter(Trade.id == 1).first() - assert trade.fee_open == fee.return_value - assert trade.fee_close == fee.return_value - assert trade.open_rate_requested is None - assert trade.close_rate_requested is None - assert trade.is_open == 1 - assert trade.amount == amount - assert trade.stake_amount == default_conf.get("stake_amount") - assert trade.pair == "ETC/BTC" - assert trade.exchange == "binance" - assert trade.max_rate == 0.0 - assert trade.stop_loss == 0.0 - assert trade.initial_stop_loss == 0.0 - assert trade.open_trade_value == trade._calc_open_trade_value() - assert log_has("trying trades_bak0", caplog) - assert log_has("Running database migration for trades - backup: trades_bak0, orders_bak0", - caplog) + with pytest.raises(OperationalException, match=r'Your database seems to be very old'): + init_db(default_conf['db_url'], default_conf['dry_run']) def test_migrate_get_last_sequence_ids(): @@ -1361,18 +1416,67 @@ def test_migrate_set_sequence_ids(): engine = MagicMock() engine.begin = MagicMock() engine.name = 'postgresql' - set_sequence_ids(engine, 22, 55) + set_sequence_ids(engine, 22, 55, 5) assert engine.begin.call_count == 1 engine.reset_mock() engine.begin.reset_mock() engine.name = 'somethingelse' - set_sequence_ids(engine, 22, 55) + set_sequence_ids(engine, 22, 55, 6) assert engine.begin.call_count == 0 +def test_migrate_pairlocks(mocker, default_conf, fee, caplog): + """ + Test Database migration (starting with new pairformat) + """ + caplog.set_level(logging.DEBUG) + # Always create all columns apart from the last! + create_table_old = """CREATE TABLE pairlocks ( + id INTEGER NOT NULL, + pair VARCHAR(25) NOT NULL, + reason VARCHAR(255), + lock_time DATETIME NOT NULL, + lock_end_time DATETIME NOT NULL, + active BOOLEAN NOT NULL, + PRIMARY KEY (id) + ) + """ + create_index1 = "CREATE INDEX ix_pairlocks_pair ON pairlocks (pair)" + create_index2 = "CREATE INDEX ix_pairlocks_lock_end_time ON pairlocks (lock_end_time)" + create_index3 = "CREATE INDEX ix_pairlocks_active ON pairlocks (active)" + insert_table_old = """INSERT INTO pairlocks ( + id, pair, reason, lock_time, lock_end_time, active) + VALUES (1, 'ETH/BTC', 'Auto lock', '2021-07-12 18:41:03', '2021-07-11 18:45:00', 1) + """ + insert_table_old2 = """INSERT INTO pairlocks ( + id, pair, reason, lock_time, lock_end_time, active) + VALUES (2, '*', 'Lock all', '2021-07-12 18:41:03', '2021-07-12 19:00:00', 1) + """ + engine = create_engine('sqlite://') + mocker.patch('freqtrade.persistence.models.create_engine', lambda *args, **kwargs: engine) + # Create table using the old format + with engine.begin() as connection: + connection.execute(text(create_table_old)) + + connection.execute(text(insert_table_old)) + connection.execute(text(insert_table_old2)) + connection.execute(text(create_index1)) + connection.execute(text(create_index2)) + connection.execute(text(create_index3)) + + init_db(default_conf['db_url'], default_conf['dry_run']) + + assert len(PairLock.query.all()) == 2 + assert len(PairLock.query.filter(PairLock.pair == '*').all()) == 1 + pairlocks = PairLock.query.filter(PairLock.pair == 'ETH/BTC').all() + assert len(pairlocks) == 1 + pairlocks[0].pair == 'ETH/BTC' + pairlocks[0].side == '*' + + def test_adjust_stop_loss(fee): trade = Trade( pair='ADA/USDT', @@ -1561,6 +1665,8 @@ def test_to_json(fee): assert result == {'trade_id': None, 'pair': 'ADA/USDT', + 'base_currency': 'ADA', + 'quote_currency': 'USDT', 'is_open': None, 'open_date': trade.open_date.strftime("%Y-%m-%d %H:%M:%S"), 'open_timestamp': int(trade.open_date.timestamp() * 1000), @@ -1590,7 +1696,8 @@ def test_to_json(fee): 'profit_pct': None, 'profit_abs': None, 'sell_reason': None, - 'sell_order_status': None, + 'exit_reason': None, + 'exit_order_status': None, 'stop_loss_abs': None, 'stop_loss_ratio': None, 'stop_loss_pct': None, @@ -1636,6 +1743,8 @@ def test_to_json(fee): assert result == {'trade_id': None, 'pair': 'XRP/BTC', + 'base_currency': 'XRP', + 'quote_currency': 'BTC', 'open_date': trade.open_date.strftime("%Y-%m-%d %H:%M:%S"), 'open_timestamp': int(trade.open_date.timestamp() * 1000), 'close_date': trade.close_date.strftime("%Y-%m-%d %H:%M:%S"), @@ -1676,7 +1785,8 @@ def test_to_json(fee): 'open_rate_requested': None, 'open_trade_value': 12.33075, 'sell_reason': None, - 'sell_order_status': None, + 'exit_reason': None, + 'exit_order_status': None, 'strategy': None, 'buy_tag': 'buys_signal_001', 'enter_tag': 'buys_signal_001', @@ -2133,19 +2243,19 @@ def test_select_order(fee, is_short): trades = Trade.get_trades().all() # Open buy order, no sell order - order = trades[0].select_order(trades[0].enter_side, True) + order = trades[0].select_order(trades[0].entry_side, True) assert order is None - order = trades[0].select_order(trades[0].enter_side, False) + order = trades[0].select_order(trades[0].entry_side, False) assert order is not None order = trades[0].select_order(trades[0].exit_side, None) assert order is None # closed buy order, and open sell order - order = trades[1].select_order(trades[1].enter_side, True) + order = trades[1].select_order(trades[1].entry_side, True) assert order is None - order = trades[1].select_order(trades[1].enter_side, False) + order = trades[1].select_order(trades[1].entry_side, False) assert order is not None - order = trades[1].select_order(trades[1].enter_side, None) + order = trades[1].select_order(trades[1].entry_side, None) assert order is not None order = trades[1].select_order(trades[1].exit_side, True) assert order is None @@ -2153,15 +2263,15 @@ def test_select_order(fee, is_short): assert order is not None # Has open buy order - order = trades[3].select_order(trades[3].enter_side, True) + order = trades[3].select_order(trades[3].entry_side, True) assert order is not None - order = trades[3].select_order(trades[3].enter_side, False) + order = trades[3].select_order(trades[3].entry_side, False) assert order is None # Open sell order - order = trades[4].select_order(trades[4].enter_side, True) + order = trades[4].select_order(trades[4].entry_side, True) assert order is None - order = trades[4].select_order(trades[4].enter_side, False) + order = trades[4].select_order(trades[4].entry_side, False) assert order is not None trades[4].orders[1].ft_order_side = trades[4].exit_side @@ -2195,7 +2305,7 @@ def test_Trade_object_idem(): 'get_open_trades_without_assigned_fees', 'get_open_order_trades', 'get_trades', - 'get_sell_reason_performance', + 'get_exit_reason_performance', 'get_enter_tag_performance', 'get_mix_tag_performance', @@ -2384,7 +2494,7 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee, is_short): o1_cost = o1_amount * o1_rate o1_fee_cost = o1_cost * fee.return_value o1_trade_val = o1_cost - o1_fee_cost if is_short else o1_cost + o1_fee_cost - enter_side = "sell" if is_short else "buy" + entry_side = "sell" if is_short else "buy" exit_side = "buy" if is_short else "sell" trade = Trade( @@ -2400,16 +2510,16 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee, is_short): is_short=is_short, leverage=1.0, ) - trade.update_fee(o1_fee_cost, 'BNB', fee.return_value, enter_side) + trade.update_fee(o1_fee_cost, 'BNB', fee.return_value, entry_side) # Check with 1 order order1 = Order( - ft_order_side=enter_side, + ft_order_side=entry_side, ft_pair=trade.pair, ft_is_open=False, status="closed", symbol=trade.pair, order_type="market", - side=enter_side, + side=entry_side, price=o1_rate, average=o1_rate, filled=o1_amount, @@ -2430,13 +2540,13 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee, is_short): assert trade.nr_of_successful_entries == 1 order2 = Order( - ft_order_side=enter_side, + ft_order_side=entry_side, ft_pair=trade.pair, ft_is_open=True, status="open", symbol=trade.pair, order_type="market", - side=enter_side, + side=entry_side, price=o1_rate, average=o1_rate, filled=o1_amount, @@ -2458,13 +2568,13 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee, is_short): # Let's try with some other orders order3 = Order( - ft_order_side=enter_side, + ft_order_side=entry_side, ft_pair=trade.pair, ft_is_open=False, status="cancelled", symbol=trade.pair, order_type="market", - side=enter_side, + side=entry_side, price=1, average=2, filled=0, @@ -2485,13 +2595,13 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee, is_short): assert trade.nr_of_successful_entries == 1 order4 = Order( - ft_order_side=enter_side, + ft_order_side=entry_side, ft_pair=trade.pair, ft_is_open=False, status="closed", symbol=trade.pair, order_type="market", - side=enter_side, + side=entry_side, price=o1_rate, average=o1_rate, filled=o1_amount, @@ -2540,13 +2650,13 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee, is_short): # Check with 1 order order_noavg = Order( - ft_order_side=enter_side, + ft_order_side=entry_side, ft_pair=trade.pair, ft_is_open=False, status="closed", symbol=trade.pair, order_type="market", - side=enter_side, + side=entry_side, price=o1_rate, average=None, filled=o1_amount, diff --git a/tests/test_plotting.py b/tests/test_plotting.py index 940639465..9ee7a75c6 100644 --- a/tests/test_plotting.py +++ b/tests/test_plotting.py @@ -10,7 +10,8 @@ from plotly.subplots import make_subplots from freqtrade.commands import start_plot_dataframe, start_plot_profit from freqtrade.configuration import TimeRange from freqtrade.data import history -from freqtrade.data.btanalysis import create_cum_profit, load_backtest_data +from freqtrade.data.btanalysis import load_backtest_data +from freqtrade.data.metrics import create_cum_profit from freqtrade.exceptions import OperationalException from freqtrade.plot.plotting import (add_areas, add_indicators, add_profit, create_plotconfig, generate_candlestick_graph, generate_plot_filename, @@ -157,7 +158,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 +299,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 +319,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"] @@ -331,7 +332,13 @@ def test_generate_profit_graph(testdatadir): trades = trades[trades['pair'].isin(pairs)] - fig = generate_profit_graph(pairs, data, trades, timeframe="5m", stake_currency='BTC') + fig = generate_profit_graph( + pairs, + data, + trades, + timeframe="5m", + stake_currency='BTC', + starting_balance=0) assert isinstance(fig, go.Figure) assert fig.layout.title.text == "Freqtrade Profit plot" @@ -340,7 +347,7 @@ def test_generate_profit_graph(testdatadir): assert fig.layout.yaxis3.title.text == "Profit BTC" figure = fig.layout.figure - assert len(figure.data) == 7 + assert len(figure.data) == 8 avgclose = find_trace_in_fig_data(figure.data, "Avg close price") assert isinstance(avgclose, go.Scatter) @@ -355,6 +362,9 @@ def test_generate_profit_graph(testdatadir): underwater = find_trace_in_fig_data(figure.data, "Underwater Plot") assert isinstance(underwater, go.Scatter) + underwater_relative = find_trace_in_fig_data(figure.data, "Underwater Plot (%)") + assert isinstance(underwater_relative, go.Scatter) + for pair in pairs: profit_pair = find_trace_in_fig_data(figure.data, f"Profit {pair}") assert isinstance(profit_pair, go.Scatter) @@ -362,7 +372,7 @@ def test_generate_profit_graph(testdatadir): with pytest.raises(OperationalException, match=r"No trades found.*"): # Pair cannot be empty - so it's an empty dataframe. generate_profit_graph(pairs, data, trades.loc[trades['pair'].isnull()], timeframe="5m", - stake_currency='BTC') + stake_currency='BTC', starting_balance=0) def test_start_plot_dataframe(mocker): @@ -456,7 +466,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/backtest-result_multistrat.json b/tests/testdata/backtest-result_multistrat.json deleted file mode 100644 index 6bb60e398..000000000 --- a/tests/testdata/backtest-result_multistrat.json +++ /dev/null @@ -1 +0,0 @@ -{"strategy":{"StrategyTestV2":{"trades":[{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.37344398340249,"open_date":"2018-01-10 07:15:00+00:00","close_date":"2018-01-10 07:20:00+00:00","open_rate":9.64e-05,"close_rate":0.00010074887218045112,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":4.348872180451118e-06,"sell_reason":"roi","initial_stop_loss_abs":8.676e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.676e-05,"stop_loss_ratio":0.1,"min_rate":9.64e-05,"max_rate":0.00010074887218045112,"is_open":false,"buy_tag":null,"open_timestamp":1515568500000.0,"close_timestamp":1515568800000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":21.026072329688816,"open_date":"2018-01-10 07:15:00+00:00","close_date":"2018-01-10 07:30:00+00:00","open_rate":4.756e-05,"close_rate":4.9705563909774425e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":15,"profit_ratio":0.03990025,"profit_abs":2.1455639097744267e-06,"sell_reason":"roi","initial_stop_loss_abs":4.2804e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.2804e-05,"stop_loss_ratio":0.1,"min_rate":4.756e-05,"max_rate":4.9705563909774425e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515568500000.0,"close_timestamp":1515569400000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":29.94908655286014,"open_date":"2018-01-10 07:25:00+00:00","close_date":"2018-01-10 07:35:00+00:00","open_rate":3.339e-05,"close_rate":3.489631578947368e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":10,"profit_ratio":0.03990025,"profit_abs":1.506315789473681e-06,"sell_reason":"roi","initial_stop_loss_abs":3.0050999999999997e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.0050999999999997e-05,"stop_loss_ratio":0.1,"min_rate":3.339e-05,"max_rate":3.489631578947368e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515569100000.0,"close_timestamp":1515569700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.313531353135314,"open_date":"2018-01-10 07:25:00+00:00","close_date":"2018-01-10 07:40:00+00:00","open_rate":9.696e-05,"close_rate":0.00010133413533834584,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":15,"profit_ratio":0.03990025,"profit_abs":4.3741353383458455e-06,"sell_reason":"roi","initial_stop_loss_abs":8.7264e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.7264e-05,"stop_loss_ratio":0.1,"min_rate":9.696e-05,"max_rate":0.00010133413533834584,"is_open":false,"buy_tag":null,"open_timestamp":1515569100000.0,"close_timestamp":1515570000000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010604453870625663,"open_date":"2018-01-10 07:35:00+00:00","close_date":"2018-01-10 08:35:00+00:00","open_rate":0.0943,"close_rate":0.09477268170426063,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.0,"profit_abs":0.0004726817042606385,"sell_reason":"roi","initial_stop_loss_abs":0.08487,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08487,"stop_loss_ratio":0.1,"min_rate":0.0943,"max_rate":0.09477268170426063,"is_open":false,"buy_tag":null,"open_timestamp":1515569700000.0,"close_timestamp":1515573300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03677001860930642,"open_date":"2018-01-10 07:40:00+00:00","close_date":"2018-01-10 08:10:00+00:00","open_rate":0.02719607,"close_rate":0.02760503345864661,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.00040896345864661204,"sell_reason":"roi","initial_stop_loss_abs":0.024476463,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.024476463,"stop_loss_ratio":0.1,"min_rate":0.02719607,"max_rate":0.02760503345864661,"is_open":false,"buy_tag":null,"open_timestamp":1515570000000.0,"close_timestamp":1515571800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.021575196463739,"open_date":"2018-01-10 08:15:00+00:00","close_date":"2018-01-10 09:55:00+00:00","open_rate":0.04634952,"close_rate":0.046581848421052625,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":100,"profit_ratio":0.0,"profit_abs":0.0002323284210526272,"sell_reason":"roi","initial_stop_loss_abs":0.041714568,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.041714568,"stop_loss_ratio":0.1,"min_rate":0.04634952,"max_rate":0.046581848421052625,"is_open":false,"buy_tag":null,"open_timestamp":1515572100000.0,"close_timestamp":1515578100000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":32.615786040443574,"open_date":"2018-01-10 14:45:00+00:00","close_date":"2018-01-10 15:50:00+00:00","open_rate":3.066e-05,"close_rate":3.081368421052631e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":65,"profit_ratio":-0.0,"profit_abs":1.5368421052630647e-07,"sell_reason":"roi","initial_stop_loss_abs":2.7594e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7594e-05,"stop_loss_ratio":0.1,"min_rate":3.066e-05,"max_rate":3.081368421052631e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515595500000.0,"close_timestamp":1515599400000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.05917194776300452,"open_date":"2018-01-10 16:35:00+00:00","close_date":"2018-01-10 17:15:00+00:00","open_rate":0.0168999,"close_rate":0.016984611278195488,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":8.471127819548868e-05,"sell_reason":"roi","initial_stop_loss_abs":0.01520991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.01520991,"stop_loss_ratio":0.1,"min_rate":0.0168999,"max_rate":0.016984611278195488,"is_open":false,"buy_tag":null,"open_timestamp":1515602100000.0,"close_timestamp":1515604500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010949822656672253,"open_date":"2018-01-10 16:40:00+00:00","close_date":"2018-01-10 17:20:00+00:00","open_rate":0.09132568,"close_rate":0.0917834528320802,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004577728320801916,"sell_reason":"roi","initial_stop_loss_abs":0.08219311200000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08219311200000001,"stop_loss_ratio":0.1,"min_rate":0.09132568,"max_rate":0.0917834528320802,"is_open":false,"buy_tag":null,"open_timestamp":1515602400000.0,"close_timestamp":1515604800000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011238476768326556,"open_date":"2018-01-10 18:50:00+00:00","close_date":"2018-01-10 19:45:00+00:00","open_rate":0.08898003,"close_rate":0.08942604518796991,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":0.00044601518796991146,"sell_reason":"roi","initial_stop_loss_abs":0.080082027,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.080082027,"stop_loss_ratio":0.1,"min_rate":0.08898003,"max_rate":0.08942604518796991,"is_open":false,"buy_tag":null,"open_timestamp":1515610200000.0,"close_timestamp":1515613500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011682232072680307,"open_date":"2018-01-10 22:15:00+00:00","close_date":"2018-01-10 23:00:00+00:00","open_rate":0.08560008,"close_rate":0.08602915308270676,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":0.0,"profit_abs":0.00042907308270676014,"sell_reason":"roi","initial_stop_loss_abs":0.077040072,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.077040072,"stop_loss_ratio":0.1,"min_rate":0.08560008,"max_rate":0.08602915308270676,"is_open":false,"buy_tag":null,"open_timestamp":1515622500000.0,"close_timestamp":1515625200000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.4014726015023105,"open_date":"2018-01-10 22:50:00+00:00","close_date":"2018-01-10 23:20:00+00:00","open_rate":0.00249083,"close_rate":0.0025282860902255634,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":3.745609022556351e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002241747,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002241747,"stop_loss_ratio":0.1,"min_rate":0.00249083,"max_rate":0.0025282860902255634,"is_open":false,"buy_tag":null,"open_timestamp":1515624600000.0,"close_timestamp":1515626400000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":33.090668431502316,"open_date":"2018-01-10 23:15:00+00:00","close_date":"2018-01-11 00:15:00+00:00","open_rate":3.022e-05,"close_rate":3.037147869674185e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.0,"profit_abs":1.5147869674185174e-07,"sell_reason":"roi","initial_stop_loss_abs":2.7198e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7198e-05,"stop_loss_ratio":0.1,"min_rate":3.022e-05,"max_rate":3.037147869674185e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515626100000.0,"close_timestamp":1515629700000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.41034058268362744,"open_date":"2018-01-10 23:40:00+00:00","close_date":"2018-01-11 00:05:00+00:00","open_rate":0.002437,"close_rate":0.0024980776942355883,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":6.107769423558838e-05,"sell_reason":"roi","initial_stop_loss_abs":0.0021933,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0021933,"stop_loss_ratio":0.1,"min_rate":0.002437,"max_rate":0.0024980776942355883,"is_open":false,"buy_tag":null,"open_timestamp":1515627600000.0,"close_timestamp":1515629100000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02095643931654345,"open_date":"2018-01-11 00:00:00+00:00","close_date":"2018-01-11 00:35:00+00:00","open_rate":0.04771803,"close_rate":0.04843559436090225,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0007175643609022495,"sell_reason":"roi","initial_stop_loss_abs":0.042946227000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.042946227000000003,"stop_loss_ratio":0.1,"min_rate":0.04771803,"max_rate":0.04843559436090225,"is_open":false,"buy_tag":null,"open_timestamp":1515628800000.0,"close_timestamp":1515630900000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":27.389756231169542,"open_date":"2018-01-11 03:40:00+00:00","close_date":"2018-01-11 04:25:00+00:00","open_rate":3.651e-05,"close_rate":3.2859000000000005e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.10448878,"profit_abs":-3.650999999999996e-06,"sell_reason":"stop_loss","initial_stop_loss_abs":3.2859000000000005e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.2859000000000005e-05,"stop_loss_ratio":0.1,"min_rate":3.2859000000000005e-05,"max_rate":3.651e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515642000000.0,"close_timestamp":1515644700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011332594070446804,"open_date":"2018-01-11 03:55:00+00:00","close_date":"2018-01-11 04:25:00+00:00","open_rate":0.08824105,"close_rate":0.08956798308270676,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.0013269330827067605,"sell_reason":"roi","initial_stop_loss_abs":0.079416945,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.079416945,"stop_loss_ratio":0.1,"min_rate":0.08824105,"max_rate":0.08956798308270676,"is_open":false,"buy_tag":null,"open_timestamp":1515642900000.0,"close_timestamp":1515644700000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.411522633744856,"open_date":"2018-01-11 04:00:00+00:00","close_date":"2018-01-11 04:50:00+00:00","open_rate":0.00243,"close_rate":0.002442180451127819,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":-0.0,"profit_abs":1.2180451127819219e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002187,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002187,"stop_loss_ratio":0.1,"min_rate":0.00243,"max_rate":0.002442180451127819,"is_open":false,"buy_tag":null,"open_timestamp":1515643200000.0,"close_timestamp":1515646200000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022001890402423376,"open_date":"2018-01-11 04:30:00+00:00","close_date":"2018-01-11 04:55:00+00:00","open_rate":0.04545064,"close_rate":0.046589753784461146,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":0.001139113784461146,"sell_reason":"roi","initial_stop_loss_abs":0.040905576,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.040905576,"stop_loss_ratio":0.1,"min_rate":0.04545064,"max_rate":0.046589753784461146,"is_open":false,"buy_tag":null,"open_timestamp":1515645000000.0,"close_timestamp":1515646500000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":29.655990510083036,"open_date":"2018-01-11 04:30:00+00:00","close_date":"2018-01-11 04:50:00+00:00","open_rate":3.372e-05,"close_rate":3.456511278195488e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":8.4511278195488e-07,"sell_reason":"roi","initial_stop_loss_abs":3.0348e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.0348e-05,"stop_loss_ratio":0.1,"min_rate":3.372e-05,"max_rate":3.456511278195488e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515645000000.0,"close_timestamp":1515646200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.037821482602118005,"open_date":"2018-01-11 04:55:00+00:00","close_date":"2018-01-11 05:15:00+00:00","open_rate":0.02644,"close_rate":0.02710265664160401,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":0.0006626566416040071,"sell_reason":"roi","initial_stop_loss_abs":0.023796,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.023796,"stop_loss_ratio":0.1,"min_rate":0.02644,"max_rate":0.02710265664160401,"is_open":false,"buy_tag":null,"open_timestamp":1515646500000.0,"close_timestamp":1515647700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011348161597821153,"open_date":"2018-01-11 11:20:00+00:00","close_date":"2018-01-11 12:00:00+00:00","open_rate":0.08812,"close_rate":0.08856170426065162,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004417042606516125,"sell_reason":"roi","initial_stop_loss_abs":0.079308,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.079308,"stop_loss_ratio":0.1,"min_rate":0.08812,"max_rate":0.08856170426065162,"is_open":false,"buy_tag":null,"open_timestamp":1515669600000.0,"close_timestamp":1515672000000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.037263696923919086,"open_date":"2018-01-11 11:35:00+00:00","close_date":"2018-01-11 12:15:00+00:00","open_rate":0.02683577,"close_rate":0.026970285137844607,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00013451513784460897,"sell_reason":"roi","initial_stop_loss_abs":0.024152193,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.024152193,"stop_loss_ratio":0.1,"min_rate":0.02683577,"max_rate":0.026970285137844607,"is_open":false,"buy_tag":null,"open_timestamp":1515670500000.0,"close_timestamp":1515672900000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":20.329335230737954,"open_date":"2018-01-11 14:00:00+00:00","close_date":"2018-01-11 14:25:00+00:00","open_rate":4.919e-05,"close_rate":5.04228320802005e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":1.232832080200495e-06,"sell_reason":"roi","initial_stop_loss_abs":4.4271000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4271000000000004e-05,"stop_loss_ratio":0.1,"min_rate":4.919e-05,"max_rate":5.04228320802005e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515679200000.0,"close_timestamp":1515680700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.01138317402960718,"open_date":"2018-01-11 19:25:00+00:00","close_date":"2018-01-11 20:35:00+00:00","open_rate":0.08784896,"close_rate":0.08828930566416039,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":70,"profit_ratio":-0.0,"profit_abs":0.0004403456641603881,"sell_reason":"roi","initial_stop_loss_abs":0.079064064,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.079064064,"stop_loss_ratio":0.1,"min_rate":0.08784896,"max_rate":0.08828930566416039,"is_open":false,"buy_tag":null,"open_timestamp":1515698700000.0,"close_timestamp":1515702900000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.58863858961802,"open_date":"2018-01-11 22:35:00+00:00","close_date":"2018-01-11 23:30:00+00:00","open_rate":5.105e-05,"close_rate":5.130588972431077e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.558897243107704e-07,"sell_reason":"roi","initial_stop_loss_abs":4.5945e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.5945e-05,"stop_loss_ratio":0.1,"min_rate":5.105e-05,"max_rate":5.130588972431077e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515710100000.0,"close_timestamp":1515713400000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":25.252525252525253,"open_date":"2018-01-11 22:55:00+00:00","close_date":"2018-01-11 23:25:00+00:00","open_rate":3.96e-05,"close_rate":4.019548872180451e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":5.954887218045116e-07,"sell_reason":"roi","initial_stop_loss_abs":3.5640000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.5640000000000004e-05,"stop_loss_ratio":0.1,"min_rate":3.96e-05,"max_rate":4.019548872180451e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515711300000.0,"close_timestamp":1515713100000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":34.66204506065858,"open_date":"2018-01-11 22:55:00+00:00","close_date":"2018-01-11 23:35:00+00:00","open_rate":2.885e-05,"close_rate":2.899461152882205e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.4461152882205115e-07,"sell_reason":"roi","initial_stop_loss_abs":2.5965e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.5965e-05,"stop_loss_ratio":0.1,"min_rate":2.885e-05,"max_rate":2.899461152882205e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515711300000.0,"close_timestamp":1515713700000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03780718336483932,"open_date":"2018-01-11 23:30:00+00:00","close_date":"2018-01-12 00:05:00+00:00","open_rate":0.02645,"close_rate":0.026847744360902256,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0003977443609022545,"sell_reason":"roi","initial_stop_loss_abs":0.023805000000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.023805000000000003,"stop_loss_ratio":0.1,"min_rate":0.02645,"max_rate":0.026847744360902256,"is_open":false,"buy_tag":null,"open_timestamp":1515713400000.0,"close_timestamp":1515715500000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.020833333333333332,"open_date":"2018-01-11 23:55:00+00:00","close_date":"2018-01-12 01:15:00+00:00","open_rate":0.048,"close_rate":0.04824060150375939,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.0,"profit_abs":0.00024060150375938838,"sell_reason":"roi","initial_stop_loss_abs":0.0432,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0432,"stop_loss_ratio":0.1,"min_rate":0.048,"max_rate":0.04824060150375939,"is_open":false,"buy_tag":null,"open_timestamp":1515714900000.0,"close_timestamp":1515719700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":21.31287297527707,"open_date":"2018-01-12 21:15:00+00:00","close_date":"2018-01-12 21:40:00+00:00","open_rate":4.692e-05,"close_rate":4.809593984962405e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":1.1759398496240516e-06,"sell_reason":"roi","initial_stop_loss_abs":4.2227999999999996e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.2227999999999996e-05,"stop_loss_ratio":0.1,"min_rate":4.692e-05,"max_rate":4.809593984962405e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515791700000.0,"close_timestamp":1515793200000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38915654211062944,"open_date":"2018-01-13 00:55:00+00:00","close_date":"2018-01-13 06:20:00+00:00","open_rate":0.00256966,"close_rate":0.0025825405012531327,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":325,"profit_ratio":-0.0,"profit_abs":1.2880501253132587e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002312694,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002312694,"stop_loss_ratio":0.1,"min_rate":0.00256966,"max_rate":0.0025825405012531327,"is_open":false,"buy_tag":null,"open_timestamp":1515804900000.0,"close_timestamp":1515824400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":15.96933886937081,"open_date":"2018-01-13 10:55:00+00:00","close_date":"2018-01-13 11:35:00+00:00","open_rate":6.262e-05,"close_rate":6.293388471177944e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":3.138847117794446e-07,"sell_reason":"roi","initial_stop_loss_abs":5.6358e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.6358e-05,"stop_loss_ratio":0.1,"min_rate":6.262e-05,"max_rate":6.293388471177944e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515840900000.0,"close_timestamp":1515843300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":21.141649048625794,"open_date":"2018-01-13 13:05:00+00:00","close_date":"2018-01-15 14:10:00+00:00","open_rate":4.73e-05,"close_rate":4.753709273182957e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":2945,"profit_ratio":0.0,"profit_abs":2.3709273182957117e-07,"sell_reason":"roi","initial_stop_loss_abs":4.257e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.257e-05,"stop_loss_ratio":0.1,"min_rate":4.73e-05,"max_rate":4.753709273182957e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515848700000.0,"close_timestamp":1516025400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":16.49348507339601,"open_date":"2018-01-13 13:30:00+00:00","close_date":"2018-01-13 14:45:00+00:00","open_rate":6.063e-05,"close_rate":6.0933909774436085e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":75,"profit_ratio":-0.0,"profit_abs":3.039097744360846e-07,"sell_reason":"roi","initial_stop_loss_abs":5.4567e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.4567e-05,"stop_loss_ratio":0.1,"min_rate":6.063e-05,"max_rate":6.0933909774436085e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515850200000.0,"close_timestamp":1515854700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":9.023641941887746,"open_date":"2018-01-13 13:40:00+00:00","close_date":"2018-01-13 23:30:00+00:00","open_rate":0.00011082,"close_rate":0.00011137548872180448,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":590,"profit_ratio":-0.0,"profit_abs":5.554887218044781e-07,"sell_reason":"roi","initial_stop_loss_abs":9.9738e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":9.9738e-05,"stop_loss_ratio":0.1,"min_rate":0.00011082,"max_rate":0.00011137548872180448,"is_open":false,"buy_tag":null,"open_timestamp":1515850800000.0,"close_timestamp":1515886200000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":16.863406408094438,"open_date":"2018-01-13 15:15:00+00:00","close_date":"2018-01-13 15:55:00+00:00","open_rate":5.93e-05,"close_rate":5.9597243107769415e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.9724310776941686e-07,"sell_reason":"roi","initial_stop_loss_abs":5.337e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.337e-05,"stop_loss_ratio":0.1,"min_rate":5.93e-05,"max_rate":5.9597243107769415e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515856500000.0,"close_timestamp":1515858900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.020618543947292404,"open_date":"2018-01-13 16:30:00+00:00","close_date":"2018-01-13 17:10:00+00:00","open_rate":0.04850003,"close_rate":0.04874313791979949,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00024310791979949287,"sell_reason":"roi","initial_stop_loss_abs":0.043650027,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.043650027,"stop_loss_ratio":0.1,"min_rate":0.04850003,"max_rate":0.04874313791979949,"is_open":false,"buy_tag":null,"open_timestamp":1515861000000.0,"close_timestamp":1515863400000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010178097365511457,"open_date":"2018-01-13 22:05:00+00:00","close_date":"2018-01-14 06:25:00+00:00","open_rate":0.09825019,"close_rate":0.09874267215538848,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":500,"profit_ratio":-0.0,"profit_abs":0.0004924821553884823,"sell_reason":"roi","initial_stop_loss_abs":0.088425171,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.088425171,"stop_loss_ratio":0.1,"min_rate":0.09825019,"max_rate":0.09874267215538848,"is_open":false,"buy_tag":null,"open_timestamp":1515881100000.0,"close_timestamp":1515911100000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":16.616816218012627,"open_date":"2018-01-14 00:20:00+00:00","close_date":"2018-01-14 22:55:00+00:00","open_rate":6.018e-05,"close_rate":6.048165413533834e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":1355,"profit_ratio":0.0,"profit_abs":3.0165413533833987e-07,"sell_reason":"roi","initial_stop_loss_abs":5.4162e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.4162e-05,"stop_loss_ratio":0.1,"min_rate":6.018e-05,"max_rate":6.048165413533834e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515889200000.0,"close_timestamp":1515970500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010246952581919518,"open_date":"2018-01-14 12:45:00+00:00","close_date":"2018-01-14 13:25:00+00:00","open_rate":0.09758999,"close_rate":0.0980791628822055,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004891728822054991,"sell_reason":"roi","initial_stop_loss_abs":0.087830991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.087830991,"stop_loss_ratio":0.1,"min_rate":0.09758999,"max_rate":0.0980791628822055,"is_open":false,"buy_tag":null,"open_timestamp":1515933900000.0,"close_timestamp":1515936300000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3215434083601286,"open_date":"2018-01-14 15:30:00+00:00","close_date":"2018-01-14 16:00:00+00:00","open_rate":0.00311,"close_rate":0.0031567669172932328,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.676691729323286e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002799,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002799,"stop_loss_ratio":0.1,"min_rate":0.00311,"max_rate":0.0031567669172932328,"is_open":false,"buy_tag":null,"open_timestamp":1515943800000.0,"close_timestamp":1515945600000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.32010140812609433,"open_date":"2018-01-14 20:45:00+00:00","close_date":"2018-01-14 22:15:00+00:00","open_rate":0.00312401,"close_rate":0.003139669197994987,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":90,"profit_ratio":-0.0,"profit_abs":1.5659197994987058e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002811609,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002811609,"stop_loss_ratio":0.1,"min_rate":0.00312401,"max_rate":0.003139669197994987,"is_open":false,"buy_tag":null,"open_timestamp":1515962700000.0,"close_timestamp":1515968100000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.057247866085791646,"open_date":"2018-01-14 23:35:00+00:00","close_date":"2018-01-15 00:30:00+00:00","open_rate":0.0174679,"close_rate":0.017555458395989976,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":0.0,"profit_abs":8.755839598997492e-05,"sell_reason":"roi","initial_stop_loss_abs":0.015721110000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.015721110000000003,"stop_loss_ratio":0.1,"min_rate":0.0174679,"max_rate":0.017555458395989976,"is_open":false,"buy_tag":null,"open_timestamp":1515972900000.0,"close_timestamp":1515976200000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.013611282991367997,"open_date":"2018-01-14 23:45:00+00:00","close_date":"2018-01-15 00:25:00+00:00","open_rate":0.07346846,"close_rate":0.07383672295739348,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00036826295739347814,"sell_reason":"roi","initial_stop_loss_abs":0.066121614,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.066121614,"stop_loss_ratio":0.1,"min_rate":0.07346846,"max_rate":0.07383672295739348,"is_open":false,"buy_tag":null,"open_timestamp":1515973500000.0,"close_timestamp":1515975900000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010204706410596568,"open_date":"2018-01-15 02:25:00+00:00","close_date":"2018-01-15 03:05:00+00:00","open_rate":0.097994,"close_rate":0.09848519799498744,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004911979949874384,"sell_reason":"roi","initial_stop_loss_abs":0.0881946,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0881946,"stop_loss_ratio":0.1,"min_rate":0.097994,"max_rate":0.09848519799498744,"is_open":false,"buy_tag":null,"open_timestamp":1515983100000.0,"close_timestamp":1515985500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010353038616834042,"open_date":"2018-01-15 07:20:00+00:00","close_date":"2018-01-15 08:00:00+00:00","open_rate":0.09659,"close_rate":0.09707416040100247,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004841604010024786,"sell_reason":"roi","initial_stop_loss_abs":0.086931,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.086931,"stop_loss_ratio":0.1,"min_rate":0.09659,"max_rate":0.09707416040100247,"is_open":false,"buy_tag":null,"open_timestamp":1516000800000.0,"close_timestamp":1516003200000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.013016921998599,"open_date":"2018-01-15 08:20:00+00:00","close_date":"2018-01-15 08:55:00+00:00","open_rate":9.987e-05,"close_rate":0.00010137180451127818,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":1.501804511278178e-06,"sell_reason":"roi","initial_stop_loss_abs":8.9883e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.9883e-05,"stop_loss_ratio":0.1,"min_rate":9.987e-05,"max_rate":0.00010137180451127818,"is_open":false,"buy_tag":null,"open_timestamp":1516004400000.0,"close_timestamp":1516006500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010537752023511832,"open_date":"2018-01-15 12:10:00+00:00","close_date":"2018-01-16 02:50:00+00:00","open_rate":0.0948969,"close_rate":0.09537257368421052,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":880,"profit_ratio":0.0,"profit_abs":0.0004756736842105175,"sell_reason":"roi","initial_stop_loss_abs":0.08540721000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08540721000000001,"stop_loss_ratio":0.1,"min_rate":0.0948969,"max_rate":0.09537257368421052,"is_open":false,"buy_tag":null,"open_timestamp":1516018200000.0,"close_timestamp":1516071000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014084507042253523,"open_date":"2018-01-15 14:10:00+00:00","close_date":"2018-01-15 17:40:00+00:00","open_rate":0.071,"close_rate":0.07135588972431077,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":210,"profit_ratio":-0.0,"profit_abs":0.00035588972431077615,"sell_reason":"roi","initial_stop_loss_abs":0.0639,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0639,"stop_loss_ratio":0.1,"min_rate":0.071,"max_rate":0.07135588972431077,"is_open":false,"buy_tag":null,"open_timestamp":1516025400000.0,"close_timestamp":1516038000000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.021736763017766978,"open_date":"2018-01-15 14:30:00+00:00","close_date":"2018-01-15 15:10:00+00:00","open_rate":0.04600501,"close_rate":0.046235611553884705,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00023060155388470588,"sell_reason":"roi","initial_stop_loss_abs":0.041404509,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.041404509,"stop_loss_ratio":0.1,"min_rate":0.04600501,"max_rate":0.046235611553884705,"is_open":false,"buy_tag":null,"open_timestamp":1516026600000.0,"close_timestamp":1516029000000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.595465140919686,"open_date":"2018-01-15 18:10:00+00:00","close_date":"2018-01-15 19:25:00+00:00","open_rate":9.438e-05,"close_rate":9.485308270676693e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":75,"profit_ratio":-0.0,"profit_abs":4.7308270676692514e-07,"sell_reason":"roi","initial_stop_loss_abs":8.4942e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.4942e-05,"stop_loss_ratio":0.1,"min_rate":9.438e-05,"max_rate":9.485308270676693e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516039800000.0,"close_timestamp":1516044300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.032894726021471705,"open_date":"2018-01-15 18:35:00+00:00","close_date":"2018-01-15 19:15:00+00:00","open_rate":0.03040001,"close_rate":0.030552391002506264,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0001523810025062626,"sell_reason":"roi","initial_stop_loss_abs":0.027360009,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.027360009,"stop_loss_ratio":0.1,"min_rate":0.03040001,"max_rate":0.030552391002506264,"is_open":false,"buy_tag":null,"open_timestamp":1516041300000.0,"close_timestamp":1516043700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.13208840157615,"open_date":"2018-01-15 20:25:00+00:00","close_date":"2018-01-16 08:25:00+00:00","open_rate":5.837e-05,"close_rate":5.2533e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":720,"profit_ratio":-0.10448878,"profit_abs":-5.8369999999999985e-06,"sell_reason":"stop_loss","initial_stop_loss_abs":5.2533e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.2533e-05,"stop_loss_ratio":0.1,"min_rate":5.2533e-05,"max_rate":5.837e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516047900000.0,"close_timestamp":1516091100000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.021722130506560085,"open_date":"2018-01-15 20:40:00+00:00","close_date":"2018-01-15 22:00:00+00:00","open_rate":0.046036,"close_rate":0.04626675689223057,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.0,"profit_abs":0.00023075689223057277,"sell_reason":"roi","initial_stop_loss_abs":0.0414324,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0414324,"stop_loss_ratio":0.1,"min_rate":0.046036,"max_rate":0.04626675689223057,"is_open":false,"buy_tag":null,"open_timestamp":1516048800000.0,"close_timestamp":1516053600000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.34861425832316545,"open_date":"2018-01-16 00:30:00+00:00","close_date":"2018-01-16 01:10:00+00:00","open_rate":0.0028685,"close_rate":0.0028828784461152877,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.4378446115287727e-05,"sell_reason":"roi","initial_stop_loss_abs":0.00258165,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.00258165,"stop_loss_ratio":0.1,"min_rate":0.0028685,"max_rate":0.0028828784461152877,"is_open":false,"buy_tag":null,"open_timestamp":1516062600000.0,"close_timestamp":1516065000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014854967241083492,"open_date":"2018-01-16 01:15:00+00:00","close_date":"2018-01-16 02:35:00+00:00","open_rate":0.06731755,"close_rate":0.0676549813283208,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":0.0,"profit_abs":0.00033743132832080025,"sell_reason":"roi","initial_stop_loss_abs":0.060585795000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060585795000000005,"stop_loss_ratio":0.1,"min_rate":0.06731755,"max_rate":0.0676549813283208,"is_open":false,"buy_tag":null,"open_timestamp":1516065300000.0,"close_timestamp":1516070100000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010848794492804754,"open_date":"2018-01-16 07:45:00+00:00","close_date":"2018-01-16 08:40:00+00:00","open_rate":0.09217614,"close_rate":0.09263817578947368,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":0.0,"profit_abs":0.0004620357894736804,"sell_reason":"roi","initial_stop_loss_abs":0.082958526,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.082958526,"stop_loss_ratio":0.1,"min_rate":0.09217614,"max_rate":0.09263817578947368,"is_open":false,"buy_tag":null,"open_timestamp":1516088700000.0,"close_timestamp":1516092000000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06060606060606061,"open_date":"2018-01-16 08:35:00+00:00","close_date":"2018-01-16 08:55:00+00:00","open_rate":0.0165,"close_rate":0.016913533834586467,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":0.00041353383458646656,"sell_reason":"roi","initial_stop_loss_abs":0.01485,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.01485,"stop_loss_ratio":0.1,"min_rate":0.0165,"max_rate":0.016913533834586467,"is_open":false,"buy_tag":null,"open_timestamp":1516091700000.0,"close_timestamp":1516092900000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":12.57387149503332,"open_date":"2018-01-16 08:35:00+00:00","close_date":"2018-01-16 08:40:00+00:00","open_rate":7.953e-05,"close_rate":8.311781954887218e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":3.587819548872171e-06,"sell_reason":"roi","initial_stop_loss_abs":7.157700000000001e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":7.157700000000001e-05,"stop_loss_ratio":0.1,"min_rate":7.953e-05,"max_rate":8.311781954887218e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516091700000.0,"close_timestamp":1516092000000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022122914915269236,"open_date":"2018-01-16 08:45:00+00:00","close_date":"2018-01-16 09:50:00+00:00","open_rate":0.045202,"close_rate":0.04542857644110275,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":65,"profit_ratio":-0.0,"profit_abs":0.00022657644110275071,"sell_reason":"roi","initial_stop_loss_abs":0.0406818,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0406818,"stop_loss_ratio":0.1,"min_rate":0.045202,"max_rate":0.04542857644110275,"is_open":false,"buy_tag":null,"open_timestamp":1516092300000.0,"close_timestamp":1516096200000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.054878048780488,"open_date":"2018-01-16 09:15:00+00:00","close_date":"2018-01-16 09:45:00+00:00","open_rate":5.248e-05,"close_rate":5.326917293233082e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":7.891729323308177e-07,"sell_reason":"roi","initial_stop_loss_abs":4.7232e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7232e-05,"stop_loss_ratio":0.1,"min_rate":5.248e-05,"max_rate":5.326917293233082e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516094100000.0,"close_timestamp":1516095900000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03457434486802627,"open_date":"2018-01-16 09:15:00+00:00","close_date":"2018-01-16 09:55:00+00:00","open_rate":0.02892318,"close_rate":0.02906815834586466,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.0001449783458646603,"sell_reason":"roi","initial_stop_loss_abs":0.026030862000000002,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.026030862000000002,"stop_loss_ratio":0.1,"min_rate":0.02892318,"max_rate":0.02906815834586466,"is_open":false,"buy_tag":null,"open_timestamp":1516094100000.0,"close_timestamp":1516096500000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.38735944164405,"open_date":"2018-01-16 09:50:00+00:00","close_date":"2018-01-16 10:10:00+00:00","open_rate":5.158e-05,"close_rate":5.287273182957392e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":1.2927318295739246e-06,"sell_reason":"roi","initial_stop_loss_abs":4.6422e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6422e-05,"stop_loss_ratio":0.1,"min_rate":5.158e-05,"max_rate":5.287273182957392e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516096200000.0,"close_timestamp":1516097400000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.035357778286929785,"open_date":"2018-01-16 10:05:00+00:00","close_date":"2018-01-16 10:35:00+00:00","open_rate":0.02828232,"close_rate":0.02870761804511278,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.00042529804511277913,"sell_reason":"roi","initial_stop_loss_abs":0.025454088,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025454088,"stop_loss_ratio":0.1,"min_rate":0.02828232,"max_rate":0.02870761804511278,"is_open":false,"buy_tag":null,"open_timestamp":1516097100000.0,"close_timestamp":1516098900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022948496230938982,"open_date":"2018-01-16 10:05:00+00:00","close_date":"2018-01-16 10:40:00+00:00","open_rate":0.04357584,"close_rate":0.044231115789473675,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0006552757894736777,"sell_reason":"roi","initial_stop_loss_abs":0.039218256,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.039218256,"stop_loss_ratio":0.1,"min_rate":0.04357584,"max_rate":0.044231115789473675,"is_open":false,"buy_tag":null,"open_timestamp":1516097100000.0,"close_timestamp":1516099200000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.64975755315181,"open_date":"2018-01-16 13:45:00+00:00","close_date":"2018-01-16 14:20:00+00:00","open_rate":5.362e-05,"close_rate":5.442631578947368e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":8.063157894736843e-07,"sell_reason":"roi","initial_stop_loss_abs":4.8258e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.8258e-05,"stop_loss_ratio":0.1,"min_rate":5.362e-05,"max_rate":5.442631578947368e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516110300000.0,"close_timestamp":1516112400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.86080724254998,"open_date":"2018-01-16 17:30:00+00:00","close_date":"2018-01-16 18:25:00+00:00","open_rate":5.302e-05,"close_rate":5.328576441102756e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.6576441102756397e-07,"sell_reason":"roi","initial_stop_loss_abs":4.7718e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7718e-05,"stop_loss_ratio":0.1,"min_rate":5.302e-05,"max_rate":5.328576441102756e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516123800000.0,"close_timestamp":1516127100000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010952903718828448,"open_date":"2018-01-16 18:15:00+00:00","close_date":"2018-01-16 18:45:00+00:00","open_rate":0.09129999,"close_rate":0.09267292218045112,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.0013729321804511196,"sell_reason":"roi","initial_stop_loss_abs":0.082169991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.082169991,"stop_loss_ratio":0.1,"min_rate":0.09129999,"max_rate":0.09267292218045112,"is_open":false,"buy_tag":null,"open_timestamp":1516126500000.0,"close_timestamp":1516128300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":26.26050420168067,"open_date":"2018-01-16 18:15:00+00:00","close_date":"2018-01-16 18:35:00+00:00","open_rate":3.808e-05,"close_rate":3.903438596491228e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":9.543859649122774e-07,"sell_reason":"roi","initial_stop_loss_abs":3.4272e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.4272e-05,"stop_loss_ratio":0.1,"min_rate":3.808e-05,"max_rate":3.903438596491228e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516126500000.0,"close_timestamp":1516127700000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.035574376772493324,"open_date":"2018-01-16 19:00:00+00:00","close_date":"2018-01-16 19:30:00+00:00","open_rate":0.02811012,"close_rate":0.028532828571428567,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.00042270857142856846,"sell_reason":"roi","initial_stop_loss_abs":0.025299108,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025299108,"stop_loss_ratio":0.1,"min_rate":0.02811012,"max_rate":0.028532828571428567,"is_open":false,"buy_tag":null,"open_timestamp":1516129200000.0,"close_timestamp":1516131000000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.387028357567759,"open_date":"2018-01-16 21:25:00+00:00","close_date":"2018-01-16 22:25:00+00:00","open_rate":0.00258379,"close_rate":0.002325411,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.10448878,"profit_abs":-0.000258379,"sell_reason":"stop_loss","initial_stop_loss_abs":0.002325411,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002325411,"stop_loss_ratio":0.1,"min_rate":0.002325411,"max_rate":0.00258379,"is_open":false,"buy_tag":null,"open_timestamp":1516137900000.0,"close_timestamp":1516141500000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":39.07776475185619,"open_date":"2018-01-16 21:25:00+00:00","close_date":"2018-01-16 22:45:00+00:00","open_rate":2.559e-05,"close_rate":2.3031e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.10448878,"profit_abs":-2.5590000000000004e-06,"sell_reason":"stop_loss","initial_stop_loss_abs":2.3031e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.3031e-05,"stop_loss_ratio":0.1,"min_rate":2.3031e-05,"max_rate":2.559e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516137900000.0,"close_timestamp":1516142700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":13.123359580052494,"open_date":"2018-01-16 21:35:00+00:00","close_date":"2018-01-16 22:25:00+00:00","open_rate":7.62e-05,"close_rate":6.858e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":-0.10448878,"profit_abs":-7.619999999999998e-06,"sell_reason":"stop_loss","initial_stop_loss_abs":6.858e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":6.858e-05,"stop_loss_ratio":0.1,"min_rate":6.858e-05,"max_rate":7.62e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516138500000.0,"close_timestamp":1516141500000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.4350777048780912,"open_date":"2018-01-16 22:30:00+00:00","close_date":"2018-01-16 22:35:00+00:00","open_rate":0.00229844,"close_rate":0.002402129022556391,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":0.00010368902255639091,"sell_reason":"roi","initial_stop_loss_abs":0.0020685960000000002,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0020685960000000002,"stop_loss_ratio":0.1,"min_rate":0.00229844,"max_rate":0.002402129022556391,"is_open":false,"buy_tag":null,"open_timestamp":1516141800000.0,"close_timestamp":1516142100000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06622516556291391,"open_date":"2018-01-16 22:30:00+00:00","close_date":"2018-01-16 22:40:00+00:00","open_rate":0.0151,"close_rate":0.015781203007518795,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":10,"profit_ratio":0.03990025,"profit_abs":0.0006812030075187946,"sell_reason":"roi","initial_stop_loss_abs":0.013590000000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.013590000000000001,"stop_loss_ratio":0.1,"min_rate":0.0151,"max_rate":0.015781203007518795,"is_open":false,"buy_tag":null,"open_timestamp":1516141800000.0,"close_timestamp":1516142400000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.42431134269081283,"open_date":"2018-01-16 22:40:00+00:00","close_date":"2018-01-16 22:45:00+00:00","open_rate":0.00235676,"close_rate":0.00246308,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":0.00010632000000000003,"sell_reason":"roi","initial_stop_loss_abs":0.002121084,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002121084,"stop_loss_ratio":0.1,"min_rate":0.00235676,"max_rate":0.00246308,"is_open":false,"buy_tag":null,"open_timestamp":1516142400000.0,"close_timestamp":1516142700000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.01585559988076589,"open_date":"2018-01-16 22:45:00+00:00","close_date":"2018-01-16 23:05:00+00:00","open_rate":0.0630692,"close_rate":0.06464988170426066,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":0.0015806817042606502,"sell_reason":"roi","initial_stop_loss_abs":0.056762280000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.056762280000000005,"stop_loss_ratio":0.1,"min_rate":0.0630692,"max_rate":0.06464988170426066,"is_open":false,"buy_tag":null,"open_timestamp":1516142700000.0,"close_timestamp":1516143900000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":45.45454545454545,"open_date":"2018-01-16 22:50:00+00:00","close_date":"2018-01-16 22:55:00+00:00","open_rate":2.2e-05,"close_rate":2.299248120300751e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":9.924812030075114e-07,"sell_reason":"roi","initial_stop_loss_abs":1.98e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":1.98e-05,"stop_loss_ratio":0.1,"min_rate":2.2e-05,"max_rate":2.299248120300751e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516143000000.0,"close_timestamp":1516143300000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":20.10454362685967,"open_date":"2018-01-17 03:30:00+00:00","close_date":"2018-01-17 04:00:00+00:00","open_rate":4.974e-05,"close_rate":5.048796992481203e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":7.479699248120277e-07,"sell_reason":"roi","initial_stop_loss_abs":4.4766000000000005e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4766000000000005e-05,"stop_loss_ratio":0.1,"min_rate":4.974e-05,"max_rate":5.048796992481203e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516159800000.0,"close_timestamp":1516161600000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":14.068655036578503,"open_date":"2018-01-17 03:55:00+00:00","close_date":"2018-01-17 04:15:00+00:00","open_rate":7.108e-05,"close_rate":7.28614536340852e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":1.7814536340851996e-06,"sell_reason":"roi","initial_stop_loss_abs":6.3972e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":6.3972e-05,"stop_loss_ratio":0.1,"min_rate":7.108e-05,"max_rate":7.28614536340852e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516161300000.0,"close_timestamp":1516162500000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.0231107002542177,"open_date":"2018-01-17 09:35:00+00:00","close_date":"2018-01-17 10:15:00+00:00","open_rate":0.04327,"close_rate":0.04348689223057644,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0002168922305764362,"sell_reason":"roi","initial_stop_loss_abs":0.038943000000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.038943000000000005,"stop_loss_ratio":0.1,"min_rate":0.04327,"max_rate":0.04348689223057644,"is_open":false,"buy_tag":null,"open_timestamp":1516181700000.0,"close_timestamp":1516184100000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":20.012007204322593,"open_date":"2018-01-17 10:20:00+00:00","close_date":"2018-01-17 17:00:00+00:00","open_rate":4.997e-05,"close_rate":5.022047619047618e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":400,"profit_ratio":-0.0,"profit_abs":2.504761904761831e-07,"sell_reason":"roi","initial_stop_loss_abs":4.4973e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4973e-05,"stop_loss_ratio":0.1,"min_rate":4.997e-05,"max_rate":5.022047619047618e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516184400000.0,"close_timestamp":1516208400000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014626687444363738,"open_date":"2018-01-17 10:30:00+00:00","close_date":"2018-01-17 11:25:00+00:00","open_rate":0.06836818,"close_rate":0.06871087764411027,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":0.00034269764411026804,"sell_reason":"roi","initial_stop_loss_abs":0.061531362,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.061531362,"stop_loss_ratio":0.1,"min_rate":0.06836818,"max_rate":0.06871087764411027,"is_open":false,"buy_tag":null,"open_timestamp":1516185000000.0,"close_timestamp":1516188300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":27.548209366391184,"open_date":"2018-01-17 10:30:00+00:00","close_date":"2018-01-17 11:10:00+00:00","open_rate":3.63e-05,"close_rate":3.648195488721804e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.8195488721804031e-07,"sell_reason":"roi","initial_stop_loss_abs":3.2670000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.2670000000000004e-05,"stop_loss_ratio":0.1,"min_rate":3.63e-05,"max_rate":3.648195488721804e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516185000000.0,"close_timestamp":1516187400000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03558718861209965,"open_date":"2018-01-17 12:30:00+00:00","close_date":"2018-01-17 22:05:00+00:00","open_rate":0.0281,"close_rate":0.02824085213032581,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":575,"profit_ratio":-0.0,"profit_abs":0.0001408521303258095,"sell_reason":"roi","initial_stop_loss_abs":0.02529,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.02529,"stop_loss_ratio":0.1,"min_rate":0.0281,"max_rate":0.02824085213032581,"is_open":false,"buy_tag":null,"open_timestamp":1516192200000.0,"close_timestamp":1516226700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011559355963546878,"open_date":"2018-01-17 12:35:00+00:00","close_date":"2018-01-17 16:55:00+00:00","open_rate":0.08651001,"close_rate":0.08694364413533832,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":260,"profit_ratio":-0.0,"profit_abs":0.00043363413533832607,"sell_reason":"roi","initial_stop_loss_abs":0.077859009,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.077859009,"stop_loss_ratio":0.1,"min_rate":0.08651001,"max_rate":0.08694364413533832,"is_open":false,"buy_tag":null,"open_timestamp":1516192500000.0,"close_timestamp":1516208100000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.752529735487308,"open_date":"2018-01-18 05:00:00+00:00","close_date":"2018-01-18 05:55:00+00:00","open_rate":5.633e-05,"close_rate":5.6612355889724306e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.8235588972430847e-07,"sell_reason":"roi","initial_stop_loss_abs":5.0697e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0697e-05,"stop_loss_ratio":0.1,"min_rate":5.633e-05,"max_rate":5.6612355889724306e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516251600000.0,"close_timestamp":1516254900000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.01430923457900944,"open_date":"2018-01-18 05:20:00+00:00","close_date":"2018-01-18 05:55:00+00:00","open_rate":0.06988494,"close_rate":0.07093584135338346,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0010509013533834544,"sell_reason":"roi","initial_stop_loss_abs":0.06289644600000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06289644600000001,"stop_loss_ratio":0.1,"min_rate":0.06988494,"max_rate":0.07093584135338346,"is_open":false,"buy_tag":null,"open_timestamp":1516252800000.0,"close_timestamp":1516254900000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.034265103697024,"open_date":"2018-01-18 07:35:00+00:00","close_date":"2018-01-18 08:15:00+00:00","open_rate":5.545e-05,"close_rate":5.572794486215538e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.779448621553787e-07,"sell_reason":"roi","initial_stop_loss_abs":4.9905e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.9905e-05,"stop_loss_ratio":0.1,"min_rate":5.545e-05,"max_rate":5.572794486215538e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516260900000.0,"close_timestamp":1516263300000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06121723118136401,"open_date":"2018-01-18 09:00:00+00:00","close_date":"2018-01-18 09:40:00+00:00","open_rate":0.01633527,"close_rate":0.016417151052631574,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":8.188105263157511e-05,"sell_reason":"roi","initial_stop_loss_abs":0.014701743,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014701743,"stop_loss_ratio":0.1,"min_rate":0.01633527,"max_rate":0.016417151052631574,"is_open":false,"buy_tag":null,"open_timestamp":1516266000000.0,"close_timestamp":1516268400000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3707356136045141,"open_date":"2018-01-18 16:40:00+00:00","close_date":"2018-01-18 17:20:00+00:00","open_rate":0.00269734,"close_rate":0.002710860501253133,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.3520501253133123e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002427606,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002427606,"stop_loss_ratio":0.1,"min_rate":0.00269734,"max_rate":0.002710860501253133,"is_open":false,"buy_tag":null,"open_timestamp":1516293600000.0,"close_timestamp":1516296000000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":22.346368715083802,"open_date":"2018-01-18 18:05:00+00:00","close_date":"2018-01-18 18:30:00+00:00","open_rate":4.475e-05,"close_rate":4.587155388471177e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":1.1215538847117757e-06,"sell_reason":"roi","initial_stop_loss_abs":4.0274999999999996e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.0274999999999996e-05,"stop_loss_ratio":0.1,"min_rate":4.475e-05,"max_rate":4.587155388471177e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516298700000.0,"close_timestamp":1516300200000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":35.842293906810035,"open_date":"2018-01-18 18:25:00+00:00","close_date":"2018-01-18 18:55:00+00:00","open_rate":2.79e-05,"close_rate":2.8319548872180444e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.1954887218044365e-07,"sell_reason":"roi","initial_stop_loss_abs":2.5110000000000002e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.5110000000000002e-05,"stop_loss_ratio":0.1,"min_rate":2.79e-05,"max_rate":2.8319548872180444e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516299900000.0,"close_timestamp":1516301700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022525942001105574,"open_date":"2018-01-18 20:10:00+00:00","close_date":"2018-01-18 20:50:00+00:00","open_rate":0.04439326,"close_rate":0.04461578260651629,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.00022252260651629135,"sell_reason":"roi","initial_stop_loss_abs":0.039953933999999997,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.039953933999999997,"stop_loss_ratio":0.1,"min_rate":0.04439326,"max_rate":0.04461578260651629,"is_open":false,"buy_tag":null,"open_timestamp":1516306200000.0,"close_timestamp":1516308600000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":22.271714922048996,"open_date":"2018-01-18 21:30:00+00:00","close_date":"2018-01-19 00:35:00+00:00","open_rate":4.49e-05,"close_rate":4.51250626566416e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":185,"profit_ratio":0.0,"profit_abs":2.2506265664159932e-07,"sell_reason":"roi","initial_stop_loss_abs":4.041e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.041e-05,"stop_loss_ratio":0.1,"min_rate":4.49e-05,"max_rate":4.51250626566416e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516311000000.0,"close_timestamp":1516322100000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03502626970227671,"open_date":"2018-01-18 21:55:00+00:00","close_date":"2018-01-19 05:05:00+00:00","open_rate":0.02855,"close_rate":0.028693107769423555,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":430,"profit_ratio":-0.0,"profit_abs":0.00014310776942355607,"sell_reason":"roi","initial_stop_loss_abs":0.025695,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025695,"stop_loss_ratio":0.1,"min_rate":0.02855,"max_rate":0.028693107769423555,"is_open":false,"buy_tag":null,"open_timestamp":1516312500000.0,"close_timestamp":1516338300000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.25327812284334,"open_date":"2018-01-18 22:10:00+00:00","close_date":"2018-01-18 22:50:00+00:00","open_rate":5.796e-05,"close_rate":5.8250526315789473e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":2.905263157894727e-07,"sell_reason":"roi","initial_stop_loss_abs":5.2164000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.2164000000000004e-05,"stop_loss_ratio":0.1,"min_rate":5.796e-05,"max_rate":5.8250526315789473e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516313400000.0,"close_timestamp":1516315800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02303975994413319,"open_date":"2018-01-18 23:50:00+00:00","close_date":"2018-01-19 00:30:00+00:00","open_rate":0.04340323,"close_rate":0.04362079005012531,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.0002175600501253122,"sell_reason":"roi","initial_stop_loss_abs":0.039062907,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.039062907,"stop_loss_ratio":0.1,"min_rate":0.04340323,"max_rate":0.04362079005012531,"is_open":false,"buy_tag":null,"open_timestamp":1516319400000.0,"close_timestamp":1516321800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02244943545282195,"open_date":"2018-01-19 16:45:00+00:00","close_date":"2018-01-19 17:35:00+00:00","open_rate":0.04454455,"close_rate":0.04476783095238095,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":0.0,"profit_abs":0.0002232809523809512,"sell_reason":"roi","initial_stop_loss_abs":0.040090095000000006,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.040090095000000006,"stop_loss_ratio":0.1,"min_rate":0.04454455,"max_rate":0.04476783095238095,"is_open":false,"buy_tag":null,"open_timestamp":1516380300000.0,"close_timestamp":1516383300000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.793594306049823,"open_date":"2018-01-19 17:15:00+00:00","close_date":"2018-01-19 19:55:00+00:00","open_rate":5.62e-05,"close_rate":5.648170426065162e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":160,"profit_ratio":-0.0,"profit_abs":2.817042606516199e-07,"sell_reason":"roi","initial_stop_loss_abs":5.058e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.058e-05,"stop_loss_ratio":0.1,"min_rate":5.62e-05,"max_rate":5.648170426065162e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516382100000.0,"close_timestamp":1516391700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":23.046784973496194,"open_date":"2018-01-19 17:20:00+00:00","close_date":"2018-01-19 20:15:00+00:00","open_rate":4.339e-05,"close_rate":4.360749373433584e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":175,"profit_ratio":-0.0,"profit_abs":2.174937343358337e-07,"sell_reason":"roi","initial_stop_loss_abs":3.9051e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.9051e-05,"stop_loss_ratio":0.1,"min_rate":4.339e-05,"max_rate":4.360749373433584e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516382400000.0,"close_timestamp":1516392900000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":9.910802775024777,"open_date":"2018-01-20 04:45:00+00:00","close_date":"2018-01-20 17:35:00+00:00","open_rate":0.0001009,"close_rate":0.00010140576441102755,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":770,"profit_ratio":0.0,"profit_abs":5.057644110275549e-07,"sell_reason":"roi","initial_stop_loss_abs":9.081e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":9.081e-05,"stop_loss_ratio":0.1,"min_rate":0.0001009,"max_rate":0.00010140576441102755,"is_open":false,"buy_tag":null,"open_timestamp":1516423500000.0,"close_timestamp":1516469700000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3696789338459548,"open_date":"2018-01-20 04:50:00+00:00","close_date":"2018-01-20 15:15:00+00:00","open_rate":0.00270505,"close_rate":0.002718609147869674,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":625,"profit_ratio":-0.0,"profit_abs":1.3559147869673764e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002434545,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002434545,"stop_loss_ratio":0.1,"min_rate":0.00270505,"max_rate":0.002718609147869674,"is_open":false,"buy_tag":null,"open_timestamp":1516423800000.0,"close_timestamp":1516461300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.033333311111125925,"open_date":"2018-01-20 04:50:00+00:00","close_date":"2018-01-20 07:00:00+00:00","open_rate":0.03000002,"close_rate":0.030150396040100245,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":130,"profit_ratio":-0.0,"profit_abs":0.00015037604010024672,"sell_reason":"roi","initial_stop_loss_abs":0.027000018,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.027000018,"stop_loss_ratio":0.1,"min_rate":0.03000002,"max_rate":0.030150396040100245,"is_open":false,"buy_tag":null,"open_timestamp":1516423800000.0,"close_timestamp":1516431600000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.315018315018317,"open_date":"2018-01-20 09:00:00+00:00","close_date":"2018-01-20 09:40:00+00:00","open_rate":5.46e-05,"close_rate":5.4873684210526304e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.736842105263053e-07,"sell_reason":"roi","initial_stop_loss_abs":4.914e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.914e-05,"stop_loss_ratio":0.1,"min_rate":5.46e-05,"max_rate":5.4873684210526304e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516438800000.0,"close_timestamp":1516441200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03244412634781012,"open_date":"2018-01-20 18:25:00+00:00","close_date":"2018-01-25 03:50:00+00:00","open_rate":0.03082222,"close_rate":0.027739998,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":6325,"profit_ratio":-0.10448878,"profit_abs":-0.0030822220000000025,"sell_reason":"stop_loss","initial_stop_loss_abs":0.027739998000000002,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.027739998000000002,"stop_loss_ratio":0.1,"min_rate":0.027739998,"max_rate":0.03082222,"is_open":false,"buy_tag":null,"open_timestamp":1516472700000.0,"close_timestamp":1516852200000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011148273260677065,"open_date":"2018-01-20 22:25:00+00:00","close_date":"2018-01-20 23:15:00+00:00","open_rate":0.08969999,"close_rate":0.09014961401002504,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":-0.0,"profit_abs":0.00044962401002504593,"sell_reason":"roi","initial_stop_loss_abs":0.080729991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.080729991,"stop_loss_ratio":0.1,"min_rate":0.08969999,"max_rate":0.09014961401002504,"is_open":false,"buy_tag":null,"open_timestamp":1516487100000.0,"close_timestamp":1516490100000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06125570520324337,"open_date":"2018-01-21 02:50:00+00:00","close_date":"2018-01-21 14:30:00+00:00","open_rate":0.01632501,"close_rate":0.01640683962406015,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":700,"profit_ratio":0.0,"profit_abs":8.182962406014932e-05,"sell_reason":"roi","initial_stop_loss_abs":0.014692509000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014692509000000001,"stop_loss_ratio":0.1,"min_rate":0.01632501,"max_rate":0.01640683962406015,"is_open":false,"buy_tag":null,"open_timestamp":1516503000000.0,"close_timestamp":1516545000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.01417675579120474,"open_date":"2018-01-21 10:20:00+00:00","close_date":"2018-01-21 11:00:00+00:00","open_rate":0.070538,"close_rate":0.07089157393483708,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00035357393483707866,"sell_reason":"roi","initial_stop_loss_abs":0.0634842,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0634842,"stop_loss_ratio":0.1,"min_rate":0.070538,"max_rate":0.07089157393483708,"is_open":false,"buy_tag":null,"open_timestamp":1516530000000.0,"close_timestamp":1516532400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.864365214110546,"open_date":"2018-01-21 15:50:00+00:00","close_date":"2018-01-21 18:45:00+00:00","open_rate":5.301e-05,"close_rate":5.327571428571427e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":175,"profit_ratio":-0.0,"profit_abs":2.657142857142672e-07,"sell_reason":"roi","initial_stop_loss_abs":4.7709e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7709e-05,"stop_loss_ratio":0.1,"min_rate":5.301e-05,"max_rate":5.327571428571427e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516549800000.0,"close_timestamp":1516560300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":25.284450063211125,"open_date":"2018-01-21 16:20:00+00:00","close_date":"2018-01-21 17:00:00+00:00","open_rate":3.955e-05,"close_rate":3.9748245614035085e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":1.9824561403508552e-07,"sell_reason":"roi","initial_stop_loss_abs":3.5595e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.5595e-05,"stop_loss_ratio":0.1,"min_rate":3.955e-05,"max_rate":3.9748245614035085e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516551600000.0,"close_timestamp":1516554000000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38683971296493297,"open_date":"2018-01-21 21:15:00+00:00","close_date":"2018-01-21 21:45:00+00:00","open_rate":0.00258505,"close_rate":0.002623922932330827,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":3.8872932330826816e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002326545,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002326545,"stop_loss_ratio":0.1,"min_rate":0.00258505,"max_rate":0.002623922932330827,"is_open":false,"buy_tag":null,"open_timestamp":1516569300000.0,"close_timestamp":1516571100000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":25.621316935690498,"open_date":"2018-01-21 21:15:00+00:00","close_date":"2018-01-21 21:55:00+00:00","open_rate":3.903e-05,"close_rate":3.922563909774435e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.9563909774435151e-07,"sell_reason":"roi","initial_stop_loss_abs":3.5127e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.5127e-05,"stop_loss_ratio":0.1,"min_rate":3.903e-05,"max_rate":3.922563909774435e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516569300000.0,"close_timestamp":1516571700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.098548510313215,"open_date":"2018-01-22 00:35:00+00:00","close_date":"2018-01-22 10:35:00+00:00","open_rate":5.236e-05,"close_rate":5.262245614035087e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":600,"profit_ratio":-0.0,"profit_abs":2.624561403508717e-07,"sell_reason":"roi","initial_stop_loss_abs":4.7124e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7124e-05,"stop_loss_ratio":0.1,"min_rate":5.236e-05,"max_rate":5.262245614035087e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516581300000.0,"close_timestamp":1516617300000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.076650420912717,"open_date":"2018-01-22 01:30:00+00:00","close_date":"2018-01-22 02:10:00+00:00","open_rate":9.028e-05,"close_rate":9.07325313283208e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":4.5253132832080657e-07,"sell_reason":"roi","initial_stop_loss_abs":8.1252e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.1252e-05,"stop_loss_ratio":0.1,"min_rate":9.028e-05,"max_rate":9.07325313283208e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516584600000.0,"close_timestamp":1516587000000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3721622627465575,"open_date":"2018-01-22 12:25:00+00:00","close_date":"2018-01-22 14:35:00+00:00","open_rate":0.002687,"close_rate":0.002700468671679198,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":130,"profit_ratio":-0.0,"profit_abs":1.3468671679197925e-05,"sell_reason":"roi","initial_stop_loss_abs":0.0024183000000000004,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0024183000000000004,"stop_loss_ratio":0.1,"min_rate":0.002687,"max_rate":0.002700468671679198,"is_open":false,"buy_tag":null,"open_timestamp":1516623900000.0,"close_timestamp":1516631700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":23.99232245681382,"open_date":"2018-01-22 13:15:00+00:00","close_date":"2018-01-22 13:55:00+00:00","open_rate":4.168e-05,"close_rate":4.188892230576441e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.0892230576441054e-07,"sell_reason":"roi","initial_stop_loss_abs":3.7512e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.7512e-05,"stop_loss_ratio":0.1,"min_rate":4.168e-05,"max_rate":4.188892230576441e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516626900000.0,"close_timestamp":1516629300000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.336583153837434,"open_date":"2018-01-22 14:00:00+00:00","close_date":"2018-01-22 14:30:00+00:00","open_rate":8.821e-05,"close_rate":8.953646616541353e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":1.326466165413529e-06,"sell_reason":"roi","initial_stop_loss_abs":7.9389e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":7.9389e-05,"stop_loss_ratio":0.1,"min_rate":8.821e-05,"max_rate":8.953646616541353e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516629600000.0,"close_timestamp":1516631400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.334880123743233,"open_date":"2018-01-22 15:55:00+00:00","close_date":"2018-01-22 16:40:00+00:00","open_rate":5.172e-05,"close_rate":5.1979248120300745e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":2.592481203007459e-07,"sell_reason":"roi","initial_stop_loss_abs":4.6548e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6548e-05,"stop_loss_ratio":0.1,"min_rate":5.172e-05,"max_rate":5.1979248120300745e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516636500000.0,"close_timestamp":1516639200000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":33.04692663582287,"open_date":"2018-01-22 16:05:00+00:00","close_date":"2018-01-22 16:25:00+00:00","open_rate":3.026e-05,"close_rate":3.101839598997494e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":7.5839598997494e-07,"sell_reason":"roi","initial_stop_loss_abs":2.7234e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7234e-05,"stop_loss_ratio":0.1,"min_rate":3.026e-05,"max_rate":3.101839598997494e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516637100000.0,"close_timestamp":1516638300000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014156285390713478,"open_date":"2018-01-22 19:50:00+00:00","close_date":"2018-01-23 00:10:00+00:00","open_rate":0.07064,"close_rate":0.07099408521303258,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":260,"profit_ratio":0.0,"profit_abs":0.00035408521303258167,"sell_reason":"roi","initial_stop_loss_abs":0.063576,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.063576,"stop_loss_ratio":0.1,"min_rate":0.07064,"max_rate":0.07099408521303258,"is_open":false,"buy_tag":null,"open_timestamp":1516650600000.0,"close_timestamp":1516666200000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06080938507725528,"open_date":"2018-01-22 21:25:00+00:00","close_date":"2018-01-22 22:05:00+00:00","open_rate":0.01644483,"close_rate":0.01652726022556391,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":8.243022556390922e-05,"sell_reason":"roi","initial_stop_loss_abs":0.014800347,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014800347,"stop_loss_ratio":0.1,"min_rate":0.01644483,"max_rate":0.01652726022556391,"is_open":false,"buy_tag":null,"open_timestamp":1516656300000.0,"close_timestamp":1516658700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":23.08935580697299,"open_date":"2018-01-23 00:05:00+00:00","close_date":"2018-01-23 00:35:00+00:00","open_rate":4.331e-05,"close_rate":4.3961278195488714e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":6.512781954887175e-07,"sell_reason":"roi","initial_stop_loss_abs":3.8979e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.8979e-05,"stop_loss_ratio":0.1,"min_rate":4.331e-05,"max_rate":4.3961278195488714e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516665900000.0,"close_timestamp":1516667700000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":31.250000000000004,"open_date":"2018-01-23 01:50:00+00:00","close_date":"2018-01-23 02:15:00+00:00","open_rate":3.2e-05,"close_rate":3.2802005012531326e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":8.020050125313278e-07,"sell_reason":"roi","initial_stop_loss_abs":2.88e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.88e-05,"stop_loss_ratio":0.1,"min_rate":3.2e-05,"max_rate":3.2802005012531326e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516672200000.0,"close_timestamp":1516673700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010907854156754155,"open_date":"2018-01-23 04:25:00+00:00","close_date":"2018-01-23 05:15:00+00:00","open_rate":0.09167706,"close_rate":0.09213659413533835,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":0.0,"profit_abs":0.0004595341353383492,"sell_reason":"roi","initial_stop_loss_abs":0.08250935400000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08250935400000001,"stop_loss_ratio":0.1,"min_rate":0.09167706,"max_rate":0.09213659413533835,"is_open":false,"buy_tag":null,"open_timestamp":1516681500000.0,"close_timestamp":1516684500000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014440474918339115,"open_date":"2018-01-23 07:35:00+00:00","close_date":"2018-01-23 09:00:00+00:00","open_rate":0.0692498,"close_rate":0.06959691679197995,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":85,"profit_ratio":0.0,"profit_abs":0.0003471167919799484,"sell_reason":"roi","initial_stop_loss_abs":0.06232482,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06232482,"stop_loss_ratio":0.1,"min_rate":0.0692498,"max_rate":0.06959691679197995,"is_open":false,"buy_tag":null,"open_timestamp":1516692900000.0,"close_timestamp":1516698000000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":31.426775612822127,"open_date":"2018-01-23 10:50:00+00:00","close_date":"2018-01-23 13:05:00+00:00","open_rate":3.182e-05,"close_rate":3.197949874686716e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":135,"profit_ratio":0.0,"profit_abs":1.594987468671663e-07,"sell_reason":"roi","initial_stop_loss_abs":2.8638e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.8638e-05,"stop_loss_ratio":0.1,"min_rate":3.182e-05,"max_rate":3.197949874686716e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516704600000.0,"close_timestamp":1516712700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024461839530332683,"open_date":"2018-01-23 11:05:00+00:00","close_date":"2018-01-23 16:05:00+00:00","open_rate":0.04088,"close_rate":0.04108491228070175,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":300,"profit_ratio":-0.0,"profit_abs":0.0002049122807017481,"sell_reason":"roi","initial_stop_loss_abs":0.036792,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036792,"stop_loss_ratio":0.1,"min_rate":0.04088,"max_rate":0.04108491228070175,"is_open":false,"buy_tag":null,"open_timestamp":1516705500000.0,"close_timestamp":1516723500000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.417475728155342,"open_date":"2018-01-23 14:55:00+00:00","close_date":"2018-01-23 15:35:00+00:00","open_rate":5.15e-05,"close_rate":5.175814536340851e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.5814536340851513e-07,"sell_reason":"roi","initial_stop_loss_abs":4.635e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.635e-05,"stop_loss_ratio":0.1,"min_rate":5.15e-05,"max_rate":5.175814536340851e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516719300000.0,"close_timestamp":1516721700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011023294646713328,"open_date":"2018-01-23 16:35:00+00:00","close_date":"2018-01-24 00:05:00+00:00","open_rate":0.09071698,"close_rate":0.09117170170426064,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":450,"profit_ratio":0.0,"profit_abs":0.00045472170426064107,"sell_reason":"roi","initial_stop_loss_abs":0.081645282,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.081645282,"stop_loss_ratio":0.1,"min_rate":0.09071698,"max_rate":0.09117170170426064,"is_open":false,"buy_tag":null,"open_timestamp":1516725300000.0,"close_timestamp":1516752300000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":31.969309462915604,"open_date":"2018-01-23 17:25:00+00:00","close_date":"2018-01-23 18:45:00+00:00","open_rate":3.128e-05,"close_rate":3.1436791979949865e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.0,"profit_abs":1.5679197994986587e-07,"sell_reason":"roi","initial_stop_loss_abs":2.8152e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.8152e-05,"stop_loss_ratio":0.1,"min_rate":3.128e-05,"max_rate":3.1436791979949865e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516728300000.0,"close_timestamp":1516733100000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.465724751439037,"open_date":"2018-01-23 20:15:00+00:00","close_date":"2018-01-23 22:00:00+00:00","open_rate":9.555e-05,"close_rate":9.602894736842104e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":105,"profit_ratio":-0.0,"profit_abs":4.789473684210343e-07,"sell_reason":"roi","initial_stop_loss_abs":8.5995e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.5995e-05,"stop_loss_ratio":0.1,"min_rate":9.555e-05,"max_rate":9.602894736842104e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516738500000.0,"close_timestamp":1516744800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02450979791426522,"open_date":"2018-01-23 22:30:00+00:00","close_date":"2018-01-23 23:10:00+00:00","open_rate":0.04080001,"close_rate":0.0410045213283208,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00020451132832080554,"sell_reason":"roi","initial_stop_loss_abs":0.036720009,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036720009,"stop_loss_ratio":0.1,"min_rate":0.04080001,"max_rate":0.0410045213283208,"is_open":false,"buy_tag":null,"open_timestamp":1516746600000.0,"close_timestamp":1516749000000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.368584156498162,"open_date":"2018-01-23 23:50:00+00:00","close_date":"2018-01-24 03:35:00+00:00","open_rate":5.163e-05,"close_rate":5.18887969924812e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":225,"profit_ratio":-0.0,"profit_abs":2.587969924812037e-07,"sell_reason":"roi","initial_stop_loss_abs":4.6467e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6467e-05,"stop_loss_ratio":0.1,"min_rate":5.163e-05,"max_rate":5.18887969924812e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516751400000.0,"close_timestamp":1516764900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024747691102289384,"open_date":"2018-01-24 00:20:00+00:00","close_date":"2018-01-24 01:50:00+00:00","open_rate":0.04040781,"close_rate":0.04061035541353383,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":90,"profit_ratio":0.0,"profit_abs":0.0002025454135338306,"sell_reason":"roi","initial_stop_loss_abs":0.036367029,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036367029,"stop_loss_ratio":0.1,"min_rate":0.04040781,"max_rate":0.04061035541353383,"is_open":false,"buy_tag":null,"open_timestamp":1516753200000.0,"close_timestamp":1516758600000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.485580670303975,"open_date":"2018-01-24 06:45:00+00:00","close_date":"2018-01-24 07:25:00+00:00","open_rate":5.132e-05,"close_rate":5.157724310776942e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.5724310776941724e-07,"sell_reason":"roi","initial_stop_loss_abs":4.6188000000000006e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6188000000000006e-05,"stop_loss_ratio":0.1,"min_rate":5.132e-05,"max_rate":5.157724310776942e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516776300000.0,"close_timestamp":1516778700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.23816852635629,"open_date":"2018-01-24 14:15:00+00:00","close_date":"2018-01-24 14:25:00+00:00","open_rate":5.198e-05,"close_rate":5.432496240601503e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":10,"profit_ratio":0.03990025,"profit_abs":2.344962406015033e-06,"sell_reason":"roi","initial_stop_loss_abs":4.6782e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6782e-05,"stop_loss_ratio":0.1,"min_rate":5.198e-05,"max_rate":5.432496240601503e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516803300000.0,"close_timestamp":1516803900000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":32.74394237066143,"open_date":"2018-01-24 14:50:00+00:00","close_date":"2018-01-24 16:35:00+00:00","open_rate":3.054e-05,"close_rate":3.069308270676692e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":105,"profit_ratio":-0.0,"profit_abs":1.5308270676691466e-07,"sell_reason":"roi","initial_stop_loss_abs":2.7486000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7486000000000004e-05,"stop_loss_ratio":0.1,"min_rate":3.054e-05,"max_rate":3.069308270676692e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516805400000.0,"close_timestamp":1516811700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.795638562020944,"open_date":"2018-01-24 15:10:00+00:00","close_date":"2018-01-24 16:15:00+00:00","open_rate":9.263e-05,"close_rate":9.309431077694236e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":65,"profit_ratio":0.0,"profit_abs":4.6431077694236234e-07,"sell_reason":"roi","initial_stop_loss_abs":8.3367e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.3367e-05,"stop_loss_ratio":0.1,"min_rate":9.263e-05,"max_rate":9.309431077694236e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516806600000.0,"close_timestamp":1516810500000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.13565469713457,"open_date":"2018-01-24 22:40:00+00:00","close_date":"2018-01-24 23:25:00+00:00","open_rate":5.514e-05,"close_rate":5.54163909774436e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":2.7639097744360576e-07,"sell_reason":"roi","initial_stop_loss_abs":4.9625999999999995e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.9625999999999995e-05,"stop_loss_ratio":0.1,"min_rate":5.514e-05,"max_rate":5.54163909774436e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516833600000.0,"close_timestamp":1516836300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":20.3210729526519,"open_date":"2018-01-25 00:50:00+00:00","close_date":"2018-01-25 01:30:00+00:00","open_rate":4.921e-05,"close_rate":4.9456666666666664e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":2.4666666666666543e-07,"sell_reason":"roi","initial_stop_loss_abs":4.4289e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4289e-05,"stop_loss_ratio":0.1,"min_rate":4.921e-05,"max_rate":4.9456666666666664e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516841400000.0,"close_timestamp":1516843800000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38461538461538464,"open_date":"2018-01-25 08:15:00+00:00","close_date":"2018-01-25 12:15:00+00:00","open_rate":0.0026,"close_rate":0.002613032581453634,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":240,"profit_ratio":0.0,"profit_abs":1.3032581453634e-05,"sell_reason":"roi","initial_stop_loss_abs":0.00234,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.00234,"stop_loss_ratio":0.1,"min_rate":0.0026,"max_rate":0.002613032581453634,"is_open":false,"buy_tag":null,"open_timestamp":1516868100000.0,"close_timestamp":1516882500000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03571593119825878,"open_date":"2018-01-25 10:25:00+00:00","close_date":"2018-01-25 16:15:00+00:00","open_rate":0.02799871,"close_rate":0.028139054411027563,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":350,"profit_ratio":-0.0,"profit_abs":0.00014034441102756326,"sell_reason":"roi","initial_stop_loss_abs":0.025198839,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025198839,"stop_loss_ratio":0.1,"min_rate":0.02799871,"max_rate":0.028139054411027563,"is_open":false,"buy_tag":null,"open_timestamp":1516875900000.0,"close_timestamp":1516896900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024516401717913302,"open_date":"2018-01-25 11:00:00+00:00","close_date":"2018-01-25 11:45:00+00:00","open_rate":0.04078902,"close_rate":0.0409934762406015,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":0.00020445624060149575,"sell_reason":"roi","initial_stop_loss_abs":0.036710118,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036710118,"stop_loss_ratio":0.1,"min_rate":0.04078902,"max_rate":0.0409934762406015,"is_open":false,"buy_tag":null,"open_timestamp":1516878000000.0,"close_timestamp":1516880700000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":34.602076124567475,"open_date":"2018-01-25 13:05:00+00:00","close_date":"2018-01-25 13:45:00+00:00","open_rate":2.89e-05,"close_rate":2.904486215538847e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.4486215538846723e-07,"sell_reason":"roi","initial_stop_loss_abs":2.601e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.601e-05,"stop_loss_ratio":0.1,"min_rate":2.89e-05,"max_rate":2.904486215538847e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516885500000.0,"close_timestamp":1516887900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02432912439481303,"open_date":"2018-01-25 13:20:00+00:00","close_date":"2018-01-25 14:05:00+00:00","open_rate":0.041103,"close_rate":0.04130903007518797,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":0.00020603007518796984,"sell_reason":"roi","initial_stop_loss_abs":0.0369927,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0369927,"stop_loss_ratio":0.1,"min_rate":0.041103,"max_rate":0.04130903007518797,"is_open":false,"buy_tag":null,"open_timestamp":1516886400000.0,"close_timestamp":1516889100000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":18.422991893883566,"open_date":"2018-01-25 15:45:00+00:00","close_date":"2018-01-25 16:15:00+00:00","open_rate":5.428e-05,"close_rate":5.509624060150376e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":8.162406015037611e-07,"sell_reason":"roi","initial_stop_loss_abs":4.8852000000000006e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.8852000000000006e-05,"stop_loss_ratio":0.1,"min_rate":5.428e-05,"max_rate":5.509624060150376e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516895100000.0,"close_timestamp":1516896900000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":18.47063169560399,"open_date":"2018-01-25 17:45:00+00:00","close_date":"2018-01-25 23:15:00+00:00","open_rate":5.414e-05,"close_rate":5.441137844611528e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":330,"profit_ratio":-0.0,"profit_abs":2.713784461152774e-07,"sell_reason":"roi","initial_stop_loss_abs":4.8726e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.8726e-05,"stop_loss_ratio":0.1,"min_rate":5.414e-05,"max_rate":5.441137844611528e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516902300000.0,"close_timestamp":1516922100000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024150056861308878,"open_date":"2018-01-25 21:15:00+00:00","close_date":"2018-01-25 21:55:00+00:00","open_rate":0.04140777,"close_rate":0.0416153277443609,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0002075577443608964,"sell_reason":"roi","initial_stop_loss_abs":0.037266993000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.037266993000000005,"stop_loss_ratio":0.1,"min_rate":0.04140777,"max_rate":0.0416153277443609,"is_open":false,"buy_tag":null,"open_timestamp":1516914900000.0,"close_timestamp":1516917300000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3932224183965176,"open_date":"2018-01-26 02:05:00+00:00","close_date":"2018-01-26 02:45:00+00:00","open_rate":0.00254309,"close_rate":0.002555837318295739,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":1.2747318295739177e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002288781,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002288781,"stop_loss_ratio":0.1,"min_rate":0.00254309,"max_rate":0.002555837318295739,"is_open":false,"buy_tag":null,"open_timestamp":1516932300000.0,"close_timestamp":1516934700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.834849295523455,"open_date":"2018-01-26 02:55:00+00:00","close_date":"2018-01-26 15:10:00+00:00","open_rate":5.607e-05,"close_rate":5.6351052631578935e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":735,"profit_ratio":-0.0,"profit_abs":2.810526315789381e-07,"sell_reason":"roi","initial_stop_loss_abs":5.0463e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0463e-05,"stop_loss_ratio":0.1,"min_rate":5.607e-05,"max_rate":5.6351052631578935e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516935300000.0,"close_timestamp":1516979400000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.39400171784748983,"open_date":"2018-01-26 06:10:00+00:00","close_date":"2018-01-26 09:25:00+00:00","open_rate":0.00253806,"close_rate":0.0025507821052631577,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":195,"profit_ratio":0.0,"profit_abs":1.2722105263157733e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002284254,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002284254,"stop_loss_ratio":0.1,"min_rate":0.00253806,"max_rate":0.0025507821052631577,"is_open":false,"buy_tag":null,"open_timestamp":1516947000000.0,"close_timestamp":1516958700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024096385542168672,"open_date":"2018-01-26 07:25:00+00:00","close_date":"2018-01-26 09:55:00+00:00","open_rate":0.0415,"close_rate":0.04170802005012531,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":150,"profit_ratio":-0.0,"profit_abs":0.00020802005012530989,"sell_reason":"roi","initial_stop_loss_abs":0.03735,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.03735,"stop_loss_ratio":0.1,"min_rate":0.0415,"max_rate":0.04170802005012531,"is_open":false,"buy_tag":null,"open_timestamp":1516951500000.0,"close_timestamp":1516960500000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":18.793459875963165,"open_date":"2018-01-26 09:55:00+00:00","close_date":"2018-01-26 10:25:00+00:00","open_rate":5.321e-05,"close_rate":5.401015037593984e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":8.00150375939842e-07,"sell_reason":"roi","initial_stop_loss_abs":4.7889e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7889e-05,"stop_loss_ratio":0.1,"min_rate":5.321e-05,"max_rate":5.401015037593984e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516960500000.0,"close_timestamp":1516962300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.036074437437185386,"open_date":"2018-01-26 16:05:00+00:00","close_date":"2018-01-26 16:45:00+00:00","open_rate":0.02772046,"close_rate":0.02785940967418546,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00013894967418546025,"sell_reason":"roi","initial_stop_loss_abs":0.024948414,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.024948414,"stop_loss_ratio":0.1,"min_rate":0.02772046,"max_rate":0.02785940967418546,"is_open":false,"buy_tag":null,"open_timestamp":1516982700000.0,"close_timestamp":1516985100000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010569326272036914,"open_date":"2018-01-26 23:35:00+00:00","close_date":"2018-01-27 00:15:00+00:00","open_rate":0.09461341,"close_rate":0.09508766268170424,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.00047425268170424306,"sell_reason":"roi","initial_stop_loss_abs":0.085152069,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.085152069,"stop_loss_ratio":0.1,"min_rate":0.09461341,"max_rate":0.09508766268170424,"is_open":false,"buy_tag":null,"open_timestamp":1517009700000.0,"close_timestamp":1517012100000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":17.809439002671414,"open_date":"2018-01-27 00:35:00+00:00","close_date":"2018-01-27 01:30:00+00:00","open_rate":5.615e-05,"close_rate":5.643145363408521e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.814536340852038e-07,"sell_reason":"roi","initial_stop_loss_abs":5.0535e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0535e-05,"stop_loss_ratio":0.1,"min_rate":5.615e-05,"max_rate":5.643145363408521e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517013300000.0,"close_timestamp":1517016600000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.998560115190784,"open_date":"2018-01-27 00:45:00+00:00","close_date":"2018-01-30 04:45:00+00:00","open_rate":5.556e-05,"close_rate":5.144e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":4560,"profit_ratio":-0.07877175,"profit_abs":-4.120000000000001e-06,"sell_reason":"force_sell","initial_stop_loss_abs":5.0004000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0004000000000004e-05,"stop_loss_ratio":0.1,"min_rate":5.144e-05,"max_rate":5.556e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517013900000.0,"close_timestamp":1517287500000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014492751522789634,"open_date":"2018-01-27 02:30:00+00:00","close_date":"2018-01-27 11:25:00+00:00","open_rate":0.06900001,"close_rate":0.06934587471177944,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":535,"profit_ratio":-0.0,"profit_abs":0.0003458647117794422,"sell_reason":"roi","initial_stop_loss_abs":0.062100009000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.062100009000000005,"stop_loss_ratio":0.1,"min_rate":0.06900001,"max_rate":0.06934587471177944,"is_open":false,"buy_tag":null,"open_timestamp":1517020200000.0,"close_timestamp":1517052300000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010582027378879437,"open_date":"2018-01-27 06:25:00+00:00","close_date":"2018-01-27 07:05:00+00:00","open_rate":0.09449985,"close_rate":0.0949735334586466,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004736834586466093,"sell_reason":"roi","initial_stop_loss_abs":0.085049865,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.085049865,"stop_loss_ratio":0.1,"min_rate":0.09449985,"max_rate":0.0949735334586466,"is_open":false,"buy_tag":null,"open_timestamp":1517034300000.0,"close_timestamp":1517036700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02434885085598385,"open_date":"2018-01-27 09:40:00+00:00","close_date":"2018-01-30 04:40:00+00:00","open_rate":0.0410697,"close_rate":0.03928809,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":4020,"profit_ratio":-0.04815133,"profit_abs":-0.001781610000000003,"sell_reason":"force_sell","initial_stop_loss_abs":0.03696273,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.03696273,"stop_loss_ratio":0.1,"min_rate":0.03928809,"max_rate":0.0410697,"is_open":false,"buy_tag":null,"open_timestamp":1517046000000.0,"close_timestamp":1517287200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03508771929824561,"open_date":"2018-01-27 11:45:00+00:00","close_date":"2018-01-27 12:30:00+00:00","open_rate":0.0285,"close_rate":0.02864285714285714,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":0.00014285714285713902,"sell_reason":"roi","initial_stop_loss_abs":0.025650000000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025650000000000003,"stop_loss_ratio":0.1,"min_rate":0.0285,"max_rate":0.02864285714285714,"is_open":false,"buy_tag":null,"open_timestamp":1517053500000.0,"close_timestamp":1517056200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.034887307020861215,"open_date":"2018-01-27 12:35:00+00:00","close_date":"2018-01-27 15:25:00+00:00","open_rate":0.02866372,"close_rate":0.02880739779448621,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":170,"profit_ratio":-0.0,"profit_abs":0.00014367779448621124,"sell_reason":"roi","initial_stop_loss_abs":0.025797348,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025797348,"stop_loss_ratio":0.1,"min_rate":0.02866372,"max_rate":0.02880739779448621,"is_open":false,"buy_tag":null,"open_timestamp":1517056500000.0,"close_timestamp":1517066700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010484268355332824,"open_date":"2018-01-27 15:50:00+00:00","close_date":"2018-01-27 16:50:00+00:00","open_rate":0.095381,"close_rate":0.09585910025062656,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.0,"profit_abs":0.00047810025062657024,"sell_reason":"roi","initial_stop_loss_abs":0.0858429,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0858429,"stop_loss_ratio":0.1,"min_rate":0.095381,"max_rate":0.09585910025062656,"is_open":false,"buy_tag":null,"open_timestamp":1517068200000.0,"close_timestamp":1517071800000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014794886650455417,"open_date":"2018-01-27 17:05:00+00:00","close_date":"2018-01-27 17:45:00+00:00","open_rate":0.06759092,"close_rate":0.06792972160401002,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00033880160401002224,"sell_reason":"roi","initial_stop_loss_abs":0.060831828,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060831828,"stop_loss_ratio":0.1,"min_rate":0.06759092,"max_rate":0.06792972160401002,"is_open":false,"buy_tag":null,"open_timestamp":1517072700000.0,"close_timestamp":1517075100000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38684569885609726,"open_date":"2018-01-27 23:40:00+00:00","close_date":"2018-01-28 01:05:00+00:00","open_rate":0.00258501,"close_rate":0.002597967443609022,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":85,"profit_ratio":-0.0,"profit_abs":1.2957443609021985e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002326509,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002326509,"stop_loss_ratio":0.1,"min_rate":0.00258501,"max_rate":0.002597967443609022,"is_open":false,"buy_tag":null,"open_timestamp":1517096400000.0,"close_timestamp":1517101500000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014928710926711672,"open_date":"2018-01-28 02:25:00+00:00","close_date":"2018-01-28 08:10:00+00:00","open_rate":0.06698502,"close_rate":0.0673207845112782,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":345,"profit_ratio":-0.0,"profit_abs":0.00033576451127818874,"sell_reason":"roi","initial_stop_loss_abs":0.060286518000000004,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060286518000000004,"stop_loss_ratio":0.1,"min_rate":0.06698502,"max_rate":0.0673207845112782,"is_open":false,"buy_tag":null,"open_timestamp":1517106300000.0,"close_timestamp":1517127000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014767187899175548,"open_date":"2018-01-28 10:25:00+00:00","close_date":"2018-01-28 16:30:00+00:00","open_rate":0.0677177,"close_rate":0.06805713709273183,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":365,"profit_ratio":-0.0,"profit_abs":0.0003394370927318202,"sell_reason":"roi","initial_stop_loss_abs":0.06094593000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06094593000000001,"stop_loss_ratio":0.1,"min_rate":0.0677177,"max_rate":0.06805713709273183,"is_open":false,"buy_tag":null,"open_timestamp":1517135100000.0,"close_timestamp":1517157000000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":19.175455417066157,"open_date":"2018-01-28 20:35:00+00:00","close_date":"2018-01-28 21:35:00+00:00","open_rate":5.215e-05,"close_rate":5.2411403508771925e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":0.0,"profit_abs":2.6140350877192417e-07,"sell_reason":"roi","initial_stop_loss_abs":4.6935000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6935000000000004e-05,"stop_loss_ratio":0.1,"min_rate":5.215e-05,"max_rate":5.2411403508771925e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517171700000.0,"close_timestamp":1517175300000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.36521808998243305,"open_date":"2018-01-28 22:00:00+00:00","close_date":"2018-01-28 22:30:00+00:00","open_rate":0.00273809,"close_rate":0.002779264285714285,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.117428571428529e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002464281,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002464281,"stop_loss_ratio":0.1,"min_rate":0.00273809,"max_rate":0.002779264285714285,"is_open":false,"buy_tag":null,"open_timestamp":1517176800000.0,"close_timestamp":1517178600000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3641236272539253,"open_date":"2018-01-29 00:00:00+00:00","close_date":"2018-01-29 00:30:00+00:00","open_rate":0.00274632,"close_rate":0.002787618045112782,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.129804511278194e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002471688,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002471688,"stop_loss_ratio":0.1,"min_rate":0.00274632,"max_rate":0.002787618045112782,"is_open":false,"buy_tag":null,"open_timestamp":1517184000000.0,"close_timestamp":1517185800000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.061634117689115045,"open_date":"2018-01-29 02:15:00+00:00","close_date":"2018-01-29 03:00:00+00:00","open_rate":0.01622478,"close_rate":0.016306107218045113,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":0.0,"profit_abs":8.132721804511231e-05,"sell_reason":"roi","initial_stop_loss_abs":0.014602302000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014602302000000001,"stop_loss_ratio":0.1,"min_rate":0.01622478,"max_rate":0.016306107218045113,"is_open":false,"buy_tag":null,"open_timestamp":1517192100000.0,"close_timestamp":1517194800000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014492753623188404,"open_date":"2018-01-29 03:05:00+00:00","close_date":"2018-01-29 03:45:00+00:00","open_rate":0.069,"close_rate":0.06934586466165413,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00034586466165412166,"sell_reason":"roi","initial_stop_loss_abs":0.06210000000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06210000000000001,"stop_loss_ratio":0.1,"min_rate":0.069,"max_rate":0.06934586466165413,"is_open":false,"buy_tag":null,"open_timestamp":1517195100000.0,"close_timestamp":1517197500000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.42204454597373,"open_date":"2018-01-29 05:20:00+00:00","close_date":"2018-01-29 06:55:00+00:00","open_rate":8.755e-05,"close_rate":8.798884711779448e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":95,"profit_ratio":-0.0,"profit_abs":4.3884711779447504e-07,"sell_reason":"roi","initial_stop_loss_abs":7.879500000000001e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":7.879500000000001e-05,"stop_loss_ratio":0.1,"min_rate":8.755e-05,"max_rate":8.798884711779448e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517203200000.0,"close_timestamp":1517208900000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014650376815016871,"open_date":"2018-01-29 07:00:00+00:00","close_date":"2018-01-29 19:25:00+00:00","open_rate":0.06825763,"close_rate":0.06859977350877192,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":745,"profit_ratio":-0.0,"profit_abs":0.00034214350877191657,"sell_reason":"roi","initial_stop_loss_abs":0.061431867,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.061431867,"stop_loss_ratio":0.1,"min_rate":0.06825763,"max_rate":0.06859977350877192,"is_open":false,"buy_tag":null,"open_timestamp":1517209200000.0,"close_timestamp":1517253900000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014894490408841846,"open_date":"2018-01-29 19:45:00+00:00","close_date":"2018-01-29 20:25:00+00:00","open_rate":0.06713892,"close_rate":0.06747545593984962,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0003365359398496137,"sell_reason":"roi","initial_stop_loss_abs":0.060425028000000006,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060425028000000006,"stop_loss_ratio":0.1,"min_rate":0.06713892,"max_rate":0.06747545593984962,"is_open":false,"buy_tag":null,"open_timestamp":1517255100000.0,"close_timestamp":1517257500000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.193194537721066,"open_date":"2018-01-29 23:30:00+00:00","close_date":"2018-01-30 04:45:00+00:00","open_rate":8.934e-05,"close_rate":8.8e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":315,"profit_ratio":-0.0199116,"profit_abs":-1.3399999999999973e-06,"sell_reason":"force_sell","initial_stop_loss_abs":8.0406e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.0406e-05,"stop_loss_ratio":0.1,"min_rate":8.8e-05,"max_rate":8.934e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517268600000.0,"close_timestamp":1517287500000.0}],"locks":[],"best_pair":{"key":"LTC/BTC","trades":8,"profit_mean":0.00748129625,"profit_mean_pct":0.748129625,"profit_sum":0.05985037,"profit_sum_pct":5.99,"profit_total_abs":0.0015944746365914707,"profit_total":0.15944746365914708,"profit_total_pct":15.94,"duration_avg":"1:59:00","wins":8,"draws":0,"losses":0},"worst_pair":{"key":"XMR/BTC","trades":16,"profit_mean":-0.0027899012500000007,"profit_mean_pct":-0.2789901250000001,"profit_sum":-0.04463842000000001,"profit_sum_pct":-4.46,"profit_total_abs":0.0006671885263157366,"profit_total":0.06671885263157366,"profit_total_pct":6.67,"duration_avg":"8:41:00","wins":15,"draws":0,"losses":1},"results_per_pair":[{"key":"ETH/BTC","trades":21,"profit_mean":0.0009500057142857142,"profit_mean_pct":0.09500057142857142,"profit_sum":0.01995012,"profit_sum_pct":2.0,"profit_total_abs":0.011505731278195264,"profit_total":1.1505731278195264,"profit_total_pct":115.06,"duration_avg":"2:17:00","wins":21,"draws":0,"losses":0},{"key":"DASH/BTC","trades":16,"profit_mean":0.0018703237499999997,"profit_mean_pct":0.18703237499999997,"profit_sum":0.029925179999999996,"profit_sum_pct":2.99,"profit_total_abs":0.007475052681704161,"profit_total":0.7475052681704161,"profit_total_pct":74.75,"duration_avg":"3:03:00","wins":16,"draws":0,"losses":0},{"key":"ZEC/BTC","trades":21,"profit_mean":-0.00039290904761904774,"profit_mean_pct":-0.03929090476190478,"profit_sum":-0.008251090000000003,"profit_sum_pct":-0.83,"profit_total_abs":0.004452605639097655,"profit_total":0.4452605639097655,"profit_total_pct":44.53,"duration_avg":"4:17:00","wins":20,"draws":0,"losses":1},{"key":"LTC/BTC","trades":8,"profit_mean":0.00748129625,"profit_mean_pct":0.748129625,"profit_sum":0.05985037,"profit_sum_pct":5.99,"profit_total_abs":0.0015944746365914707,"profit_total":0.15944746365914708,"profit_total_pct":15.94,"duration_avg":"1:59:00","wins":8,"draws":0,"losses":0},{"key":"XMR/BTC","trades":16,"profit_mean":-0.0027899012500000007,"profit_mean_pct":-0.2789901250000001,"profit_sum":-0.04463842000000001,"profit_sum_pct":-4.46,"profit_total_abs":0.0006671885263157366,"profit_total":0.06671885263157366,"profit_total_pct":6.67,"duration_avg":"8:41:00","wins":15,"draws":0,"losses":1},{"key":"ETC/BTC","trades":20,"profit_mean":0.0022568569999999997,"profit_mean_pct":0.22568569999999996,"profit_sum":0.04513713999999999,"profit_sum_pct":4.51,"profit_total_abs":0.00036538235338345404,"profit_total":0.0365382353383454,"profit_total_pct":3.65,"duration_avg":"1:45:00","wins":19,"draws":0,"losses":1},{"key":"TRX/BTC","trades":15,"profit_mean":0.0023467073333333323,"profit_mean_pct":0.23467073333333321,"profit_sum":0.035200609999999986,"profit_sum_pct":3.52,"profit_total_abs":1.1329523809523682e-05,"profit_total":0.0011329523809523682,"profit_total_pct":0.11,"duration_avg":"2:28:00","wins":13,"draws":0,"losses":2},{"key":"XLM/BTC","trades":21,"profit_mean":0.0026243899999999994,"profit_mean_pct":0.2624389999999999,"profit_sum":0.05511218999999999,"profit_sum_pct":5.51,"profit_total_abs":7.340779448621465e-06,"profit_total":0.0007340779448621465,"profit_total_pct":0.07,"duration_avg":"3:21:00","wins":20,"draws":0,"losses":1},{"key":"ADA/BTC","trades":29,"profit_mean":-0.0011598141379310352,"profit_mean_pct":-0.11598141379310352,"profit_sum":-0.03363461000000002,"profit_sum_pct":-3.36,"profit_total_abs":4.916634085212862e-06,"profit_total":0.0004916634085212862,"profit_total_pct":0.05,"duration_avg":"5:35:00","wins":27,"draws":0,"losses":2},{"key":"NXT/BTC","trades":12,"profit_mean":-0.0012261025000000006,"profit_mean_pct":-0.12261025000000006,"profit_sum":-0.014713230000000008,"profit_sum_pct":-1.47,"profit_total_abs":1.4774411027568458e-06,"profit_total":0.00014774411027568458,"profit_total_pct":0.01,"duration_avg":"0:57:00","wins":11,"draws":0,"losses":1},{"key":"TOTAL","trades":179,"profit_mean":0.0008041243575418989,"profit_mean_pct":0.0804124357541899,"profit_sum":0.1439382599999999,"profit_sum_pct":14.39,"profit_total_abs":0.026085499493733857,"profit_total":2.6085499493733857,"profit_total_pct":260.85,"duration_avg":"3:40:00","wins":170,"draws":0,"losses":9}],"results_per_enter_tag":[{"key":"TOTAL","trades":179,"profit_mean":0.0008041243575418989,"profit_mean_pct":0.0804124357541899,"profit_sum":0.1439382599999999,"profit_sum_pct":14.39,"profit_total_abs":0.026085499493733857,"profit_total":2.6085499493733857,"profit_total_pct":260.85,"duration_avg":"3:40:00","wins":170,"draws":0,"losses":9}],"sell_reason_summary":[{"sell_reason":"roi","trades":170,"wins":170,"draws":0,"losses":0,"profit_mean":0.005398268352941177,"profit_mean_pct":0.54,"profit_sum":0.91770562,"profit_sum_pct":91.77,"profit_total_abs":0.031232837493733862,"profit_total":0.30590187333333335,"profit_total_pct":30.59},{"sell_reason":"stop_loss","trades":6,"wins":0,"draws":0,"losses":6,"profit_mean":-0.10448878000000002,"profit_mean_pct":-10.45,"profit_sum":-0.6269326800000001,"profit_sum_pct":-62.69,"profit_total_abs":-0.0033602680000000026,"profit_total":-0.20897756000000003,"profit_total_pct":-20.9},{"sell_reason":"force_sell","trades":3,"wins":0,"draws":0,"losses":3,"profit_mean":-0.04894489333333333,"profit_mean_pct":-4.89,"profit_sum":-0.14683468,"profit_sum_pct":-14.68,"profit_total_abs":-0.001787070000000003,"profit_total":-0.04894489333333333,"profit_total_pct":-4.89}],"left_open_trades":[{"key":"TOTAL","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0}],"total_trades":179,"total_volume":0.17900000000000005,"avg_stake_amount":0.0010000000000000002,"profit_mean":0.0008041243575418989,"profit_median":0.0,"profit_total":2.6085499493733857,"profit_total_abs":0.026085499493733857,"backtest_start":"2018-01-10 07:15:00","backtest_start_ts":1515568500000,"backtest_end":"2018-01-30 04:45:00","backtest_end_ts":1517287500000,"backtest_days":19,"backtest_run_start_ts":"2020-10-01 18:00:00+00:00","backtest_run_end_ts":"2020-10-01 18:01:00+00:00","trades_per_day":9.42,"market_change":1.22,"pairlist":[],"stake_amount":0.001,"stake_currency":"BTC","stake_currency_decimals":8,"starting_balance":0.01,"dry_run_wallet":0.01,"final_balance":0.03608549949373386,"rejected_signals":0,"max_open_trades":3,"max_open_trades_setting":3,"timeframe":"5m","timeframe_detail":"","timerange":"","enable_protections":false,"strategy_name":"StrategyTestV2","stoploss":0.1,"trailing_stop":false,"trailing_stop_positive":null,"trailing_stop_positive_offset":0.0,"trailing_only_offset_is_reached":false,"use_custom_stoploss":false,"minimal_roi":{},"use_sell_signal":true,"sell_profit_only":false,"sell_profit_offset":false,"ignore_roi_if_buy_signal":false,"backtest_best_day":0.17955111999999998,"backtest_worst_day":-0.14683468,"backtest_best_day_abs":0.0071570099,"backtest_worst_day_abs":-0.0023093218,"winning_days":19,"draw_days":0,"losing_days":2,"daily_profit":[["2018-01-10",0.0025815306],["2018-01-11",0.0049356655],["2018-01-12",0.0006395218],["2018-01-13",0.0002574589],["2018-01-14",0.0010443828],["2018-01-15",0.0024030209],["2018-01-16",0.0071570099],["2018-01-17",0.001137038],["2018-01-18",0.0013712174],["2018-01-19",0.000584673],["2018-01-20",0.0006143386],["2018-01-21",0.0004749361],["2018-01-22",9.91669e-05],["2018-01-23",0.0015726664],["2018-01-24",0.0006610219],["2018-01-25",-0.0023093218],["2018-01-26",0.0003735204],["2018-01-27",0.0023975191],["2018-01-28",0.0007295947],["2018-01-29",0.0011476082],["2018-01-30",-0.00178707]],"wins":48,"losses":9,"draws":122,"holding_avg":"3:40:00","holding_avg_s":13200.0,"winner_holding_avg":"0:24:00","winner_holding_avg_s":1440.0,"loser_holding_avg":"1 day, 5:57:00","loser_holding_avg_s":107820.0,"max_drawdown":0.21142322000000008,"max_drawdown_account":0.08674033488183289,"max_drawdown_abs":0.0030822220000000025,"drawdown_start":"2018-01-25 01:30:00","drawdown_start_ts":1516843800000.0,"drawdown_end":"2018-01-25 03:50:00","drawdown_end_ts":1516852200000.0,"max_drawdown_low":0.02245167355388436,"max_drawdown_high":0.025533895553884363,"csum_min":0.01000434887218045,"csum_max":0.03608683949373386},"TestStrategy":{"trades":[{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.37344398340249,"open_date":"2018-01-10 07:15:00+00:00","close_date":"2018-01-10 07:20:00+00:00","open_rate":9.64e-05,"close_rate":0.00010074887218045112,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":4.348872180451118e-06,"sell_reason":"roi","initial_stop_loss_abs":8.676e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.676e-05,"stop_loss_ratio":0.1,"min_rate":9.64e-05,"max_rate":0.00010074887218045112,"is_open":false,"buy_tag":null,"open_timestamp":1515568500000.0,"close_timestamp":1515568800000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":21.026072329688816,"open_date":"2018-01-10 07:15:00+00:00","close_date":"2018-01-10 07:30:00+00:00","open_rate":4.756e-05,"close_rate":4.9705563909774425e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":15,"profit_ratio":0.03990025,"profit_abs":2.1455639097744267e-06,"sell_reason":"roi","initial_stop_loss_abs":4.2804e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.2804e-05,"stop_loss_ratio":0.1,"min_rate":4.756e-05,"max_rate":4.9705563909774425e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515568500000.0,"close_timestamp":1515569400000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":29.94908655286014,"open_date":"2018-01-10 07:25:00+00:00","close_date":"2018-01-10 07:35:00+00:00","open_rate":3.339e-05,"close_rate":3.489631578947368e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":10,"profit_ratio":0.03990025,"profit_abs":1.506315789473681e-06,"sell_reason":"roi","initial_stop_loss_abs":3.0050999999999997e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.0050999999999997e-05,"stop_loss_ratio":0.1,"min_rate":3.339e-05,"max_rate":3.489631578947368e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515569100000.0,"close_timestamp":1515569700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.313531353135314,"open_date":"2018-01-10 07:25:00+00:00","close_date":"2018-01-10 07:40:00+00:00","open_rate":9.696e-05,"close_rate":0.00010133413533834584,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":15,"profit_ratio":0.03990025,"profit_abs":4.3741353383458455e-06,"sell_reason":"roi","initial_stop_loss_abs":8.7264e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.7264e-05,"stop_loss_ratio":0.1,"min_rate":9.696e-05,"max_rate":0.00010133413533834584,"is_open":false,"buy_tag":null,"open_timestamp":1515569100000.0,"close_timestamp":1515570000000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010604453870625663,"open_date":"2018-01-10 07:35:00+00:00","close_date":"2018-01-10 08:35:00+00:00","open_rate":0.0943,"close_rate":0.09477268170426063,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.0,"profit_abs":0.0004726817042606385,"sell_reason":"roi","initial_stop_loss_abs":0.08487,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08487,"stop_loss_ratio":0.1,"min_rate":0.0943,"max_rate":0.09477268170426063,"is_open":false,"buy_tag":null,"open_timestamp":1515569700000.0,"close_timestamp":1515573300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03677001860930642,"open_date":"2018-01-10 07:40:00+00:00","close_date":"2018-01-10 08:10:00+00:00","open_rate":0.02719607,"close_rate":0.02760503345864661,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.00040896345864661204,"sell_reason":"roi","initial_stop_loss_abs":0.024476463,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.024476463,"stop_loss_ratio":0.1,"min_rate":0.02719607,"max_rate":0.02760503345864661,"is_open":false,"buy_tag":null,"open_timestamp":1515570000000.0,"close_timestamp":1515571800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.021575196463739,"open_date":"2018-01-10 08:15:00+00:00","close_date":"2018-01-10 09:55:00+00:00","open_rate":0.04634952,"close_rate":0.046581848421052625,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":100,"profit_ratio":0.0,"profit_abs":0.0002323284210526272,"sell_reason":"roi","initial_stop_loss_abs":0.041714568,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.041714568,"stop_loss_ratio":0.1,"min_rate":0.04634952,"max_rate":0.046581848421052625,"is_open":false,"buy_tag":null,"open_timestamp":1515572100000.0,"close_timestamp":1515578100000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":32.615786040443574,"open_date":"2018-01-10 14:45:00+00:00","close_date":"2018-01-10 15:50:00+00:00","open_rate":3.066e-05,"close_rate":3.081368421052631e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":65,"profit_ratio":-0.0,"profit_abs":1.5368421052630647e-07,"sell_reason":"roi","initial_stop_loss_abs":2.7594e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7594e-05,"stop_loss_ratio":0.1,"min_rate":3.066e-05,"max_rate":3.081368421052631e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515595500000.0,"close_timestamp":1515599400000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.05917194776300452,"open_date":"2018-01-10 16:35:00+00:00","close_date":"2018-01-10 17:15:00+00:00","open_rate":0.0168999,"close_rate":0.016984611278195488,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":8.471127819548868e-05,"sell_reason":"roi","initial_stop_loss_abs":0.01520991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.01520991,"stop_loss_ratio":0.1,"min_rate":0.0168999,"max_rate":0.016984611278195488,"is_open":false,"buy_tag":null,"open_timestamp":1515602100000.0,"close_timestamp":1515604500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010949822656672253,"open_date":"2018-01-10 16:40:00+00:00","close_date":"2018-01-10 17:20:00+00:00","open_rate":0.09132568,"close_rate":0.0917834528320802,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004577728320801916,"sell_reason":"roi","initial_stop_loss_abs":0.08219311200000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08219311200000001,"stop_loss_ratio":0.1,"min_rate":0.09132568,"max_rate":0.0917834528320802,"is_open":false,"buy_tag":null,"open_timestamp":1515602400000.0,"close_timestamp":1515604800000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011238476768326556,"open_date":"2018-01-10 18:50:00+00:00","close_date":"2018-01-10 19:45:00+00:00","open_rate":0.08898003,"close_rate":0.08942604518796991,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":0.00044601518796991146,"sell_reason":"roi","initial_stop_loss_abs":0.080082027,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.080082027,"stop_loss_ratio":0.1,"min_rate":0.08898003,"max_rate":0.08942604518796991,"is_open":false,"buy_tag":null,"open_timestamp":1515610200000.0,"close_timestamp":1515613500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011682232072680307,"open_date":"2018-01-10 22:15:00+00:00","close_date":"2018-01-10 23:00:00+00:00","open_rate":0.08560008,"close_rate":0.08602915308270676,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":0.0,"profit_abs":0.00042907308270676014,"sell_reason":"roi","initial_stop_loss_abs":0.077040072,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.077040072,"stop_loss_ratio":0.1,"min_rate":0.08560008,"max_rate":0.08602915308270676,"is_open":false,"buy_tag":null,"open_timestamp":1515622500000.0,"close_timestamp":1515625200000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.4014726015023105,"open_date":"2018-01-10 22:50:00+00:00","close_date":"2018-01-10 23:20:00+00:00","open_rate":0.00249083,"close_rate":0.0025282860902255634,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":3.745609022556351e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002241747,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002241747,"stop_loss_ratio":0.1,"min_rate":0.00249083,"max_rate":0.0025282860902255634,"is_open":false,"buy_tag":null,"open_timestamp":1515624600000.0,"close_timestamp":1515626400000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":33.090668431502316,"open_date":"2018-01-10 23:15:00+00:00","close_date":"2018-01-11 00:15:00+00:00","open_rate":3.022e-05,"close_rate":3.037147869674185e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.0,"profit_abs":1.5147869674185174e-07,"sell_reason":"roi","initial_stop_loss_abs":2.7198e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7198e-05,"stop_loss_ratio":0.1,"min_rate":3.022e-05,"max_rate":3.037147869674185e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515626100000.0,"close_timestamp":1515629700000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.41034058268362744,"open_date":"2018-01-10 23:40:00+00:00","close_date":"2018-01-11 00:05:00+00:00","open_rate":0.002437,"close_rate":0.0024980776942355883,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":6.107769423558838e-05,"sell_reason":"roi","initial_stop_loss_abs":0.0021933,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0021933,"stop_loss_ratio":0.1,"min_rate":0.002437,"max_rate":0.0024980776942355883,"is_open":false,"buy_tag":null,"open_timestamp":1515627600000.0,"close_timestamp":1515629100000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02095643931654345,"open_date":"2018-01-11 00:00:00+00:00","close_date":"2018-01-11 00:35:00+00:00","open_rate":0.04771803,"close_rate":0.04843559436090225,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0007175643609022495,"sell_reason":"roi","initial_stop_loss_abs":0.042946227000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.042946227000000003,"stop_loss_ratio":0.1,"min_rate":0.04771803,"max_rate":0.04843559436090225,"is_open":false,"buy_tag":null,"open_timestamp":1515628800000.0,"close_timestamp":1515630900000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":27.389756231169542,"open_date":"2018-01-11 03:40:00+00:00","close_date":"2018-01-11 04:25:00+00:00","open_rate":3.651e-05,"close_rate":3.2859000000000005e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.10448878,"profit_abs":-3.650999999999996e-06,"sell_reason":"stop_loss","initial_stop_loss_abs":3.2859000000000005e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.2859000000000005e-05,"stop_loss_ratio":0.1,"min_rate":3.2859000000000005e-05,"max_rate":3.651e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515642000000.0,"close_timestamp":1515644700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011332594070446804,"open_date":"2018-01-11 03:55:00+00:00","close_date":"2018-01-11 04:25:00+00:00","open_rate":0.08824105,"close_rate":0.08956798308270676,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.0013269330827067605,"sell_reason":"roi","initial_stop_loss_abs":0.079416945,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.079416945,"stop_loss_ratio":0.1,"min_rate":0.08824105,"max_rate":0.08956798308270676,"is_open":false,"buy_tag":null,"open_timestamp":1515642900000.0,"close_timestamp":1515644700000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.411522633744856,"open_date":"2018-01-11 04:00:00+00:00","close_date":"2018-01-11 04:50:00+00:00","open_rate":0.00243,"close_rate":0.002442180451127819,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":-0.0,"profit_abs":1.2180451127819219e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002187,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002187,"stop_loss_ratio":0.1,"min_rate":0.00243,"max_rate":0.002442180451127819,"is_open":false,"buy_tag":null,"open_timestamp":1515643200000.0,"close_timestamp":1515646200000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022001890402423376,"open_date":"2018-01-11 04:30:00+00:00","close_date":"2018-01-11 04:55:00+00:00","open_rate":0.04545064,"close_rate":0.046589753784461146,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":0.001139113784461146,"sell_reason":"roi","initial_stop_loss_abs":0.040905576,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.040905576,"stop_loss_ratio":0.1,"min_rate":0.04545064,"max_rate":0.046589753784461146,"is_open":false,"buy_tag":null,"open_timestamp":1515645000000.0,"close_timestamp":1515646500000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":29.655990510083036,"open_date":"2018-01-11 04:30:00+00:00","close_date":"2018-01-11 04:50:00+00:00","open_rate":3.372e-05,"close_rate":3.456511278195488e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":8.4511278195488e-07,"sell_reason":"roi","initial_stop_loss_abs":3.0348e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.0348e-05,"stop_loss_ratio":0.1,"min_rate":3.372e-05,"max_rate":3.456511278195488e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515645000000.0,"close_timestamp":1515646200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.037821482602118005,"open_date":"2018-01-11 04:55:00+00:00","close_date":"2018-01-11 05:15:00+00:00","open_rate":0.02644,"close_rate":0.02710265664160401,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":0.0006626566416040071,"sell_reason":"roi","initial_stop_loss_abs":0.023796,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.023796,"stop_loss_ratio":0.1,"min_rate":0.02644,"max_rate":0.02710265664160401,"is_open":false,"buy_tag":null,"open_timestamp":1515646500000.0,"close_timestamp":1515647700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011348161597821153,"open_date":"2018-01-11 11:20:00+00:00","close_date":"2018-01-11 12:00:00+00:00","open_rate":0.08812,"close_rate":0.08856170426065162,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004417042606516125,"sell_reason":"roi","initial_stop_loss_abs":0.079308,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.079308,"stop_loss_ratio":0.1,"min_rate":0.08812,"max_rate":0.08856170426065162,"is_open":false,"buy_tag":null,"open_timestamp":1515669600000.0,"close_timestamp":1515672000000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.037263696923919086,"open_date":"2018-01-11 11:35:00+00:00","close_date":"2018-01-11 12:15:00+00:00","open_rate":0.02683577,"close_rate":0.026970285137844607,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00013451513784460897,"sell_reason":"roi","initial_stop_loss_abs":0.024152193,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.024152193,"stop_loss_ratio":0.1,"min_rate":0.02683577,"max_rate":0.026970285137844607,"is_open":false,"buy_tag":null,"open_timestamp":1515670500000.0,"close_timestamp":1515672900000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":20.329335230737954,"open_date":"2018-01-11 14:00:00+00:00","close_date":"2018-01-11 14:25:00+00:00","open_rate":4.919e-05,"close_rate":5.04228320802005e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":1.232832080200495e-06,"sell_reason":"roi","initial_stop_loss_abs":4.4271000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4271000000000004e-05,"stop_loss_ratio":0.1,"min_rate":4.919e-05,"max_rate":5.04228320802005e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515679200000.0,"close_timestamp":1515680700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.01138317402960718,"open_date":"2018-01-11 19:25:00+00:00","close_date":"2018-01-11 20:35:00+00:00","open_rate":0.08784896,"close_rate":0.08828930566416039,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":70,"profit_ratio":-0.0,"profit_abs":0.0004403456641603881,"sell_reason":"roi","initial_stop_loss_abs":0.079064064,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.079064064,"stop_loss_ratio":0.1,"min_rate":0.08784896,"max_rate":0.08828930566416039,"is_open":false,"buy_tag":null,"open_timestamp":1515698700000.0,"close_timestamp":1515702900000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.58863858961802,"open_date":"2018-01-11 22:35:00+00:00","close_date":"2018-01-11 23:30:00+00:00","open_rate":5.105e-05,"close_rate":5.130588972431077e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.558897243107704e-07,"sell_reason":"roi","initial_stop_loss_abs":4.5945e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.5945e-05,"stop_loss_ratio":0.1,"min_rate":5.105e-05,"max_rate":5.130588972431077e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515710100000.0,"close_timestamp":1515713400000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":25.252525252525253,"open_date":"2018-01-11 22:55:00+00:00","close_date":"2018-01-11 23:25:00+00:00","open_rate":3.96e-05,"close_rate":4.019548872180451e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":5.954887218045116e-07,"sell_reason":"roi","initial_stop_loss_abs":3.5640000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.5640000000000004e-05,"stop_loss_ratio":0.1,"min_rate":3.96e-05,"max_rate":4.019548872180451e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515711300000.0,"close_timestamp":1515713100000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":34.66204506065858,"open_date":"2018-01-11 22:55:00+00:00","close_date":"2018-01-11 23:35:00+00:00","open_rate":2.885e-05,"close_rate":2.899461152882205e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.4461152882205115e-07,"sell_reason":"roi","initial_stop_loss_abs":2.5965e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.5965e-05,"stop_loss_ratio":0.1,"min_rate":2.885e-05,"max_rate":2.899461152882205e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515711300000.0,"close_timestamp":1515713700000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03780718336483932,"open_date":"2018-01-11 23:30:00+00:00","close_date":"2018-01-12 00:05:00+00:00","open_rate":0.02645,"close_rate":0.026847744360902256,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0003977443609022545,"sell_reason":"roi","initial_stop_loss_abs":0.023805000000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.023805000000000003,"stop_loss_ratio":0.1,"min_rate":0.02645,"max_rate":0.026847744360902256,"is_open":false,"buy_tag":null,"open_timestamp":1515713400000.0,"close_timestamp":1515715500000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.020833333333333332,"open_date":"2018-01-11 23:55:00+00:00","close_date":"2018-01-12 01:15:00+00:00","open_rate":0.048,"close_rate":0.04824060150375939,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.0,"profit_abs":0.00024060150375938838,"sell_reason":"roi","initial_stop_loss_abs":0.0432,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0432,"stop_loss_ratio":0.1,"min_rate":0.048,"max_rate":0.04824060150375939,"is_open":false,"buy_tag":null,"open_timestamp":1515714900000.0,"close_timestamp":1515719700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":21.31287297527707,"open_date":"2018-01-12 21:15:00+00:00","close_date":"2018-01-12 21:40:00+00:00","open_rate":4.692e-05,"close_rate":4.809593984962405e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":1.1759398496240516e-06,"sell_reason":"roi","initial_stop_loss_abs":4.2227999999999996e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.2227999999999996e-05,"stop_loss_ratio":0.1,"min_rate":4.692e-05,"max_rate":4.809593984962405e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515791700000.0,"close_timestamp":1515793200000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38915654211062944,"open_date":"2018-01-13 00:55:00+00:00","close_date":"2018-01-13 06:20:00+00:00","open_rate":0.00256966,"close_rate":0.0025825405012531327,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":325,"profit_ratio":-0.0,"profit_abs":1.2880501253132587e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002312694,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002312694,"stop_loss_ratio":0.1,"min_rate":0.00256966,"max_rate":0.0025825405012531327,"is_open":false,"buy_tag":null,"open_timestamp":1515804900000.0,"close_timestamp":1515824400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":15.96933886937081,"open_date":"2018-01-13 10:55:00+00:00","close_date":"2018-01-13 11:35:00+00:00","open_rate":6.262e-05,"close_rate":6.293388471177944e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":3.138847117794446e-07,"sell_reason":"roi","initial_stop_loss_abs":5.6358e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.6358e-05,"stop_loss_ratio":0.1,"min_rate":6.262e-05,"max_rate":6.293388471177944e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515840900000.0,"close_timestamp":1515843300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":21.141649048625794,"open_date":"2018-01-13 13:05:00+00:00","close_date":"2018-01-15 14:10:00+00:00","open_rate":4.73e-05,"close_rate":4.753709273182957e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":2945,"profit_ratio":0.0,"profit_abs":2.3709273182957117e-07,"sell_reason":"roi","initial_stop_loss_abs":4.257e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.257e-05,"stop_loss_ratio":0.1,"min_rate":4.73e-05,"max_rate":4.753709273182957e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515848700000.0,"close_timestamp":1516025400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":16.49348507339601,"open_date":"2018-01-13 13:30:00+00:00","close_date":"2018-01-13 14:45:00+00:00","open_rate":6.063e-05,"close_rate":6.0933909774436085e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":75,"profit_ratio":-0.0,"profit_abs":3.039097744360846e-07,"sell_reason":"roi","initial_stop_loss_abs":5.4567e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.4567e-05,"stop_loss_ratio":0.1,"min_rate":6.063e-05,"max_rate":6.0933909774436085e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515850200000.0,"close_timestamp":1515854700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":9.023641941887746,"open_date":"2018-01-13 13:40:00+00:00","close_date":"2018-01-13 23:30:00+00:00","open_rate":0.00011082,"close_rate":0.00011137548872180448,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":590,"profit_ratio":-0.0,"profit_abs":5.554887218044781e-07,"sell_reason":"roi","initial_stop_loss_abs":9.9738e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":9.9738e-05,"stop_loss_ratio":0.1,"min_rate":0.00011082,"max_rate":0.00011137548872180448,"is_open":false,"buy_tag":null,"open_timestamp":1515850800000.0,"close_timestamp":1515886200000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":16.863406408094438,"open_date":"2018-01-13 15:15:00+00:00","close_date":"2018-01-13 15:55:00+00:00","open_rate":5.93e-05,"close_rate":5.9597243107769415e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.9724310776941686e-07,"sell_reason":"roi","initial_stop_loss_abs":5.337e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.337e-05,"stop_loss_ratio":0.1,"min_rate":5.93e-05,"max_rate":5.9597243107769415e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515856500000.0,"close_timestamp":1515858900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.020618543947292404,"open_date":"2018-01-13 16:30:00+00:00","close_date":"2018-01-13 17:10:00+00:00","open_rate":0.04850003,"close_rate":0.04874313791979949,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00024310791979949287,"sell_reason":"roi","initial_stop_loss_abs":0.043650027,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.043650027,"stop_loss_ratio":0.1,"min_rate":0.04850003,"max_rate":0.04874313791979949,"is_open":false,"buy_tag":null,"open_timestamp":1515861000000.0,"close_timestamp":1515863400000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010178097365511457,"open_date":"2018-01-13 22:05:00+00:00","close_date":"2018-01-14 06:25:00+00:00","open_rate":0.09825019,"close_rate":0.09874267215538848,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":500,"profit_ratio":-0.0,"profit_abs":0.0004924821553884823,"sell_reason":"roi","initial_stop_loss_abs":0.088425171,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.088425171,"stop_loss_ratio":0.1,"min_rate":0.09825019,"max_rate":0.09874267215538848,"is_open":false,"buy_tag":null,"open_timestamp":1515881100000.0,"close_timestamp":1515911100000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":16.616816218012627,"open_date":"2018-01-14 00:20:00+00:00","close_date":"2018-01-14 22:55:00+00:00","open_rate":6.018e-05,"close_rate":6.048165413533834e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":1355,"profit_ratio":0.0,"profit_abs":3.0165413533833987e-07,"sell_reason":"roi","initial_stop_loss_abs":5.4162e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.4162e-05,"stop_loss_ratio":0.1,"min_rate":6.018e-05,"max_rate":6.048165413533834e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515889200000.0,"close_timestamp":1515970500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010246952581919518,"open_date":"2018-01-14 12:45:00+00:00","close_date":"2018-01-14 13:25:00+00:00","open_rate":0.09758999,"close_rate":0.0980791628822055,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004891728822054991,"sell_reason":"roi","initial_stop_loss_abs":0.087830991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.087830991,"stop_loss_ratio":0.1,"min_rate":0.09758999,"max_rate":0.0980791628822055,"is_open":false,"buy_tag":null,"open_timestamp":1515933900000.0,"close_timestamp":1515936300000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3215434083601286,"open_date":"2018-01-14 15:30:00+00:00","close_date":"2018-01-14 16:00:00+00:00","open_rate":0.00311,"close_rate":0.0031567669172932328,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.676691729323286e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002799,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002799,"stop_loss_ratio":0.1,"min_rate":0.00311,"max_rate":0.0031567669172932328,"is_open":false,"buy_tag":null,"open_timestamp":1515943800000.0,"close_timestamp":1515945600000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.32010140812609433,"open_date":"2018-01-14 20:45:00+00:00","close_date":"2018-01-14 22:15:00+00:00","open_rate":0.00312401,"close_rate":0.003139669197994987,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":90,"profit_ratio":-0.0,"profit_abs":1.5659197994987058e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002811609,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002811609,"stop_loss_ratio":0.1,"min_rate":0.00312401,"max_rate":0.003139669197994987,"is_open":false,"buy_tag":null,"open_timestamp":1515962700000.0,"close_timestamp":1515968100000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.057247866085791646,"open_date":"2018-01-14 23:35:00+00:00","close_date":"2018-01-15 00:30:00+00:00","open_rate":0.0174679,"close_rate":0.017555458395989976,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":0.0,"profit_abs":8.755839598997492e-05,"sell_reason":"roi","initial_stop_loss_abs":0.015721110000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.015721110000000003,"stop_loss_ratio":0.1,"min_rate":0.0174679,"max_rate":0.017555458395989976,"is_open":false,"buy_tag":null,"open_timestamp":1515972900000.0,"close_timestamp":1515976200000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.013611282991367997,"open_date":"2018-01-14 23:45:00+00:00","close_date":"2018-01-15 00:25:00+00:00","open_rate":0.07346846,"close_rate":0.07383672295739348,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00036826295739347814,"sell_reason":"roi","initial_stop_loss_abs":0.066121614,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.066121614,"stop_loss_ratio":0.1,"min_rate":0.07346846,"max_rate":0.07383672295739348,"is_open":false,"buy_tag":null,"open_timestamp":1515973500000.0,"close_timestamp":1515975900000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010204706410596568,"open_date":"2018-01-15 02:25:00+00:00","close_date":"2018-01-15 03:05:00+00:00","open_rate":0.097994,"close_rate":0.09848519799498744,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004911979949874384,"sell_reason":"roi","initial_stop_loss_abs":0.0881946,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0881946,"stop_loss_ratio":0.1,"min_rate":0.097994,"max_rate":0.09848519799498744,"is_open":false,"buy_tag":null,"open_timestamp":1515983100000.0,"close_timestamp":1515985500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010353038616834042,"open_date":"2018-01-15 07:20:00+00:00","close_date":"2018-01-15 08:00:00+00:00","open_rate":0.09659,"close_rate":0.09707416040100247,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004841604010024786,"sell_reason":"roi","initial_stop_loss_abs":0.086931,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.086931,"stop_loss_ratio":0.1,"min_rate":0.09659,"max_rate":0.09707416040100247,"is_open":false,"buy_tag":null,"open_timestamp":1516000800000.0,"close_timestamp":1516003200000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.013016921998599,"open_date":"2018-01-15 08:20:00+00:00","close_date":"2018-01-15 08:55:00+00:00","open_rate":9.987e-05,"close_rate":0.00010137180451127818,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":1.501804511278178e-06,"sell_reason":"roi","initial_stop_loss_abs":8.9883e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.9883e-05,"stop_loss_ratio":0.1,"min_rate":9.987e-05,"max_rate":0.00010137180451127818,"is_open":false,"buy_tag":null,"open_timestamp":1516004400000.0,"close_timestamp":1516006500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010537752023511832,"open_date":"2018-01-15 12:10:00+00:00","close_date":"2018-01-16 02:50:00+00:00","open_rate":0.0948969,"close_rate":0.09537257368421052,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":880,"profit_ratio":0.0,"profit_abs":0.0004756736842105175,"sell_reason":"roi","initial_stop_loss_abs":0.08540721000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08540721000000001,"stop_loss_ratio":0.1,"min_rate":0.0948969,"max_rate":0.09537257368421052,"is_open":false,"buy_tag":null,"open_timestamp":1516018200000.0,"close_timestamp":1516071000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014084507042253523,"open_date":"2018-01-15 14:10:00+00:00","close_date":"2018-01-15 17:40:00+00:00","open_rate":0.071,"close_rate":0.07135588972431077,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":210,"profit_ratio":-0.0,"profit_abs":0.00035588972431077615,"sell_reason":"roi","initial_stop_loss_abs":0.0639,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0639,"stop_loss_ratio":0.1,"min_rate":0.071,"max_rate":0.07135588972431077,"is_open":false,"buy_tag":null,"open_timestamp":1516025400000.0,"close_timestamp":1516038000000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.021736763017766978,"open_date":"2018-01-15 14:30:00+00:00","close_date":"2018-01-15 15:10:00+00:00","open_rate":0.04600501,"close_rate":0.046235611553884705,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00023060155388470588,"sell_reason":"roi","initial_stop_loss_abs":0.041404509,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.041404509,"stop_loss_ratio":0.1,"min_rate":0.04600501,"max_rate":0.046235611553884705,"is_open":false,"buy_tag":null,"open_timestamp":1516026600000.0,"close_timestamp":1516029000000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.595465140919686,"open_date":"2018-01-15 18:10:00+00:00","close_date":"2018-01-15 19:25:00+00:00","open_rate":9.438e-05,"close_rate":9.485308270676693e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":75,"profit_ratio":-0.0,"profit_abs":4.7308270676692514e-07,"sell_reason":"roi","initial_stop_loss_abs":8.4942e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.4942e-05,"stop_loss_ratio":0.1,"min_rate":9.438e-05,"max_rate":9.485308270676693e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516039800000.0,"close_timestamp":1516044300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.032894726021471705,"open_date":"2018-01-15 18:35:00+00:00","close_date":"2018-01-15 19:15:00+00:00","open_rate":0.03040001,"close_rate":0.030552391002506264,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0001523810025062626,"sell_reason":"roi","initial_stop_loss_abs":0.027360009,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.027360009,"stop_loss_ratio":0.1,"min_rate":0.03040001,"max_rate":0.030552391002506264,"is_open":false,"buy_tag":null,"open_timestamp":1516041300000.0,"close_timestamp":1516043700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.13208840157615,"open_date":"2018-01-15 20:25:00+00:00","close_date":"2018-01-16 08:25:00+00:00","open_rate":5.837e-05,"close_rate":5.2533e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":720,"profit_ratio":-0.10448878,"profit_abs":-5.8369999999999985e-06,"sell_reason":"stop_loss","initial_stop_loss_abs":5.2533e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.2533e-05,"stop_loss_ratio":0.1,"min_rate":5.2533e-05,"max_rate":5.837e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516047900000.0,"close_timestamp":1516091100000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.021722130506560085,"open_date":"2018-01-15 20:40:00+00:00","close_date":"2018-01-15 22:00:00+00:00","open_rate":0.046036,"close_rate":0.04626675689223057,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.0,"profit_abs":0.00023075689223057277,"sell_reason":"roi","initial_stop_loss_abs":0.0414324,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0414324,"stop_loss_ratio":0.1,"min_rate":0.046036,"max_rate":0.04626675689223057,"is_open":false,"buy_tag":null,"open_timestamp":1516048800000.0,"close_timestamp":1516053600000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.34861425832316545,"open_date":"2018-01-16 00:30:00+00:00","close_date":"2018-01-16 01:10:00+00:00","open_rate":0.0028685,"close_rate":0.0028828784461152877,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.4378446115287727e-05,"sell_reason":"roi","initial_stop_loss_abs":0.00258165,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.00258165,"stop_loss_ratio":0.1,"min_rate":0.0028685,"max_rate":0.0028828784461152877,"is_open":false,"buy_tag":null,"open_timestamp":1516062600000.0,"close_timestamp":1516065000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014854967241083492,"open_date":"2018-01-16 01:15:00+00:00","close_date":"2018-01-16 02:35:00+00:00","open_rate":0.06731755,"close_rate":0.0676549813283208,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":0.0,"profit_abs":0.00033743132832080025,"sell_reason":"roi","initial_stop_loss_abs":0.060585795000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060585795000000005,"stop_loss_ratio":0.1,"min_rate":0.06731755,"max_rate":0.0676549813283208,"is_open":false,"buy_tag":null,"open_timestamp":1516065300000.0,"close_timestamp":1516070100000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010848794492804754,"open_date":"2018-01-16 07:45:00+00:00","close_date":"2018-01-16 08:40:00+00:00","open_rate":0.09217614,"close_rate":0.09263817578947368,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":0.0,"profit_abs":0.0004620357894736804,"sell_reason":"roi","initial_stop_loss_abs":0.082958526,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.082958526,"stop_loss_ratio":0.1,"min_rate":0.09217614,"max_rate":0.09263817578947368,"is_open":false,"buy_tag":null,"open_timestamp":1516088700000.0,"close_timestamp":1516092000000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06060606060606061,"open_date":"2018-01-16 08:35:00+00:00","close_date":"2018-01-16 08:55:00+00:00","open_rate":0.0165,"close_rate":0.016913533834586467,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":0.00041353383458646656,"sell_reason":"roi","initial_stop_loss_abs":0.01485,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.01485,"stop_loss_ratio":0.1,"min_rate":0.0165,"max_rate":0.016913533834586467,"is_open":false,"buy_tag":null,"open_timestamp":1516091700000.0,"close_timestamp":1516092900000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":12.57387149503332,"open_date":"2018-01-16 08:35:00+00:00","close_date":"2018-01-16 08:40:00+00:00","open_rate":7.953e-05,"close_rate":8.311781954887218e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":3.587819548872171e-06,"sell_reason":"roi","initial_stop_loss_abs":7.157700000000001e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":7.157700000000001e-05,"stop_loss_ratio":0.1,"min_rate":7.953e-05,"max_rate":8.311781954887218e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516091700000.0,"close_timestamp":1516092000000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022122914915269236,"open_date":"2018-01-16 08:45:00+00:00","close_date":"2018-01-16 09:50:00+00:00","open_rate":0.045202,"close_rate":0.04542857644110275,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":65,"profit_ratio":-0.0,"profit_abs":0.00022657644110275071,"sell_reason":"roi","initial_stop_loss_abs":0.0406818,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0406818,"stop_loss_ratio":0.1,"min_rate":0.045202,"max_rate":0.04542857644110275,"is_open":false,"buy_tag":null,"open_timestamp":1516092300000.0,"close_timestamp":1516096200000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.054878048780488,"open_date":"2018-01-16 09:15:00+00:00","close_date":"2018-01-16 09:45:00+00:00","open_rate":5.248e-05,"close_rate":5.326917293233082e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":7.891729323308177e-07,"sell_reason":"roi","initial_stop_loss_abs":4.7232e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7232e-05,"stop_loss_ratio":0.1,"min_rate":5.248e-05,"max_rate":5.326917293233082e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516094100000.0,"close_timestamp":1516095900000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03457434486802627,"open_date":"2018-01-16 09:15:00+00:00","close_date":"2018-01-16 09:55:00+00:00","open_rate":0.02892318,"close_rate":0.02906815834586466,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.0001449783458646603,"sell_reason":"roi","initial_stop_loss_abs":0.026030862000000002,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.026030862000000002,"stop_loss_ratio":0.1,"min_rate":0.02892318,"max_rate":0.02906815834586466,"is_open":false,"buy_tag":null,"open_timestamp":1516094100000.0,"close_timestamp":1516096500000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.38735944164405,"open_date":"2018-01-16 09:50:00+00:00","close_date":"2018-01-16 10:10:00+00:00","open_rate":5.158e-05,"close_rate":5.287273182957392e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":1.2927318295739246e-06,"sell_reason":"roi","initial_stop_loss_abs":4.6422e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6422e-05,"stop_loss_ratio":0.1,"min_rate":5.158e-05,"max_rate":5.287273182957392e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516096200000.0,"close_timestamp":1516097400000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.035357778286929785,"open_date":"2018-01-16 10:05:00+00:00","close_date":"2018-01-16 10:35:00+00:00","open_rate":0.02828232,"close_rate":0.02870761804511278,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.00042529804511277913,"sell_reason":"roi","initial_stop_loss_abs":0.025454088,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025454088,"stop_loss_ratio":0.1,"min_rate":0.02828232,"max_rate":0.02870761804511278,"is_open":false,"buy_tag":null,"open_timestamp":1516097100000.0,"close_timestamp":1516098900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022948496230938982,"open_date":"2018-01-16 10:05:00+00:00","close_date":"2018-01-16 10:40:00+00:00","open_rate":0.04357584,"close_rate":0.044231115789473675,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0006552757894736777,"sell_reason":"roi","initial_stop_loss_abs":0.039218256,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.039218256,"stop_loss_ratio":0.1,"min_rate":0.04357584,"max_rate":0.044231115789473675,"is_open":false,"buy_tag":null,"open_timestamp":1516097100000.0,"close_timestamp":1516099200000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.64975755315181,"open_date":"2018-01-16 13:45:00+00:00","close_date":"2018-01-16 14:20:00+00:00","open_rate":5.362e-05,"close_rate":5.442631578947368e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":8.063157894736843e-07,"sell_reason":"roi","initial_stop_loss_abs":4.8258e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.8258e-05,"stop_loss_ratio":0.1,"min_rate":5.362e-05,"max_rate":5.442631578947368e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516110300000.0,"close_timestamp":1516112400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.86080724254998,"open_date":"2018-01-16 17:30:00+00:00","close_date":"2018-01-16 18:25:00+00:00","open_rate":5.302e-05,"close_rate":5.328576441102756e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.6576441102756397e-07,"sell_reason":"roi","initial_stop_loss_abs":4.7718e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7718e-05,"stop_loss_ratio":0.1,"min_rate":5.302e-05,"max_rate":5.328576441102756e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516123800000.0,"close_timestamp":1516127100000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010952903718828448,"open_date":"2018-01-16 18:15:00+00:00","close_date":"2018-01-16 18:45:00+00:00","open_rate":0.09129999,"close_rate":0.09267292218045112,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.0013729321804511196,"sell_reason":"roi","initial_stop_loss_abs":0.082169991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.082169991,"stop_loss_ratio":0.1,"min_rate":0.09129999,"max_rate":0.09267292218045112,"is_open":false,"buy_tag":null,"open_timestamp":1516126500000.0,"close_timestamp":1516128300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":26.26050420168067,"open_date":"2018-01-16 18:15:00+00:00","close_date":"2018-01-16 18:35:00+00:00","open_rate":3.808e-05,"close_rate":3.903438596491228e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":9.543859649122774e-07,"sell_reason":"roi","initial_stop_loss_abs":3.4272e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.4272e-05,"stop_loss_ratio":0.1,"min_rate":3.808e-05,"max_rate":3.903438596491228e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516126500000.0,"close_timestamp":1516127700000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.035574376772493324,"open_date":"2018-01-16 19:00:00+00:00","close_date":"2018-01-16 19:30:00+00:00","open_rate":0.02811012,"close_rate":0.028532828571428567,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.00042270857142856846,"sell_reason":"roi","initial_stop_loss_abs":0.025299108,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025299108,"stop_loss_ratio":0.1,"min_rate":0.02811012,"max_rate":0.028532828571428567,"is_open":false,"buy_tag":null,"open_timestamp":1516129200000.0,"close_timestamp":1516131000000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.387028357567759,"open_date":"2018-01-16 21:25:00+00:00","close_date":"2018-01-16 22:25:00+00:00","open_rate":0.00258379,"close_rate":0.002325411,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.10448878,"profit_abs":-0.000258379,"sell_reason":"stop_loss","initial_stop_loss_abs":0.002325411,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002325411,"stop_loss_ratio":0.1,"min_rate":0.002325411,"max_rate":0.00258379,"is_open":false,"buy_tag":null,"open_timestamp":1516137900000.0,"close_timestamp":1516141500000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":39.07776475185619,"open_date":"2018-01-16 21:25:00+00:00","close_date":"2018-01-16 22:45:00+00:00","open_rate":2.559e-05,"close_rate":2.3031e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.10448878,"profit_abs":-2.5590000000000004e-06,"sell_reason":"stop_loss","initial_stop_loss_abs":2.3031e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.3031e-05,"stop_loss_ratio":0.1,"min_rate":2.3031e-05,"max_rate":2.559e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516137900000.0,"close_timestamp":1516142700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":13.123359580052494,"open_date":"2018-01-16 21:35:00+00:00","close_date":"2018-01-16 22:25:00+00:00","open_rate":7.62e-05,"close_rate":6.858e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":-0.10448878,"profit_abs":-7.619999999999998e-06,"sell_reason":"stop_loss","initial_stop_loss_abs":6.858e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":6.858e-05,"stop_loss_ratio":0.1,"min_rate":6.858e-05,"max_rate":7.62e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516138500000.0,"close_timestamp":1516141500000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.4350777048780912,"open_date":"2018-01-16 22:30:00+00:00","close_date":"2018-01-16 22:35:00+00:00","open_rate":0.00229844,"close_rate":0.002402129022556391,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":0.00010368902255639091,"sell_reason":"roi","initial_stop_loss_abs":0.0020685960000000002,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0020685960000000002,"stop_loss_ratio":0.1,"min_rate":0.00229844,"max_rate":0.002402129022556391,"is_open":false,"buy_tag":null,"open_timestamp":1516141800000.0,"close_timestamp":1516142100000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06622516556291391,"open_date":"2018-01-16 22:30:00+00:00","close_date":"2018-01-16 22:40:00+00:00","open_rate":0.0151,"close_rate":0.015781203007518795,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":10,"profit_ratio":0.03990025,"profit_abs":0.0006812030075187946,"sell_reason":"roi","initial_stop_loss_abs":0.013590000000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.013590000000000001,"stop_loss_ratio":0.1,"min_rate":0.0151,"max_rate":0.015781203007518795,"is_open":false,"buy_tag":null,"open_timestamp":1516141800000.0,"close_timestamp":1516142400000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.42431134269081283,"open_date":"2018-01-16 22:40:00+00:00","close_date":"2018-01-16 22:45:00+00:00","open_rate":0.00235676,"close_rate":0.00246308,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":0.00010632000000000003,"sell_reason":"roi","initial_stop_loss_abs":0.002121084,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002121084,"stop_loss_ratio":0.1,"min_rate":0.00235676,"max_rate":0.00246308,"is_open":false,"buy_tag":null,"open_timestamp":1516142400000.0,"close_timestamp":1516142700000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.01585559988076589,"open_date":"2018-01-16 22:45:00+00:00","close_date":"2018-01-16 23:05:00+00:00","open_rate":0.0630692,"close_rate":0.06464988170426066,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":0.0015806817042606502,"sell_reason":"roi","initial_stop_loss_abs":0.056762280000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.056762280000000005,"stop_loss_ratio":0.1,"min_rate":0.0630692,"max_rate":0.06464988170426066,"is_open":false,"buy_tag":null,"open_timestamp":1516142700000.0,"close_timestamp":1516143900000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":45.45454545454545,"open_date":"2018-01-16 22:50:00+00:00","close_date":"2018-01-16 22:55:00+00:00","open_rate":2.2e-05,"close_rate":2.299248120300751e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":9.924812030075114e-07,"sell_reason":"roi","initial_stop_loss_abs":1.98e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":1.98e-05,"stop_loss_ratio":0.1,"min_rate":2.2e-05,"max_rate":2.299248120300751e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516143000000.0,"close_timestamp":1516143300000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":20.10454362685967,"open_date":"2018-01-17 03:30:00+00:00","close_date":"2018-01-17 04:00:00+00:00","open_rate":4.974e-05,"close_rate":5.048796992481203e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":7.479699248120277e-07,"sell_reason":"roi","initial_stop_loss_abs":4.4766000000000005e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4766000000000005e-05,"stop_loss_ratio":0.1,"min_rate":4.974e-05,"max_rate":5.048796992481203e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516159800000.0,"close_timestamp":1516161600000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":14.068655036578503,"open_date":"2018-01-17 03:55:00+00:00","close_date":"2018-01-17 04:15:00+00:00","open_rate":7.108e-05,"close_rate":7.28614536340852e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":1.7814536340851996e-06,"sell_reason":"roi","initial_stop_loss_abs":6.3972e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":6.3972e-05,"stop_loss_ratio":0.1,"min_rate":7.108e-05,"max_rate":7.28614536340852e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516161300000.0,"close_timestamp":1516162500000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.0231107002542177,"open_date":"2018-01-17 09:35:00+00:00","close_date":"2018-01-17 10:15:00+00:00","open_rate":0.04327,"close_rate":0.04348689223057644,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0002168922305764362,"sell_reason":"roi","initial_stop_loss_abs":0.038943000000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.038943000000000005,"stop_loss_ratio":0.1,"min_rate":0.04327,"max_rate":0.04348689223057644,"is_open":false,"buy_tag":null,"open_timestamp":1516181700000.0,"close_timestamp":1516184100000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":20.012007204322593,"open_date":"2018-01-17 10:20:00+00:00","close_date":"2018-01-17 17:00:00+00:00","open_rate":4.997e-05,"close_rate":5.022047619047618e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":400,"profit_ratio":-0.0,"profit_abs":2.504761904761831e-07,"sell_reason":"roi","initial_stop_loss_abs":4.4973e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4973e-05,"stop_loss_ratio":0.1,"min_rate":4.997e-05,"max_rate":5.022047619047618e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516184400000.0,"close_timestamp":1516208400000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014626687444363738,"open_date":"2018-01-17 10:30:00+00:00","close_date":"2018-01-17 11:25:00+00:00","open_rate":0.06836818,"close_rate":0.06871087764411027,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":0.00034269764411026804,"sell_reason":"roi","initial_stop_loss_abs":0.061531362,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.061531362,"stop_loss_ratio":0.1,"min_rate":0.06836818,"max_rate":0.06871087764411027,"is_open":false,"buy_tag":null,"open_timestamp":1516185000000.0,"close_timestamp":1516188300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":27.548209366391184,"open_date":"2018-01-17 10:30:00+00:00","close_date":"2018-01-17 11:10:00+00:00","open_rate":3.63e-05,"close_rate":3.648195488721804e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.8195488721804031e-07,"sell_reason":"roi","initial_stop_loss_abs":3.2670000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.2670000000000004e-05,"stop_loss_ratio":0.1,"min_rate":3.63e-05,"max_rate":3.648195488721804e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516185000000.0,"close_timestamp":1516187400000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03558718861209965,"open_date":"2018-01-17 12:30:00+00:00","close_date":"2018-01-17 22:05:00+00:00","open_rate":0.0281,"close_rate":0.02824085213032581,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":575,"profit_ratio":-0.0,"profit_abs":0.0001408521303258095,"sell_reason":"roi","initial_stop_loss_abs":0.02529,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.02529,"stop_loss_ratio":0.1,"min_rate":0.0281,"max_rate":0.02824085213032581,"is_open":false,"buy_tag":null,"open_timestamp":1516192200000.0,"close_timestamp":1516226700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011559355963546878,"open_date":"2018-01-17 12:35:00+00:00","close_date":"2018-01-17 16:55:00+00:00","open_rate":0.08651001,"close_rate":0.08694364413533832,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":260,"profit_ratio":-0.0,"profit_abs":0.00043363413533832607,"sell_reason":"roi","initial_stop_loss_abs":0.077859009,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.077859009,"stop_loss_ratio":0.1,"min_rate":0.08651001,"max_rate":0.08694364413533832,"is_open":false,"buy_tag":null,"open_timestamp":1516192500000.0,"close_timestamp":1516208100000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.752529735487308,"open_date":"2018-01-18 05:00:00+00:00","close_date":"2018-01-18 05:55:00+00:00","open_rate":5.633e-05,"close_rate":5.6612355889724306e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.8235588972430847e-07,"sell_reason":"roi","initial_stop_loss_abs":5.0697e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0697e-05,"stop_loss_ratio":0.1,"min_rate":5.633e-05,"max_rate":5.6612355889724306e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516251600000.0,"close_timestamp":1516254900000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.01430923457900944,"open_date":"2018-01-18 05:20:00+00:00","close_date":"2018-01-18 05:55:00+00:00","open_rate":0.06988494,"close_rate":0.07093584135338346,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0010509013533834544,"sell_reason":"roi","initial_stop_loss_abs":0.06289644600000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06289644600000001,"stop_loss_ratio":0.1,"min_rate":0.06988494,"max_rate":0.07093584135338346,"is_open":false,"buy_tag":null,"open_timestamp":1516252800000.0,"close_timestamp":1516254900000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.034265103697024,"open_date":"2018-01-18 07:35:00+00:00","close_date":"2018-01-18 08:15:00+00:00","open_rate":5.545e-05,"close_rate":5.572794486215538e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.779448621553787e-07,"sell_reason":"roi","initial_stop_loss_abs":4.9905e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.9905e-05,"stop_loss_ratio":0.1,"min_rate":5.545e-05,"max_rate":5.572794486215538e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516260900000.0,"close_timestamp":1516263300000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06121723118136401,"open_date":"2018-01-18 09:00:00+00:00","close_date":"2018-01-18 09:40:00+00:00","open_rate":0.01633527,"close_rate":0.016417151052631574,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":8.188105263157511e-05,"sell_reason":"roi","initial_stop_loss_abs":0.014701743,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014701743,"stop_loss_ratio":0.1,"min_rate":0.01633527,"max_rate":0.016417151052631574,"is_open":false,"buy_tag":null,"open_timestamp":1516266000000.0,"close_timestamp":1516268400000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3707356136045141,"open_date":"2018-01-18 16:40:00+00:00","close_date":"2018-01-18 17:20:00+00:00","open_rate":0.00269734,"close_rate":0.002710860501253133,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.3520501253133123e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002427606,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002427606,"stop_loss_ratio":0.1,"min_rate":0.00269734,"max_rate":0.002710860501253133,"is_open":false,"buy_tag":null,"open_timestamp":1516293600000.0,"close_timestamp":1516296000000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":22.346368715083802,"open_date":"2018-01-18 18:05:00+00:00","close_date":"2018-01-18 18:30:00+00:00","open_rate":4.475e-05,"close_rate":4.587155388471177e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":1.1215538847117757e-06,"sell_reason":"roi","initial_stop_loss_abs":4.0274999999999996e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.0274999999999996e-05,"stop_loss_ratio":0.1,"min_rate":4.475e-05,"max_rate":4.587155388471177e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516298700000.0,"close_timestamp":1516300200000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":35.842293906810035,"open_date":"2018-01-18 18:25:00+00:00","close_date":"2018-01-18 18:55:00+00:00","open_rate":2.79e-05,"close_rate":2.8319548872180444e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.1954887218044365e-07,"sell_reason":"roi","initial_stop_loss_abs":2.5110000000000002e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.5110000000000002e-05,"stop_loss_ratio":0.1,"min_rate":2.79e-05,"max_rate":2.8319548872180444e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516299900000.0,"close_timestamp":1516301700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022525942001105574,"open_date":"2018-01-18 20:10:00+00:00","close_date":"2018-01-18 20:50:00+00:00","open_rate":0.04439326,"close_rate":0.04461578260651629,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.00022252260651629135,"sell_reason":"roi","initial_stop_loss_abs":0.039953933999999997,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.039953933999999997,"stop_loss_ratio":0.1,"min_rate":0.04439326,"max_rate":0.04461578260651629,"is_open":false,"buy_tag":null,"open_timestamp":1516306200000.0,"close_timestamp":1516308600000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":22.271714922048996,"open_date":"2018-01-18 21:30:00+00:00","close_date":"2018-01-19 00:35:00+00:00","open_rate":4.49e-05,"close_rate":4.51250626566416e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":185,"profit_ratio":0.0,"profit_abs":2.2506265664159932e-07,"sell_reason":"roi","initial_stop_loss_abs":4.041e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.041e-05,"stop_loss_ratio":0.1,"min_rate":4.49e-05,"max_rate":4.51250626566416e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516311000000.0,"close_timestamp":1516322100000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03502626970227671,"open_date":"2018-01-18 21:55:00+00:00","close_date":"2018-01-19 05:05:00+00:00","open_rate":0.02855,"close_rate":0.028693107769423555,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":430,"profit_ratio":-0.0,"profit_abs":0.00014310776942355607,"sell_reason":"roi","initial_stop_loss_abs":0.025695,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025695,"stop_loss_ratio":0.1,"min_rate":0.02855,"max_rate":0.028693107769423555,"is_open":false,"buy_tag":null,"open_timestamp":1516312500000.0,"close_timestamp":1516338300000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.25327812284334,"open_date":"2018-01-18 22:10:00+00:00","close_date":"2018-01-18 22:50:00+00:00","open_rate":5.796e-05,"close_rate":5.8250526315789473e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":2.905263157894727e-07,"sell_reason":"roi","initial_stop_loss_abs":5.2164000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.2164000000000004e-05,"stop_loss_ratio":0.1,"min_rate":5.796e-05,"max_rate":5.8250526315789473e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516313400000.0,"close_timestamp":1516315800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02303975994413319,"open_date":"2018-01-18 23:50:00+00:00","close_date":"2018-01-19 00:30:00+00:00","open_rate":0.04340323,"close_rate":0.04362079005012531,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.0002175600501253122,"sell_reason":"roi","initial_stop_loss_abs":0.039062907,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.039062907,"stop_loss_ratio":0.1,"min_rate":0.04340323,"max_rate":0.04362079005012531,"is_open":false,"buy_tag":null,"open_timestamp":1516319400000.0,"close_timestamp":1516321800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02244943545282195,"open_date":"2018-01-19 16:45:00+00:00","close_date":"2018-01-19 17:35:00+00:00","open_rate":0.04454455,"close_rate":0.04476783095238095,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":0.0,"profit_abs":0.0002232809523809512,"sell_reason":"roi","initial_stop_loss_abs":0.040090095000000006,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.040090095000000006,"stop_loss_ratio":0.1,"min_rate":0.04454455,"max_rate":0.04476783095238095,"is_open":false,"buy_tag":null,"open_timestamp":1516380300000.0,"close_timestamp":1516383300000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.793594306049823,"open_date":"2018-01-19 17:15:00+00:00","close_date":"2018-01-19 19:55:00+00:00","open_rate":5.62e-05,"close_rate":5.648170426065162e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":160,"profit_ratio":-0.0,"profit_abs":2.817042606516199e-07,"sell_reason":"roi","initial_stop_loss_abs":5.058e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.058e-05,"stop_loss_ratio":0.1,"min_rate":5.62e-05,"max_rate":5.648170426065162e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516382100000.0,"close_timestamp":1516391700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":23.046784973496194,"open_date":"2018-01-19 17:20:00+00:00","close_date":"2018-01-19 20:15:00+00:00","open_rate":4.339e-05,"close_rate":4.360749373433584e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":175,"profit_ratio":-0.0,"profit_abs":2.174937343358337e-07,"sell_reason":"roi","initial_stop_loss_abs":3.9051e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.9051e-05,"stop_loss_ratio":0.1,"min_rate":4.339e-05,"max_rate":4.360749373433584e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516382400000.0,"close_timestamp":1516392900000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":9.910802775024777,"open_date":"2018-01-20 04:45:00+00:00","close_date":"2018-01-20 17:35:00+00:00","open_rate":0.0001009,"close_rate":0.00010140576441102755,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":770,"profit_ratio":0.0,"profit_abs":5.057644110275549e-07,"sell_reason":"roi","initial_stop_loss_abs":9.081e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":9.081e-05,"stop_loss_ratio":0.1,"min_rate":0.0001009,"max_rate":0.00010140576441102755,"is_open":false,"buy_tag":null,"open_timestamp":1516423500000.0,"close_timestamp":1516469700000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3696789338459548,"open_date":"2018-01-20 04:50:00+00:00","close_date":"2018-01-20 15:15:00+00:00","open_rate":0.00270505,"close_rate":0.002718609147869674,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":625,"profit_ratio":-0.0,"profit_abs":1.3559147869673764e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002434545,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002434545,"stop_loss_ratio":0.1,"min_rate":0.00270505,"max_rate":0.002718609147869674,"is_open":false,"buy_tag":null,"open_timestamp":1516423800000.0,"close_timestamp":1516461300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.033333311111125925,"open_date":"2018-01-20 04:50:00+00:00","close_date":"2018-01-20 07:00:00+00:00","open_rate":0.03000002,"close_rate":0.030150396040100245,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":130,"profit_ratio":-0.0,"profit_abs":0.00015037604010024672,"sell_reason":"roi","initial_stop_loss_abs":0.027000018,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.027000018,"stop_loss_ratio":0.1,"min_rate":0.03000002,"max_rate":0.030150396040100245,"is_open":false,"buy_tag":null,"open_timestamp":1516423800000.0,"close_timestamp":1516431600000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.315018315018317,"open_date":"2018-01-20 09:00:00+00:00","close_date":"2018-01-20 09:40:00+00:00","open_rate":5.46e-05,"close_rate":5.4873684210526304e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.736842105263053e-07,"sell_reason":"roi","initial_stop_loss_abs":4.914e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.914e-05,"stop_loss_ratio":0.1,"min_rate":5.46e-05,"max_rate":5.4873684210526304e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516438800000.0,"close_timestamp":1516441200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03244412634781012,"open_date":"2018-01-20 18:25:00+00:00","close_date":"2018-01-25 03:50:00+00:00","open_rate":0.03082222,"close_rate":0.027739998,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":6325,"profit_ratio":-0.10448878,"profit_abs":-0.0030822220000000025,"sell_reason":"stop_loss","initial_stop_loss_abs":0.027739998000000002,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.027739998000000002,"stop_loss_ratio":0.1,"min_rate":0.027739998,"max_rate":0.03082222,"is_open":false,"buy_tag":null,"open_timestamp":1516472700000.0,"close_timestamp":1516852200000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011148273260677065,"open_date":"2018-01-20 22:25:00+00:00","close_date":"2018-01-20 23:15:00+00:00","open_rate":0.08969999,"close_rate":0.09014961401002504,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":-0.0,"profit_abs":0.00044962401002504593,"sell_reason":"roi","initial_stop_loss_abs":0.080729991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.080729991,"stop_loss_ratio":0.1,"min_rate":0.08969999,"max_rate":0.09014961401002504,"is_open":false,"buy_tag":null,"open_timestamp":1516487100000.0,"close_timestamp":1516490100000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06125570520324337,"open_date":"2018-01-21 02:50:00+00:00","close_date":"2018-01-21 14:30:00+00:00","open_rate":0.01632501,"close_rate":0.01640683962406015,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":700,"profit_ratio":0.0,"profit_abs":8.182962406014932e-05,"sell_reason":"roi","initial_stop_loss_abs":0.014692509000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014692509000000001,"stop_loss_ratio":0.1,"min_rate":0.01632501,"max_rate":0.01640683962406015,"is_open":false,"buy_tag":null,"open_timestamp":1516503000000.0,"close_timestamp":1516545000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.01417675579120474,"open_date":"2018-01-21 10:20:00+00:00","close_date":"2018-01-21 11:00:00+00:00","open_rate":0.070538,"close_rate":0.07089157393483708,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00035357393483707866,"sell_reason":"roi","initial_stop_loss_abs":0.0634842,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0634842,"stop_loss_ratio":0.1,"min_rate":0.070538,"max_rate":0.07089157393483708,"is_open":false,"buy_tag":null,"open_timestamp":1516530000000.0,"close_timestamp":1516532400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.864365214110546,"open_date":"2018-01-21 15:50:00+00:00","close_date":"2018-01-21 18:45:00+00:00","open_rate":5.301e-05,"close_rate":5.327571428571427e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":175,"profit_ratio":-0.0,"profit_abs":2.657142857142672e-07,"sell_reason":"roi","initial_stop_loss_abs":4.7709e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7709e-05,"stop_loss_ratio":0.1,"min_rate":5.301e-05,"max_rate":5.327571428571427e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516549800000.0,"close_timestamp":1516560300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":25.284450063211125,"open_date":"2018-01-21 16:20:00+00:00","close_date":"2018-01-21 17:00:00+00:00","open_rate":3.955e-05,"close_rate":3.9748245614035085e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":1.9824561403508552e-07,"sell_reason":"roi","initial_stop_loss_abs":3.5595e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.5595e-05,"stop_loss_ratio":0.1,"min_rate":3.955e-05,"max_rate":3.9748245614035085e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516551600000.0,"close_timestamp":1516554000000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38683971296493297,"open_date":"2018-01-21 21:15:00+00:00","close_date":"2018-01-21 21:45:00+00:00","open_rate":0.00258505,"close_rate":0.002623922932330827,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":3.8872932330826816e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002326545,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002326545,"stop_loss_ratio":0.1,"min_rate":0.00258505,"max_rate":0.002623922932330827,"is_open":false,"buy_tag":null,"open_timestamp":1516569300000.0,"close_timestamp":1516571100000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":25.621316935690498,"open_date":"2018-01-21 21:15:00+00:00","close_date":"2018-01-21 21:55:00+00:00","open_rate":3.903e-05,"close_rate":3.922563909774435e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.9563909774435151e-07,"sell_reason":"roi","initial_stop_loss_abs":3.5127e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.5127e-05,"stop_loss_ratio":0.1,"min_rate":3.903e-05,"max_rate":3.922563909774435e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516569300000.0,"close_timestamp":1516571700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.098548510313215,"open_date":"2018-01-22 00:35:00+00:00","close_date":"2018-01-22 10:35:00+00:00","open_rate":5.236e-05,"close_rate":5.262245614035087e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":600,"profit_ratio":-0.0,"profit_abs":2.624561403508717e-07,"sell_reason":"roi","initial_stop_loss_abs":4.7124e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7124e-05,"stop_loss_ratio":0.1,"min_rate":5.236e-05,"max_rate":5.262245614035087e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516581300000.0,"close_timestamp":1516617300000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.076650420912717,"open_date":"2018-01-22 01:30:00+00:00","close_date":"2018-01-22 02:10:00+00:00","open_rate":9.028e-05,"close_rate":9.07325313283208e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":4.5253132832080657e-07,"sell_reason":"roi","initial_stop_loss_abs":8.1252e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.1252e-05,"stop_loss_ratio":0.1,"min_rate":9.028e-05,"max_rate":9.07325313283208e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516584600000.0,"close_timestamp":1516587000000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3721622627465575,"open_date":"2018-01-22 12:25:00+00:00","close_date":"2018-01-22 14:35:00+00:00","open_rate":0.002687,"close_rate":0.002700468671679198,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":130,"profit_ratio":-0.0,"profit_abs":1.3468671679197925e-05,"sell_reason":"roi","initial_stop_loss_abs":0.0024183000000000004,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0024183000000000004,"stop_loss_ratio":0.1,"min_rate":0.002687,"max_rate":0.002700468671679198,"is_open":false,"buy_tag":null,"open_timestamp":1516623900000.0,"close_timestamp":1516631700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":23.99232245681382,"open_date":"2018-01-22 13:15:00+00:00","close_date":"2018-01-22 13:55:00+00:00","open_rate":4.168e-05,"close_rate":4.188892230576441e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.0892230576441054e-07,"sell_reason":"roi","initial_stop_loss_abs":3.7512e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.7512e-05,"stop_loss_ratio":0.1,"min_rate":4.168e-05,"max_rate":4.188892230576441e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516626900000.0,"close_timestamp":1516629300000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.336583153837434,"open_date":"2018-01-22 14:00:00+00:00","close_date":"2018-01-22 14:30:00+00:00","open_rate":8.821e-05,"close_rate":8.953646616541353e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":1.326466165413529e-06,"sell_reason":"roi","initial_stop_loss_abs":7.9389e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":7.9389e-05,"stop_loss_ratio":0.1,"min_rate":8.821e-05,"max_rate":8.953646616541353e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516629600000.0,"close_timestamp":1516631400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.334880123743233,"open_date":"2018-01-22 15:55:00+00:00","close_date":"2018-01-22 16:40:00+00:00","open_rate":5.172e-05,"close_rate":5.1979248120300745e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":2.592481203007459e-07,"sell_reason":"roi","initial_stop_loss_abs":4.6548e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6548e-05,"stop_loss_ratio":0.1,"min_rate":5.172e-05,"max_rate":5.1979248120300745e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516636500000.0,"close_timestamp":1516639200000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":33.04692663582287,"open_date":"2018-01-22 16:05:00+00:00","close_date":"2018-01-22 16:25:00+00:00","open_rate":3.026e-05,"close_rate":3.101839598997494e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":7.5839598997494e-07,"sell_reason":"roi","initial_stop_loss_abs":2.7234e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7234e-05,"stop_loss_ratio":0.1,"min_rate":3.026e-05,"max_rate":3.101839598997494e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516637100000.0,"close_timestamp":1516638300000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014156285390713478,"open_date":"2018-01-22 19:50:00+00:00","close_date":"2018-01-23 00:10:00+00:00","open_rate":0.07064,"close_rate":0.07099408521303258,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":260,"profit_ratio":0.0,"profit_abs":0.00035408521303258167,"sell_reason":"roi","initial_stop_loss_abs":0.063576,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.063576,"stop_loss_ratio":0.1,"min_rate":0.07064,"max_rate":0.07099408521303258,"is_open":false,"buy_tag":null,"open_timestamp":1516650600000.0,"close_timestamp":1516666200000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06080938507725528,"open_date":"2018-01-22 21:25:00+00:00","close_date":"2018-01-22 22:05:00+00:00","open_rate":0.01644483,"close_rate":0.01652726022556391,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":8.243022556390922e-05,"sell_reason":"roi","initial_stop_loss_abs":0.014800347,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014800347,"stop_loss_ratio":0.1,"min_rate":0.01644483,"max_rate":0.01652726022556391,"is_open":false,"buy_tag":null,"open_timestamp":1516656300000.0,"close_timestamp":1516658700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":23.08935580697299,"open_date":"2018-01-23 00:05:00+00:00","close_date":"2018-01-23 00:35:00+00:00","open_rate":4.331e-05,"close_rate":4.3961278195488714e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":6.512781954887175e-07,"sell_reason":"roi","initial_stop_loss_abs":3.8979e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.8979e-05,"stop_loss_ratio":0.1,"min_rate":4.331e-05,"max_rate":4.3961278195488714e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516665900000.0,"close_timestamp":1516667700000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":31.250000000000004,"open_date":"2018-01-23 01:50:00+00:00","close_date":"2018-01-23 02:15:00+00:00","open_rate":3.2e-05,"close_rate":3.2802005012531326e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":8.020050125313278e-07,"sell_reason":"roi","initial_stop_loss_abs":2.88e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.88e-05,"stop_loss_ratio":0.1,"min_rate":3.2e-05,"max_rate":3.2802005012531326e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516672200000.0,"close_timestamp":1516673700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010907854156754155,"open_date":"2018-01-23 04:25:00+00:00","close_date":"2018-01-23 05:15:00+00:00","open_rate":0.09167706,"close_rate":0.09213659413533835,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":0.0,"profit_abs":0.0004595341353383492,"sell_reason":"roi","initial_stop_loss_abs":0.08250935400000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08250935400000001,"stop_loss_ratio":0.1,"min_rate":0.09167706,"max_rate":0.09213659413533835,"is_open":false,"buy_tag":null,"open_timestamp":1516681500000.0,"close_timestamp":1516684500000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014440474918339115,"open_date":"2018-01-23 07:35:00+00:00","close_date":"2018-01-23 09:00:00+00:00","open_rate":0.0692498,"close_rate":0.06959691679197995,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":85,"profit_ratio":0.0,"profit_abs":0.0003471167919799484,"sell_reason":"roi","initial_stop_loss_abs":0.06232482,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06232482,"stop_loss_ratio":0.1,"min_rate":0.0692498,"max_rate":0.06959691679197995,"is_open":false,"buy_tag":null,"open_timestamp":1516692900000.0,"close_timestamp":1516698000000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":31.426775612822127,"open_date":"2018-01-23 10:50:00+00:00","close_date":"2018-01-23 13:05:00+00:00","open_rate":3.182e-05,"close_rate":3.197949874686716e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":135,"profit_ratio":0.0,"profit_abs":1.594987468671663e-07,"sell_reason":"roi","initial_stop_loss_abs":2.8638e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.8638e-05,"stop_loss_ratio":0.1,"min_rate":3.182e-05,"max_rate":3.197949874686716e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516704600000.0,"close_timestamp":1516712700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024461839530332683,"open_date":"2018-01-23 11:05:00+00:00","close_date":"2018-01-23 16:05:00+00:00","open_rate":0.04088,"close_rate":0.04108491228070175,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":300,"profit_ratio":-0.0,"profit_abs":0.0002049122807017481,"sell_reason":"roi","initial_stop_loss_abs":0.036792,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036792,"stop_loss_ratio":0.1,"min_rate":0.04088,"max_rate":0.04108491228070175,"is_open":false,"buy_tag":null,"open_timestamp":1516705500000.0,"close_timestamp":1516723500000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.417475728155342,"open_date":"2018-01-23 14:55:00+00:00","close_date":"2018-01-23 15:35:00+00:00","open_rate":5.15e-05,"close_rate":5.175814536340851e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.5814536340851513e-07,"sell_reason":"roi","initial_stop_loss_abs":4.635e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.635e-05,"stop_loss_ratio":0.1,"min_rate":5.15e-05,"max_rate":5.175814536340851e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516719300000.0,"close_timestamp":1516721700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011023294646713328,"open_date":"2018-01-23 16:35:00+00:00","close_date":"2018-01-24 00:05:00+00:00","open_rate":0.09071698,"close_rate":0.09117170170426064,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":450,"profit_ratio":0.0,"profit_abs":0.00045472170426064107,"sell_reason":"roi","initial_stop_loss_abs":0.081645282,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.081645282,"stop_loss_ratio":0.1,"min_rate":0.09071698,"max_rate":0.09117170170426064,"is_open":false,"buy_tag":null,"open_timestamp":1516725300000.0,"close_timestamp":1516752300000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":31.969309462915604,"open_date":"2018-01-23 17:25:00+00:00","close_date":"2018-01-23 18:45:00+00:00","open_rate":3.128e-05,"close_rate":3.1436791979949865e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.0,"profit_abs":1.5679197994986587e-07,"sell_reason":"roi","initial_stop_loss_abs":2.8152e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.8152e-05,"stop_loss_ratio":0.1,"min_rate":3.128e-05,"max_rate":3.1436791979949865e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516728300000.0,"close_timestamp":1516733100000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.465724751439037,"open_date":"2018-01-23 20:15:00+00:00","close_date":"2018-01-23 22:00:00+00:00","open_rate":9.555e-05,"close_rate":9.602894736842104e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":105,"profit_ratio":-0.0,"profit_abs":4.789473684210343e-07,"sell_reason":"roi","initial_stop_loss_abs":8.5995e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.5995e-05,"stop_loss_ratio":0.1,"min_rate":9.555e-05,"max_rate":9.602894736842104e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516738500000.0,"close_timestamp":1516744800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02450979791426522,"open_date":"2018-01-23 22:30:00+00:00","close_date":"2018-01-23 23:10:00+00:00","open_rate":0.04080001,"close_rate":0.0410045213283208,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00020451132832080554,"sell_reason":"roi","initial_stop_loss_abs":0.036720009,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036720009,"stop_loss_ratio":0.1,"min_rate":0.04080001,"max_rate":0.0410045213283208,"is_open":false,"buy_tag":null,"open_timestamp":1516746600000.0,"close_timestamp":1516749000000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.368584156498162,"open_date":"2018-01-23 23:50:00+00:00","close_date":"2018-01-24 03:35:00+00:00","open_rate":5.163e-05,"close_rate":5.18887969924812e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":225,"profit_ratio":-0.0,"profit_abs":2.587969924812037e-07,"sell_reason":"roi","initial_stop_loss_abs":4.6467e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6467e-05,"stop_loss_ratio":0.1,"min_rate":5.163e-05,"max_rate":5.18887969924812e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516751400000.0,"close_timestamp":1516764900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024747691102289384,"open_date":"2018-01-24 00:20:00+00:00","close_date":"2018-01-24 01:50:00+00:00","open_rate":0.04040781,"close_rate":0.04061035541353383,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":90,"profit_ratio":0.0,"profit_abs":0.0002025454135338306,"sell_reason":"roi","initial_stop_loss_abs":0.036367029,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036367029,"stop_loss_ratio":0.1,"min_rate":0.04040781,"max_rate":0.04061035541353383,"is_open":false,"buy_tag":null,"open_timestamp":1516753200000.0,"close_timestamp":1516758600000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.485580670303975,"open_date":"2018-01-24 06:45:00+00:00","close_date":"2018-01-24 07:25:00+00:00","open_rate":5.132e-05,"close_rate":5.157724310776942e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.5724310776941724e-07,"sell_reason":"roi","initial_stop_loss_abs":4.6188000000000006e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6188000000000006e-05,"stop_loss_ratio":0.1,"min_rate":5.132e-05,"max_rate":5.157724310776942e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516776300000.0,"close_timestamp":1516778700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.23816852635629,"open_date":"2018-01-24 14:15:00+00:00","close_date":"2018-01-24 14:25:00+00:00","open_rate":5.198e-05,"close_rate":5.432496240601503e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":10,"profit_ratio":0.03990025,"profit_abs":2.344962406015033e-06,"sell_reason":"roi","initial_stop_loss_abs":4.6782e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6782e-05,"stop_loss_ratio":0.1,"min_rate":5.198e-05,"max_rate":5.432496240601503e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516803300000.0,"close_timestamp":1516803900000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":32.74394237066143,"open_date":"2018-01-24 14:50:00+00:00","close_date":"2018-01-24 16:35:00+00:00","open_rate":3.054e-05,"close_rate":3.069308270676692e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":105,"profit_ratio":-0.0,"profit_abs":1.5308270676691466e-07,"sell_reason":"roi","initial_stop_loss_abs":2.7486000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7486000000000004e-05,"stop_loss_ratio":0.1,"min_rate":3.054e-05,"max_rate":3.069308270676692e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516805400000.0,"close_timestamp":1516811700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.795638562020944,"open_date":"2018-01-24 15:10:00+00:00","close_date":"2018-01-24 16:15:00+00:00","open_rate":9.263e-05,"close_rate":9.309431077694236e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":65,"profit_ratio":0.0,"profit_abs":4.6431077694236234e-07,"sell_reason":"roi","initial_stop_loss_abs":8.3367e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.3367e-05,"stop_loss_ratio":0.1,"min_rate":9.263e-05,"max_rate":9.309431077694236e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516806600000.0,"close_timestamp":1516810500000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.13565469713457,"open_date":"2018-01-24 22:40:00+00:00","close_date":"2018-01-24 23:25:00+00:00","open_rate":5.514e-05,"close_rate":5.54163909774436e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":2.7639097744360576e-07,"sell_reason":"roi","initial_stop_loss_abs":4.9625999999999995e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.9625999999999995e-05,"stop_loss_ratio":0.1,"min_rate":5.514e-05,"max_rate":5.54163909774436e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516833600000.0,"close_timestamp":1516836300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":20.3210729526519,"open_date":"2018-01-25 00:50:00+00:00","close_date":"2018-01-25 01:30:00+00:00","open_rate":4.921e-05,"close_rate":4.9456666666666664e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":2.4666666666666543e-07,"sell_reason":"roi","initial_stop_loss_abs":4.4289e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4289e-05,"stop_loss_ratio":0.1,"min_rate":4.921e-05,"max_rate":4.9456666666666664e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516841400000.0,"close_timestamp":1516843800000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38461538461538464,"open_date":"2018-01-25 08:15:00+00:00","close_date":"2018-01-25 12:15:00+00:00","open_rate":0.0026,"close_rate":0.002613032581453634,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":240,"profit_ratio":0.0,"profit_abs":1.3032581453634e-05,"sell_reason":"roi","initial_stop_loss_abs":0.00234,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.00234,"stop_loss_ratio":0.1,"min_rate":0.0026,"max_rate":0.002613032581453634,"is_open":false,"buy_tag":null,"open_timestamp":1516868100000.0,"close_timestamp":1516882500000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03571593119825878,"open_date":"2018-01-25 10:25:00+00:00","close_date":"2018-01-25 16:15:00+00:00","open_rate":0.02799871,"close_rate":0.028139054411027563,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":350,"profit_ratio":-0.0,"profit_abs":0.00014034441102756326,"sell_reason":"roi","initial_stop_loss_abs":0.025198839,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025198839,"stop_loss_ratio":0.1,"min_rate":0.02799871,"max_rate":0.028139054411027563,"is_open":false,"buy_tag":null,"open_timestamp":1516875900000.0,"close_timestamp":1516896900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024516401717913302,"open_date":"2018-01-25 11:00:00+00:00","close_date":"2018-01-25 11:45:00+00:00","open_rate":0.04078902,"close_rate":0.0409934762406015,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":0.00020445624060149575,"sell_reason":"roi","initial_stop_loss_abs":0.036710118,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036710118,"stop_loss_ratio":0.1,"min_rate":0.04078902,"max_rate":0.0409934762406015,"is_open":false,"buy_tag":null,"open_timestamp":1516878000000.0,"close_timestamp":1516880700000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":34.602076124567475,"open_date":"2018-01-25 13:05:00+00:00","close_date":"2018-01-25 13:45:00+00:00","open_rate":2.89e-05,"close_rate":2.904486215538847e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.4486215538846723e-07,"sell_reason":"roi","initial_stop_loss_abs":2.601e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.601e-05,"stop_loss_ratio":0.1,"min_rate":2.89e-05,"max_rate":2.904486215538847e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516885500000.0,"close_timestamp":1516887900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02432912439481303,"open_date":"2018-01-25 13:20:00+00:00","close_date":"2018-01-25 14:05:00+00:00","open_rate":0.041103,"close_rate":0.04130903007518797,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":0.00020603007518796984,"sell_reason":"roi","initial_stop_loss_abs":0.0369927,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0369927,"stop_loss_ratio":0.1,"min_rate":0.041103,"max_rate":0.04130903007518797,"is_open":false,"buy_tag":null,"open_timestamp":1516886400000.0,"close_timestamp":1516889100000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":18.422991893883566,"open_date":"2018-01-25 15:45:00+00:00","close_date":"2018-01-25 16:15:00+00:00","open_rate":5.428e-05,"close_rate":5.509624060150376e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":8.162406015037611e-07,"sell_reason":"roi","initial_stop_loss_abs":4.8852000000000006e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.8852000000000006e-05,"stop_loss_ratio":0.1,"min_rate":5.428e-05,"max_rate":5.509624060150376e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516895100000.0,"close_timestamp":1516896900000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":18.47063169560399,"open_date":"2018-01-25 17:45:00+00:00","close_date":"2018-01-25 23:15:00+00:00","open_rate":5.414e-05,"close_rate":5.441137844611528e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":330,"profit_ratio":-0.0,"profit_abs":2.713784461152774e-07,"sell_reason":"roi","initial_stop_loss_abs":4.8726e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.8726e-05,"stop_loss_ratio":0.1,"min_rate":5.414e-05,"max_rate":5.441137844611528e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516902300000.0,"close_timestamp":1516922100000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024150056861308878,"open_date":"2018-01-25 21:15:00+00:00","close_date":"2018-01-25 21:55:00+00:00","open_rate":0.04140777,"close_rate":0.0416153277443609,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0002075577443608964,"sell_reason":"roi","initial_stop_loss_abs":0.037266993000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.037266993000000005,"stop_loss_ratio":0.1,"min_rate":0.04140777,"max_rate":0.0416153277443609,"is_open":false,"buy_tag":null,"open_timestamp":1516914900000.0,"close_timestamp":1516917300000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3932224183965176,"open_date":"2018-01-26 02:05:00+00:00","close_date":"2018-01-26 02:45:00+00:00","open_rate":0.00254309,"close_rate":0.002555837318295739,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":1.2747318295739177e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002288781,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002288781,"stop_loss_ratio":0.1,"min_rate":0.00254309,"max_rate":0.002555837318295739,"is_open":false,"buy_tag":null,"open_timestamp":1516932300000.0,"close_timestamp":1516934700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.834849295523455,"open_date":"2018-01-26 02:55:00+00:00","close_date":"2018-01-26 15:10:00+00:00","open_rate":5.607e-05,"close_rate":5.6351052631578935e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":735,"profit_ratio":-0.0,"profit_abs":2.810526315789381e-07,"sell_reason":"roi","initial_stop_loss_abs":5.0463e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0463e-05,"stop_loss_ratio":0.1,"min_rate":5.607e-05,"max_rate":5.6351052631578935e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516935300000.0,"close_timestamp":1516979400000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.39400171784748983,"open_date":"2018-01-26 06:10:00+00:00","close_date":"2018-01-26 09:25:00+00:00","open_rate":0.00253806,"close_rate":0.0025507821052631577,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":195,"profit_ratio":0.0,"profit_abs":1.2722105263157733e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002284254,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002284254,"stop_loss_ratio":0.1,"min_rate":0.00253806,"max_rate":0.0025507821052631577,"is_open":false,"buy_tag":null,"open_timestamp":1516947000000.0,"close_timestamp":1516958700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024096385542168672,"open_date":"2018-01-26 07:25:00+00:00","close_date":"2018-01-26 09:55:00+00:00","open_rate":0.0415,"close_rate":0.04170802005012531,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":150,"profit_ratio":-0.0,"profit_abs":0.00020802005012530989,"sell_reason":"roi","initial_stop_loss_abs":0.03735,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.03735,"stop_loss_ratio":0.1,"min_rate":0.0415,"max_rate":0.04170802005012531,"is_open":false,"buy_tag":null,"open_timestamp":1516951500000.0,"close_timestamp":1516960500000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":18.793459875963165,"open_date":"2018-01-26 09:55:00+00:00","close_date":"2018-01-26 10:25:00+00:00","open_rate":5.321e-05,"close_rate":5.401015037593984e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":8.00150375939842e-07,"sell_reason":"roi","initial_stop_loss_abs":4.7889e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7889e-05,"stop_loss_ratio":0.1,"min_rate":5.321e-05,"max_rate":5.401015037593984e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516960500000.0,"close_timestamp":1516962300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.036074437437185386,"open_date":"2018-01-26 16:05:00+00:00","close_date":"2018-01-26 16:45:00+00:00","open_rate":0.02772046,"close_rate":0.02785940967418546,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00013894967418546025,"sell_reason":"roi","initial_stop_loss_abs":0.024948414,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.024948414,"stop_loss_ratio":0.1,"min_rate":0.02772046,"max_rate":0.02785940967418546,"is_open":false,"buy_tag":null,"open_timestamp":1516982700000.0,"close_timestamp":1516985100000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010569326272036914,"open_date":"2018-01-26 23:35:00+00:00","close_date":"2018-01-27 00:15:00+00:00","open_rate":0.09461341,"close_rate":0.09508766268170424,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.00047425268170424306,"sell_reason":"roi","initial_stop_loss_abs":0.085152069,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.085152069,"stop_loss_ratio":0.1,"min_rate":0.09461341,"max_rate":0.09508766268170424,"is_open":false,"buy_tag":null,"open_timestamp":1517009700000.0,"close_timestamp":1517012100000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":17.809439002671414,"open_date":"2018-01-27 00:35:00+00:00","close_date":"2018-01-27 01:30:00+00:00","open_rate":5.615e-05,"close_rate":5.643145363408521e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.814536340852038e-07,"sell_reason":"roi","initial_stop_loss_abs":5.0535e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0535e-05,"stop_loss_ratio":0.1,"min_rate":5.615e-05,"max_rate":5.643145363408521e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517013300000.0,"close_timestamp":1517016600000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.998560115190784,"open_date":"2018-01-27 00:45:00+00:00","close_date":"2018-01-30 04:45:00+00:00","open_rate":5.556e-05,"close_rate":5.144e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":4560,"profit_ratio":-0.07877175,"profit_abs":-4.120000000000001e-06,"sell_reason":"force_sell","initial_stop_loss_abs":5.0004000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0004000000000004e-05,"stop_loss_ratio":0.1,"min_rate":5.144e-05,"max_rate":5.556e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517013900000.0,"close_timestamp":1517287500000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014492751522789634,"open_date":"2018-01-27 02:30:00+00:00","close_date":"2018-01-27 11:25:00+00:00","open_rate":0.06900001,"close_rate":0.06934587471177944,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":535,"profit_ratio":-0.0,"profit_abs":0.0003458647117794422,"sell_reason":"roi","initial_stop_loss_abs":0.062100009000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.062100009000000005,"stop_loss_ratio":0.1,"min_rate":0.06900001,"max_rate":0.06934587471177944,"is_open":false,"buy_tag":null,"open_timestamp":1517020200000.0,"close_timestamp":1517052300000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010582027378879437,"open_date":"2018-01-27 06:25:00+00:00","close_date":"2018-01-27 07:05:00+00:00","open_rate":0.09449985,"close_rate":0.0949735334586466,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004736834586466093,"sell_reason":"roi","initial_stop_loss_abs":0.085049865,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.085049865,"stop_loss_ratio":0.1,"min_rate":0.09449985,"max_rate":0.0949735334586466,"is_open":false,"buy_tag":null,"open_timestamp":1517034300000.0,"close_timestamp":1517036700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02434885085598385,"open_date":"2018-01-27 09:40:00+00:00","close_date":"2018-01-30 04:40:00+00:00","open_rate":0.0410697,"close_rate":0.03928809,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":4020,"profit_ratio":-0.04815133,"profit_abs":-0.001781610000000003,"sell_reason":"force_sell","initial_stop_loss_abs":0.03696273,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.03696273,"stop_loss_ratio":0.1,"min_rate":0.03928809,"max_rate":0.0410697,"is_open":false,"buy_tag":null,"open_timestamp":1517046000000.0,"close_timestamp":1517287200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03508771929824561,"open_date":"2018-01-27 11:45:00+00:00","close_date":"2018-01-27 12:30:00+00:00","open_rate":0.0285,"close_rate":0.02864285714285714,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":0.00014285714285713902,"sell_reason":"roi","initial_stop_loss_abs":0.025650000000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025650000000000003,"stop_loss_ratio":0.1,"min_rate":0.0285,"max_rate":0.02864285714285714,"is_open":false,"buy_tag":null,"open_timestamp":1517053500000.0,"close_timestamp":1517056200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.034887307020861215,"open_date":"2018-01-27 12:35:00+00:00","close_date":"2018-01-27 15:25:00+00:00","open_rate":0.02866372,"close_rate":0.02880739779448621,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":170,"profit_ratio":-0.0,"profit_abs":0.00014367779448621124,"sell_reason":"roi","initial_stop_loss_abs":0.025797348,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025797348,"stop_loss_ratio":0.1,"min_rate":0.02866372,"max_rate":0.02880739779448621,"is_open":false,"buy_tag":null,"open_timestamp":1517056500000.0,"close_timestamp":1517066700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010484268355332824,"open_date":"2018-01-27 15:50:00+00:00","close_date":"2018-01-27 16:50:00+00:00","open_rate":0.095381,"close_rate":0.09585910025062656,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.0,"profit_abs":0.00047810025062657024,"sell_reason":"roi","initial_stop_loss_abs":0.0858429,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0858429,"stop_loss_ratio":0.1,"min_rate":0.095381,"max_rate":0.09585910025062656,"is_open":false,"buy_tag":null,"open_timestamp":1517068200000.0,"close_timestamp":1517071800000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014794886650455417,"open_date":"2018-01-27 17:05:00+00:00","close_date":"2018-01-27 17:45:00+00:00","open_rate":0.06759092,"close_rate":0.06792972160401002,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00033880160401002224,"sell_reason":"roi","initial_stop_loss_abs":0.060831828,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060831828,"stop_loss_ratio":0.1,"min_rate":0.06759092,"max_rate":0.06792972160401002,"is_open":false,"buy_tag":null,"open_timestamp":1517072700000.0,"close_timestamp":1517075100000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38684569885609726,"open_date":"2018-01-27 23:40:00+00:00","close_date":"2018-01-28 01:05:00+00:00","open_rate":0.00258501,"close_rate":0.002597967443609022,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":85,"profit_ratio":-0.0,"profit_abs":1.2957443609021985e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002326509,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002326509,"stop_loss_ratio":0.1,"min_rate":0.00258501,"max_rate":0.002597967443609022,"is_open":false,"buy_tag":null,"open_timestamp":1517096400000.0,"close_timestamp":1517101500000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014928710926711672,"open_date":"2018-01-28 02:25:00+00:00","close_date":"2018-01-28 08:10:00+00:00","open_rate":0.06698502,"close_rate":0.0673207845112782,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":345,"profit_ratio":-0.0,"profit_abs":0.00033576451127818874,"sell_reason":"roi","initial_stop_loss_abs":0.060286518000000004,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060286518000000004,"stop_loss_ratio":0.1,"min_rate":0.06698502,"max_rate":0.0673207845112782,"is_open":false,"buy_tag":null,"open_timestamp":1517106300000.0,"close_timestamp":1517127000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014767187899175548,"open_date":"2018-01-28 10:25:00+00:00","close_date":"2018-01-28 16:30:00+00:00","open_rate":0.0677177,"close_rate":0.06805713709273183,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":365,"profit_ratio":-0.0,"profit_abs":0.0003394370927318202,"sell_reason":"roi","initial_stop_loss_abs":0.06094593000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06094593000000001,"stop_loss_ratio":0.1,"min_rate":0.0677177,"max_rate":0.06805713709273183,"is_open":false,"buy_tag":null,"open_timestamp":1517135100000.0,"close_timestamp":1517157000000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":19.175455417066157,"open_date":"2018-01-28 20:35:00+00:00","close_date":"2018-01-28 21:35:00+00:00","open_rate":5.215e-05,"close_rate":5.2411403508771925e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":0.0,"profit_abs":2.6140350877192417e-07,"sell_reason":"roi","initial_stop_loss_abs":4.6935000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6935000000000004e-05,"stop_loss_ratio":0.1,"min_rate":5.215e-05,"max_rate":5.2411403508771925e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517171700000.0,"close_timestamp":1517175300000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.36521808998243305,"open_date":"2018-01-28 22:00:00+00:00","close_date":"2018-01-28 22:30:00+00:00","open_rate":0.00273809,"close_rate":0.002779264285714285,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.117428571428529e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002464281,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002464281,"stop_loss_ratio":0.1,"min_rate":0.00273809,"max_rate":0.002779264285714285,"is_open":false,"buy_tag":null,"open_timestamp":1517176800000.0,"close_timestamp":1517178600000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3641236272539253,"open_date":"2018-01-29 00:00:00+00:00","close_date":"2018-01-29 00:30:00+00:00","open_rate":0.00274632,"close_rate":0.002787618045112782,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.129804511278194e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002471688,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002471688,"stop_loss_ratio":0.1,"min_rate":0.00274632,"max_rate":0.002787618045112782,"is_open":false,"buy_tag":null,"open_timestamp":1517184000000.0,"close_timestamp":1517185800000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.061634117689115045,"open_date":"2018-01-29 02:15:00+00:00","close_date":"2018-01-29 03:00:00+00:00","open_rate":0.01622478,"close_rate":0.016306107218045113,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":0.0,"profit_abs":8.132721804511231e-05,"sell_reason":"roi","initial_stop_loss_abs":0.014602302000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014602302000000001,"stop_loss_ratio":0.1,"min_rate":0.01622478,"max_rate":0.016306107218045113,"is_open":false,"buy_tag":null,"open_timestamp":1517192100000.0,"close_timestamp":1517194800000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014492753623188404,"open_date":"2018-01-29 03:05:00+00:00","close_date":"2018-01-29 03:45:00+00:00","open_rate":0.069,"close_rate":0.06934586466165413,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00034586466165412166,"sell_reason":"roi","initial_stop_loss_abs":0.06210000000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06210000000000001,"stop_loss_ratio":0.1,"min_rate":0.069,"max_rate":0.06934586466165413,"is_open":false,"buy_tag":null,"open_timestamp":1517195100000.0,"close_timestamp":1517197500000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.42204454597373,"open_date":"2018-01-29 05:20:00+00:00","close_date":"2018-01-29 06:55:00+00:00","open_rate":8.755e-05,"close_rate":8.798884711779448e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":95,"profit_ratio":-0.0,"profit_abs":4.3884711779447504e-07,"sell_reason":"roi","initial_stop_loss_abs":7.879500000000001e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":7.879500000000001e-05,"stop_loss_ratio":0.1,"min_rate":8.755e-05,"max_rate":8.798884711779448e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517203200000.0,"close_timestamp":1517208900000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014650376815016871,"open_date":"2018-01-29 07:00:00+00:00","close_date":"2018-01-29 19:25:00+00:00","open_rate":0.06825763,"close_rate":0.06859977350877192,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":745,"profit_ratio":-0.0,"profit_abs":0.00034214350877191657,"sell_reason":"roi","initial_stop_loss_abs":0.061431867,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.061431867,"stop_loss_ratio":0.1,"min_rate":0.06825763,"max_rate":0.06859977350877192,"is_open":false,"buy_tag":null,"open_timestamp":1517209200000.0,"close_timestamp":1517253900000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014894490408841846,"open_date":"2018-01-29 19:45:00+00:00","close_date":"2018-01-29 20:25:00+00:00","open_rate":0.06713892,"close_rate":0.06747545593984962,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0003365359398496137,"sell_reason":"roi","initial_stop_loss_abs":0.060425028000000006,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060425028000000006,"stop_loss_ratio":0.1,"min_rate":0.06713892,"max_rate":0.06747545593984962,"is_open":false,"buy_tag":null,"open_timestamp":1517255100000.0,"close_timestamp":1517257500000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.193194537721066,"open_date":"2018-01-29 23:30:00+00:00","close_date":"2018-01-30 04:45:00+00:00","open_rate":8.934e-05,"close_rate":8.8e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":315,"profit_ratio":-0.0199116,"profit_abs":-1.3399999999999973e-06,"sell_reason":"force_sell","initial_stop_loss_abs":8.0406e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.0406e-05,"stop_loss_ratio":0.1,"min_rate":8.8e-05,"max_rate":8.934e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517268600000.0,"close_timestamp":1517287500000.0}],"locks":[],"best_pair":{"key":"LTC/BTC","trades":8,"profit_mean":0.00748129625,"profit_mean_pct":0.748129625,"profit_sum":0.05985037,"profit_sum_pct":5.99,"profit_total_abs":0.0015944746365914707,"profit_total":0.15944746365914708,"profit_total_pct":15.94,"duration_avg":"1:59:00","wins":8,"draws":0,"losses":0},"worst_pair":{"key":"XMR/BTC","trades":16,"profit_mean":-0.0027899012500000007,"profit_mean_pct":-0.2789901250000001,"profit_sum":-0.04463842000000001,"profit_sum_pct":-4.46,"profit_total_abs":0.0006671885263157366,"profit_total":0.06671885263157366,"profit_total_pct":6.67,"duration_avg":"8:41:00","wins":15,"draws":0,"losses":1},"results_per_pair":[{"key":"ETH/BTC","trades":21,"profit_mean":0.0009500057142857142,"profit_mean_pct":0.09500057142857142,"profit_sum":0.01995012,"profit_sum_pct":2.0,"profit_total_abs":0.011505731278195264,"profit_total":1.1505731278195264,"profit_total_pct":115.06,"duration_avg":"2:17:00","wins":21,"draws":0,"losses":0},{"key":"DASH/BTC","trades":16,"profit_mean":0.0018703237499999997,"profit_mean_pct":0.18703237499999997,"profit_sum":0.029925179999999996,"profit_sum_pct":2.99,"profit_total_abs":0.007475052681704161,"profit_total":0.7475052681704161,"profit_total_pct":74.75,"duration_avg":"3:03:00","wins":16,"draws":0,"losses":0},{"key":"ZEC/BTC","trades":21,"profit_mean":-0.00039290904761904774,"profit_mean_pct":-0.03929090476190478,"profit_sum":-0.008251090000000003,"profit_sum_pct":-0.83,"profit_total_abs":0.004452605639097655,"profit_total":0.4452605639097655,"profit_total_pct":44.53,"duration_avg":"4:17:00","wins":20,"draws":0,"losses":1},{"key":"LTC/BTC","trades":8,"profit_mean":0.00748129625,"profit_mean_pct":0.748129625,"profit_sum":0.05985037,"profit_sum_pct":5.99,"profit_total_abs":0.0015944746365914707,"profit_total":0.15944746365914708,"profit_total_pct":15.94,"duration_avg":"1:59:00","wins":8,"draws":0,"losses":0},{"key":"XMR/BTC","trades":16,"profit_mean":-0.0027899012500000007,"profit_mean_pct":-0.2789901250000001,"profit_sum":-0.04463842000000001,"profit_sum_pct":-4.46,"profit_total_abs":0.0006671885263157366,"profit_total":0.06671885263157366,"profit_total_pct":6.67,"duration_avg":"8:41:00","wins":15,"draws":0,"losses":1},{"key":"ETC/BTC","trades":20,"profit_mean":0.0022568569999999997,"profit_mean_pct":0.22568569999999996,"profit_sum":0.04513713999999999,"profit_sum_pct":4.51,"profit_total_abs":0.00036538235338345404,"profit_total":0.0365382353383454,"profit_total_pct":3.65,"duration_avg":"1:45:00","wins":19,"draws":0,"losses":1},{"key":"TRX/BTC","trades":15,"profit_mean":0.0023467073333333323,"profit_mean_pct":0.23467073333333321,"profit_sum":0.035200609999999986,"profit_sum_pct":3.52,"profit_total_abs":1.1329523809523682e-05,"profit_total":0.0011329523809523682,"profit_total_pct":0.11,"duration_avg":"2:28:00","wins":13,"draws":0,"losses":2},{"key":"XLM/BTC","trades":21,"profit_mean":0.0026243899999999994,"profit_mean_pct":0.2624389999999999,"profit_sum":0.05511218999999999,"profit_sum_pct":5.51,"profit_total_abs":7.340779448621465e-06,"profit_total":0.0007340779448621465,"profit_total_pct":0.07,"duration_avg":"3:21:00","wins":20,"draws":0,"losses":1},{"key":"ADA/BTC","trades":29,"profit_mean":-0.0011598141379310352,"profit_mean_pct":-0.11598141379310352,"profit_sum":-0.03363461000000002,"profit_sum_pct":-3.36,"profit_total_abs":4.916634085212862e-06,"profit_total":0.0004916634085212862,"profit_total_pct":0.05,"duration_avg":"5:35:00","wins":27,"draws":0,"losses":2},{"key":"NXT/BTC","trades":12,"profit_mean":-0.0012261025000000006,"profit_mean_pct":-0.12261025000000006,"profit_sum":-0.014713230000000008,"profit_sum_pct":-1.47,"profit_total_abs":1.4774411027568458e-06,"profit_total":0.00014774411027568458,"profit_total_pct":0.01,"duration_avg":"0:57:00","wins":11,"draws":0,"losses":1},{"key":"TOTAL","trades":179,"profit_mean":0.0008041243575418989,"profit_mean_pct":0.0804124357541899,"profit_sum":0.1439382599999999,"profit_sum_pct":14.39,"profit_total_abs":0.026085499493733857,"profit_total":2.6085499493733857,"profit_total_pct":260.85,"duration_avg":"3:40:00","wins":170,"draws":0,"losses":9}],"results_per_enter_tag":[{"key":"TOTAL","trades":179,"profit_mean":0.0008041243575418989,"profit_mean_pct":0.0804124357541899,"profit_sum":0.1439382599999999,"profit_sum_pct":14.39,"profit_total_abs":0.026085499493733857,"profit_total":2.6085499493733857,"profit_total_pct":260.85,"duration_avg":"3:40:00","wins":170,"draws":0,"losses":9}],"sell_reason_summary":[{"sell_reason":"roi","trades":170,"wins":170,"draws":0,"losses":0,"profit_mean":0.005398268352941177,"profit_mean_pct":0.54,"profit_sum":0.91770562,"profit_sum_pct":91.77,"profit_total_abs":0.031232837493733862,"profit_total":0.30590187333333335,"profit_total_pct":30.59},{"sell_reason":"stop_loss","trades":6,"wins":0,"draws":0,"losses":6,"profit_mean":-0.10448878000000002,"profit_mean_pct":-10.45,"profit_sum":-0.6269326800000001,"profit_sum_pct":-62.69,"profit_total_abs":-0.0033602680000000026,"profit_total":-0.20897756000000003,"profit_total_pct":-20.9},{"sell_reason":"force_sell","trades":3,"wins":0,"draws":0,"losses":3,"profit_mean":-0.04894489333333333,"profit_mean_pct":-4.89,"profit_sum":-0.14683468,"profit_sum_pct":-14.68,"profit_total_abs":-0.001787070000000003,"profit_total":-0.04894489333333333,"profit_total_pct":-4.89}],"left_open_trades":[{"key":"TOTAL","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0}],"total_trades":179,"total_volume":0.17900000000000005,"avg_stake_amount":0.0010000000000000002,"profit_mean":0.0008041243575418989,"profit_median":0.0,"profit_total":2.6085499493733857,"profit_total_abs":0.026085499493733857,"backtest_start":"2018-01-10 07:15:00","backtest_start_ts":1515568500000,"backtest_end":"2018-01-30 04:45:00","backtest_end_ts":1517287500000,"backtest_days":19,"backtest_run_start_ts":"2020-10-01 18:00:00+00:00","backtest_run_end_ts":"2020-10-01 18:01:00+00:00","trades_per_day":9.42,"market_change":1.22,"pairlist":[],"stake_amount":0.001,"stake_currency":"BTC","stake_currency_decimals":8,"starting_balance":0.01,"dry_run_wallet":0.01,"final_balance":0.03608549949373386,"rejected_signals":0,"max_open_trades":3,"max_open_trades_setting":3,"timeframe":"5m","timeframe_detail":"","timerange":"","enable_protections":false,"strategy_name":"StrategyTestV2","stoploss":0.1,"trailing_stop":false,"trailing_stop_positive":null,"trailing_stop_positive_offset":0.0,"trailing_only_offset_is_reached":false,"use_custom_stoploss":false,"minimal_roi":{},"use_sell_signal":true,"sell_profit_only":false,"sell_profit_offset":false,"ignore_roi_if_buy_signal":false,"backtest_best_day":0.17955111999999998,"backtest_worst_day":-0.14683468,"backtest_best_day_abs":0.0071570099,"backtest_worst_day_abs":-0.0023093218,"winning_days":19,"draw_days":0,"losing_days":2,"daily_profit":[["2018-01-10",0.0025815306],["2018-01-11",0.0049356655],["2018-01-12",0.0006395218],["2018-01-13",0.0002574589],["2018-01-14",0.0010443828],["2018-01-15",0.0024030209],["2018-01-16",0.0071570099],["2018-01-17",0.001137038],["2018-01-18",0.0013712174],["2018-01-19",0.000584673],["2018-01-20",0.0006143386],["2018-01-21",0.0004749361],["2018-01-22",9.91669e-05],["2018-01-23",0.0015726664],["2018-01-24",0.0006610219],["2018-01-25",-0.0023093218],["2018-01-26",0.0003735204],["2018-01-27",0.0023975191],["2018-01-28",0.0007295947],["2018-01-29",0.0011476082],["2018-01-30",-0.00178707]],"wins":48,"losses":9,"draws":122,"holding_avg":"3:40:00","holding_avg_s":13200.0,"winner_holding_avg":"0:24:00","winner_holding_avg_s":1440.0,"loser_holding_avg":"1 day, 5:57:00","loser_holding_avg_s":107820.0,"max_drawdown":0.21142322000000008,"max_drawdown_account":0.08674033488183289,"max_drawdown_abs":0.0030822220000000025,"drawdown_start":"2018-01-25 01:30:00","drawdown_start_ts":1516843800000.0,"drawdown_end":"2018-01-25 03:50:00","drawdown_end_ts":1516852200000.0,"max_drawdown_low":0.02245167355388436,"max_drawdown_high":0.025533895553884363,"csum_min":0.01000434887218045,"csum_max":0.03608683949373386}},"strategy_comparison":[{"key":"StrategyTestV2","trades":179,"profit_mean":0.0008041243575418989,"profit_mean_pct":0.0804124357541899,"profit_sum":0.1439382599999999,"profit_sum_pct":14.39,"profit_total_abs":0.026085499493733857,"profit_total":2.6085499493733857,"profit_total_pct":260.85,"duration_avg":"3:40:00","wins":170,"draws":0,"losses":9,"max_drawdown_account":0.08674033488183289,"max_drawdown_abs":"0.00308222"},{"key":"TestStrategy","trades":179,"profit_mean":0.0008041243575418989,"profit_mean_pct":0.0804124357541899,"profit_sum":0.1439382599999999,"profit_sum_pct":14.39,"profit_total_abs":0.026085499493733857,"profit_total":2.6085499493733857,"profit_total_pct":260.85,"duration_avg":"3:40:00","wins":170,"draws":0,"losses":9,"max_drawdown_account":0.08674033488183289,"max_drawdown_abs":"0.00308222"}]} 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_results/backtest-result_multistrat.json b/tests/testdata/backtest_results/backtest-result_multistrat.json new file mode 100644 index 000000000..786795d67 --- /dev/null +++ b/tests/testdata/backtest_results/backtest-result_multistrat.json @@ -0,0 +1 @@ +{"strategy":{"StrategyTestV2":{"trades":[{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.37344398340249,"open_date":"2018-01-10 07:15:00+00:00","close_date":"2018-01-10 07:20:00+00:00","open_rate":9.64e-05,"close_rate":0.00010074887218045112,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":4.348872180451118e-06,"exit_reason":"roi","initial_stop_loss_abs":8.676e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.676e-05,"stop_loss_ratio":0.1,"min_rate":9.64e-05,"max_rate":0.00010074887218045112,"is_open":false,"buy_tag":null,"open_timestamp":1515568500000.0,"close_timestamp":1515568800000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":21.026072329688816,"open_date":"2018-01-10 07:15:00+00:00","close_date":"2018-01-10 07:30:00+00:00","open_rate":4.756e-05,"close_rate":4.9705563909774425e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":15,"profit_ratio":0.03990025,"profit_abs":2.1455639097744267e-06,"exit_reason":"roi","initial_stop_loss_abs":4.2804e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.2804e-05,"stop_loss_ratio":0.1,"min_rate":4.756e-05,"max_rate":4.9705563909774425e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515568500000.0,"close_timestamp":1515569400000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":29.94908655286014,"open_date":"2018-01-10 07:25:00+00:00","close_date":"2018-01-10 07:35:00+00:00","open_rate":3.339e-05,"close_rate":3.489631578947368e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":10,"profit_ratio":0.03990025,"profit_abs":1.506315789473681e-06,"exit_reason":"roi","initial_stop_loss_abs":3.0050999999999997e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.0050999999999997e-05,"stop_loss_ratio":0.1,"min_rate":3.339e-05,"max_rate":3.489631578947368e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515569100000.0,"close_timestamp":1515569700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.313531353135314,"open_date":"2018-01-10 07:25:00+00:00","close_date":"2018-01-10 07:40:00+00:00","open_rate":9.696e-05,"close_rate":0.00010133413533834584,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":15,"profit_ratio":0.03990025,"profit_abs":4.3741353383458455e-06,"exit_reason":"roi","initial_stop_loss_abs":8.7264e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.7264e-05,"stop_loss_ratio":0.1,"min_rate":9.696e-05,"max_rate":0.00010133413533834584,"is_open":false,"buy_tag":null,"open_timestamp":1515569100000.0,"close_timestamp":1515570000000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010604453870625663,"open_date":"2018-01-10 07:35:00+00:00","close_date":"2018-01-10 08:35:00+00:00","open_rate":0.0943,"close_rate":0.09477268170426063,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.0,"profit_abs":0.0004726817042606385,"exit_reason":"roi","initial_stop_loss_abs":0.08487,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08487,"stop_loss_ratio":0.1,"min_rate":0.0943,"max_rate":0.09477268170426063,"is_open":false,"buy_tag":null,"open_timestamp":1515569700000.0,"close_timestamp":1515573300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03677001860930642,"open_date":"2018-01-10 07:40:00+00:00","close_date":"2018-01-10 08:10:00+00:00","open_rate":0.02719607,"close_rate":0.02760503345864661,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.00040896345864661204,"exit_reason":"roi","initial_stop_loss_abs":0.024476463,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.024476463,"stop_loss_ratio":0.1,"min_rate":0.02719607,"max_rate":0.02760503345864661,"is_open":false,"buy_tag":null,"open_timestamp":1515570000000.0,"close_timestamp":1515571800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.021575196463739,"open_date":"2018-01-10 08:15:00+00:00","close_date":"2018-01-10 09:55:00+00:00","open_rate":0.04634952,"close_rate":0.046581848421052625,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":100,"profit_ratio":0.0,"profit_abs":0.0002323284210526272,"exit_reason":"roi","initial_stop_loss_abs":0.041714568,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.041714568,"stop_loss_ratio":0.1,"min_rate":0.04634952,"max_rate":0.046581848421052625,"is_open":false,"buy_tag":null,"open_timestamp":1515572100000.0,"close_timestamp":1515578100000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":32.615786040443574,"open_date":"2018-01-10 14:45:00+00:00","close_date":"2018-01-10 15:50:00+00:00","open_rate":3.066e-05,"close_rate":3.081368421052631e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":65,"profit_ratio":-0.0,"profit_abs":1.5368421052630647e-07,"exit_reason":"roi","initial_stop_loss_abs":2.7594e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7594e-05,"stop_loss_ratio":0.1,"min_rate":3.066e-05,"max_rate":3.081368421052631e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515595500000.0,"close_timestamp":1515599400000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.05917194776300452,"open_date":"2018-01-10 16:35:00+00:00","close_date":"2018-01-10 17:15:00+00:00","open_rate":0.0168999,"close_rate":0.016984611278195488,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":8.471127819548868e-05,"exit_reason":"roi","initial_stop_loss_abs":0.01520991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.01520991,"stop_loss_ratio":0.1,"min_rate":0.0168999,"max_rate":0.016984611278195488,"is_open":false,"buy_tag":null,"open_timestamp":1515602100000.0,"close_timestamp":1515604500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010949822656672253,"open_date":"2018-01-10 16:40:00+00:00","close_date":"2018-01-10 17:20:00+00:00","open_rate":0.09132568,"close_rate":0.0917834528320802,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004577728320801916,"exit_reason":"roi","initial_stop_loss_abs":0.08219311200000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08219311200000001,"stop_loss_ratio":0.1,"min_rate":0.09132568,"max_rate":0.0917834528320802,"is_open":false,"buy_tag":null,"open_timestamp":1515602400000.0,"close_timestamp":1515604800000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011238476768326556,"open_date":"2018-01-10 18:50:00+00:00","close_date":"2018-01-10 19:45:00+00:00","open_rate":0.08898003,"close_rate":0.08942604518796991,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":0.00044601518796991146,"exit_reason":"roi","initial_stop_loss_abs":0.080082027,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.080082027,"stop_loss_ratio":0.1,"min_rate":0.08898003,"max_rate":0.08942604518796991,"is_open":false,"buy_tag":null,"open_timestamp":1515610200000.0,"close_timestamp":1515613500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011682232072680307,"open_date":"2018-01-10 22:15:00+00:00","close_date":"2018-01-10 23:00:00+00:00","open_rate":0.08560008,"close_rate":0.08602915308270676,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":0.0,"profit_abs":0.00042907308270676014,"exit_reason":"roi","initial_stop_loss_abs":0.077040072,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.077040072,"stop_loss_ratio":0.1,"min_rate":0.08560008,"max_rate":0.08602915308270676,"is_open":false,"buy_tag":null,"open_timestamp":1515622500000.0,"close_timestamp":1515625200000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.4014726015023105,"open_date":"2018-01-10 22:50:00+00:00","close_date":"2018-01-10 23:20:00+00:00","open_rate":0.00249083,"close_rate":0.0025282860902255634,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":3.745609022556351e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002241747,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002241747,"stop_loss_ratio":0.1,"min_rate":0.00249083,"max_rate":0.0025282860902255634,"is_open":false,"buy_tag":null,"open_timestamp":1515624600000.0,"close_timestamp":1515626400000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":33.090668431502316,"open_date":"2018-01-10 23:15:00+00:00","close_date":"2018-01-11 00:15:00+00:00","open_rate":3.022e-05,"close_rate":3.037147869674185e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.0,"profit_abs":1.5147869674185174e-07,"exit_reason":"roi","initial_stop_loss_abs":2.7198e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7198e-05,"stop_loss_ratio":0.1,"min_rate":3.022e-05,"max_rate":3.037147869674185e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515626100000.0,"close_timestamp":1515629700000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.41034058268362744,"open_date":"2018-01-10 23:40:00+00:00","close_date":"2018-01-11 00:05:00+00:00","open_rate":0.002437,"close_rate":0.0024980776942355883,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":6.107769423558838e-05,"exit_reason":"roi","initial_stop_loss_abs":0.0021933,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0021933,"stop_loss_ratio":0.1,"min_rate":0.002437,"max_rate":0.0024980776942355883,"is_open":false,"buy_tag":null,"open_timestamp":1515627600000.0,"close_timestamp":1515629100000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02095643931654345,"open_date":"2018-01-11 00:00:00+00:00","close_date":"2018-01-11 00:35:00+00:00","open_rate":0.04771803,"close_rate":0.04843559436090225,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0007175643609022495,"exit_reason":"roi","initial_stop_loss_abs":0.042946227000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.042946227000000003,"stop_loss_ratio":0.1,"min_rate":0.04771803,"max_rate":0.04843559436090225,"is_open":false,"buy_tag":null,"open_timestamp":1515628800000.0,"close_timestamp":1515630900000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":27.389756231169542,"open_date":"2018-01-11 03:40:00+00:00","close_date":"2018-01-11 04:25:00+00:00","open_rate":3.651e-05,"close_rate":3.2859000000000005e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.10448878,"profit_abs":-3.650999999999996e-06,"exit_reason":"stop_loss","initial_stop_loss_abs":3.2859000000000005e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.2859000000000005e-05,"stop_loss_ratio":0.1,"min_rate":3.2859000000000005e-05,"max_rate":3.651e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515642000000.0,"close_timestamp":1515644700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011332594070446804,"open_date":"2018-01-11 03:55:00+00:00","close_date":"2018-01-11 04:25:00+00:00","open_rate":0.08824105,"close_rate":0.08956798308270676,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.0013269330827067605,"exit_reason":"roi","initial_stop_loss_abs":0.079416945,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.079416945,"stop_loss_ratio":0.1,"min_rate":0.08824105,"max_rate":0.08956798308270676,"is_open":false,"buy_tag":null,"open_timestamp":1515642900000.0,"close_timestamp":1515644700000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.411522633744856,"open_date":"2018-01-11 04:00:00+00:00","close_date":"2018-01-11 04:50:00+00:00","open_rate":0.00243,"close_rate":0.002442180451127819,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":-0.0,"profit_abs":1.2180451127819219e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002187,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002187,"stop_loss_ratio":0.1,"min_rate":0.00243,"max_rate":0.002442180451127819,"is_open":false,"buy_tag":null,"open_timestamp":1515643200000.0,"close_timestamp":1515646200000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022001890402423376,"open_date":"2018-01-11 04:30:00+00:00","close_date":"2018-01-11 04:55:00+00:00","open_rate":0.04545064,"close_rate":0.046589753784461146,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":0.001139113784461146,"exit_reason":"roi","initial_stop_loss_abs":0.040905576,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.040905576,"stop_loss_ratio":0.1,"min_rate":0.04545064,"max_rate":0.046589753784461146,"is_open":false,"buy_tag":null,"open_timestamp":1515645000000.0,"close_timestamp":1515646500000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":29.655990510083036,"open_date":"2018-01-11 04:30:00+00:00","close_date":"2018-01-11 04:50:00+00:00","open_rate":3.372e-05,"close_rate":3.456511278195488e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":8.4511278195488e-07,"exit_reason":"roi","initial_stop_loss_abs":3.0348e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.0348e-05,"stop_loss_ratio":0.1,"min_rate":3.372e-05,"max_rate":3.456511278195488e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515645000000.0,"close_timestamp":1515646200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.037821482602118005,"open_date":"2018-01-11 04:55:00+00:00","close_date":"2018-01-11 05:15:00+00:00","open_rate":0.02644,"close_rate":0.02710265664160401,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":0.0006626566416040071,"exit_reason":"roi","initial_stop_loss_abs":0.023796,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.023796,"stop_loss_ratio":0.1,"min_rate":0.02644,"max_rate":0.02710265664160401,"is_open":false,"buy_tag":null,"open_timestamp":1515646500000.0,"close_timestamp":1515647700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011348161597821153,"open_date":"2018-01-11 11:20:00+00:00","close_date":"2018-01-11 12:00:00+00:00","open_rate":0.08812,"close_rate":0.08856170426065162,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004417042606516125,"exit_reason":"roi","initial_stop_loss_abs":0.079308,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.079308,"stop_loss_ratio":0.1,"min_rate":0.08812,"max_rate":0.08856170426065162,"is_open":false,"buy_tag":null,"open_timestamp":1515669600000.0,"close_timestamp":1515672000000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.037263696923919086,"open_date":"2018-01-11 11:35:00+00:00","close_date":"2018-01-11 12:15:00+00:00","open_rate":0.02683577,"close_rate":0.026970285137844607,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00013451513784460897,"exit_reason":"roi","initial_stop_loss_abs":0.024152193,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.024152193,"stop_loss_ratio":0.1,"min_rate":0.02683577,"max_rate":0.026970285137844607,"is_open":false,"buy_tag":null,"open_timestamp":1515670500000.0,"close_timestamp":1515672900000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":20.329335230737954,"open_date":"2018-01-11 14:00:00+00:00","close_date":"2018-01-11 14:25:00+00:00","open_rate":4.919e-05,"close_rate":5.04228320802005e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":1.232832080200495e-06,"exit_reason":"roi","initial_stop_loss_abs":4.4271000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4271000000000004e-05,"stop_loss_ratio":0.1,"min_rate":4.919e-05,"max_rate":5.04228320802005e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515679200000.0,"close_timestamp":1515680700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.01138317402960718,"open_date":"2018-01-11 19:25:00+00:00","close_date":"2018-01-11 20:35:00+00:00","open_rate":0.08784896,"close_rate":0.08828930566416039,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":70,"profit_ratio":-0.0,"profit_abs":0.0004403456641603881,"exit_reason":"roi","initial_stop_loss_abs":0.079064064,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.079064064,"stop_loss_ratio":0.1,"min_rate":0.08784896,"max_rate":0.08828930566416039,"is_open":false,"buy_tag":null,"open_timestamp":1515698700000.0,"close_timestamp":1515702900000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.58863858961802,"open_date":"2018-01-11 22:35:00+00:00","close_date":"2018-01-11 23:30:00+00:00","open_rate":5.105e-05,"close_rate":5.130588972431077e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.558897243107704e-07,"exit_reason":"roi","initial_stop_loss_abs":4.5945e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.5945e-05,"stop_loss_ratio":0.1,"min_rate":5.105e-05,"max_rate":5.130588972431077e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515710100000.0,"close_timestamp":1515713400000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":25.252525252525253,"open_date":"2018-01-11 22:55:00+00:00","close_date":"2018-01-11 23:25:00+00:00","open_rate":3.96e-05,"close_rate":4.019548872180451e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":5.954887218045116e-07,"exit_reason":"roi","initial_stop_loss_abs":3.5640000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.5640000000000004e-05,"stop_loss_ratio":0.1,"min_rate":3.96e-05,"max_rate":4.019548872180451e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515711300000.0,"close_timestamp":1515713100000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":34.66204506065858,"open_date":"2018-01-11 22:55:00+00:00","close_date":"2018-01-11 23:35:00+00:00","open_rate":2.885e-05,"close_rate":2.899461152882205e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.4461152882205115e-07,"exit_reason":"roi","initial_stop_loss_abs":2.5965e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.5965e-05,"stop_loss_ratio":0.1,"min_rate":2.885e-05,"max_rate":2.899461152882205e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515711300000.0,"close_timestamp":1515713700000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03780718336483932,"open_date":"2018-01-11 23:30:00+00:00","close_date":"2018-01-12 00:05:00+00:00","open_rate":0.02645,"close_rate":0.026847744360902256,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0003977443609022545,"exit_reason":"roi","initial_stop_loss_abs":0.023805000000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.023805000000000003,"stop_loss_ratio":0.1,"min_rate":0.02645,"max_rate":0.026847744360902256,"is_open":false,"buy_tag":null,"open_timestamp":1515713400000.0,"close_timestamp":1515715500000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.020833333333333332,"open_date":"2018-01-11 23:55:00+00:00","close_date":"2018-01-12 01:15:00+00:00","open_rate":0.048,"close_rate":0.04824060150375939,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.0,"profit_abs":0.00024060150375938838,"exit_reason":"roi","initial_stop_loss_abs":0.0432,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0432,"stop_loss_ratio":0.1,"min_rate":0.048,"max_rate":0.04824060150375939,"is_open":false,"buy_tag":null,"open_timestamp":1515714900000.0,"close_timestamp":1515719700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":21.31287297527707,"open_date":"2018-01-12 21:15:00+00:00","close_date":"2018-01-12 21:40:00+00:00","open_rate":4.692e-05,"close_rate":4.809593984962405e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":1.1759398496240516e-06,"exit_reason":"roi","initial_stop_loss_abs":4.2227999999999996e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.2227999999999996e-05,"stop_loss_ratio":0.1,"min_rate":4.692e-05,"max_rate":4.809593984962405e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515791700000.0,"close_timestamp":1515793200000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38915654211062944,"open_date":"2018-01-13 00:55:00+00:00","close_date":"2018-01-13 06:20:00+00:00","open_rate":0.00256966,"close_rate":0.0025825405012531327,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":325,"profit_ratio":-0.0,"profit_abs":1.2880501253132587e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002312694,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002312694,"stop_loss_ratio":0.1,"min_rate":0.00256966,"max_rate":0.0025825405012531327,"is_open":false,"buy_tag":null,"open_timestamp":1515804900000.0,"close_timestamp":1515824400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":15.96933886937081,"open_date":"2018-01-13 10:55:00+00:00","close_date":"2018-01-13 11:35:00+00:00","open_rate":6.262e-05,"close_rate":6.293388471177944e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":3.138847117794446e-07,"exit_reason":"roi","initial_stop_loss_abs":5.6358e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.6358e-05,"stop_loss_ratio":0.1,"min_rate":6.262e-05,"max_rate":6.293388471177944e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515840900000.0,"close_timestamp":1515843300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":21.141649048625794,"open_date":"2018-01-13 13:05:00+00:00","close_date":"2018-01-15 14:10:00+00:00","open_rate":4.73e-05,"close_rate":4.753709273182957e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":2945,"profit_ratio":0.0,"profit_abs":2.3709273182957117e-07,"exit_reason":"roi","initial_stop_loss_abs":4.257e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.257e-05,"stop_loss_ratio":0.1,"min_rate":4.73e-05,"max_rate":4.753709273182957e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515848700000.0,"close_timestamp":1516025400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":16.49348507339601,"open_date":"2018-01-13 13:30:00+00:00","close_date":"2018-01-13 14:45:00+00:00","open_rate":6.063e-05,"close_rate":6.0933909774436085e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":75,"profit_ratio":-0.0,"profit_abs":3.039097744360846e-07,"exit_reason":"roi","initial_stop_loss_abs":5.4567e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.4567e-05,"stop_loss_ratio":0.1,"min_rate":6.063e-05,"max_rate":6.0933909774436085e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515850200000.0,"close_timestamp":1515854700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":9.023641941887746,"open_date":"2018-01-13 13:40:00+00:00","close_date":"2018-01-13 23:30:00+00:00","open_rate":0.00011082,"close_rate":0.00011137548872180448,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":590,"profit_ratio":-0.0,"profit_abs":5.554887218044781e-07,"exit_reason":"roi","initial_stop_loss_abs":9.9738e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":9.9738e-05,"stop_loss_ratio":0.1,"min_rate":0.00011082,"max_rate":0.00011137548872180448,"is_open":false,"buy_tag":null,"open_timestamp":1515850800000.0,"close_timestamp":1515886200000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":16.863406408094438,"open_date":"2018-01-13 15:15:00+00:00","close_date":"2018-01-13 15:55:00+00:00","open_rate":5.93e-05,"close_rate":5.9597243107769415e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.9724310776941686e-07,"exit_reason":"roi","initial_stop_loss_abs":5.337e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.337e-05,"stop_loss_ratio":0.1,"min_rate":5.93e-05,"max_rate":5.9597243107769415e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515856500000.0,"close_timestamp":1515858900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.020618543947292404,"open_date":"2018-01-13 16:30:00+00:00","close_date":"2018-01-13 17:10:00+00:00","open_rate":0.04850003,"close_rate":0.04874313791979949,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00024310791979949287,"exit_reason":"roi","initial_stop_loss_abs":0.043650027,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.043650027,"stop_loss_ratio":0.1,"min_rate":0.04850003,"max_rate":0.04874313791979949,"is_open":false,"buy_tag":null,"open_timestamp":1515861000000.0,"close_timestamp":1515863400000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010178097365511457,"open_date":"2018-01-13 22:05:00+00:00","close_date":"2018-01-14 06:25:00+00:00","open_rate":0.09825019,"close_rate":0.09874267215538848,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":500,"profit_ratio":-0.0,"profit_abs":0.0004924821553884823,"exit_reason":"roi","initial_stop_loss_abs":0.088425171,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.088425171,"stop_loss_ratio":0.1,"min_rate":0.09825019,"max_rate":0.09874267215538848,"is_open":false,"buy_tag":null,"open_timestamp":1515881100000.0,"close_timestamp":1515911100000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":16.616816218012627,"open_date":"2018-01-14 00:20:00+00:00","close_date":"2018-01-14 22:55:00+00:00","open_rate":6.018e-05,"close_rate":6.048165413533834e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":1355,"profit_ratio":0.0,"profit_abs":3.0165413533833987e-07,"exit_reason":"roi","initial_stop_loss_abs":5.4162e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.4162e-05,"stop_loss_ratio":0.1,"min_rate":6.018e-05,"max_rate":6.048165413533834e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515889200000.0,"close_timestamp":1515970500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010246952581919518,"open_date":"2018-01-14 12:45:00+00:00","close_date":"2018-01-14 13:25:00+00:00","open_rate":0.09758999,"close_rate":0.0980791628822055,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004891728822054991,"exit_reason":"roi","initial_stop_loss_abs":0.087830991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.087830991,"stop_loss_ratio":0.1,"min_rate":0.09758999,"max_rate":0.0980791628822055,"is_open":false,"buy_tag":null,"open_timestamp":1515933900000.0,"close_timestamp":1515936300000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3215434083601286,"open_date":"2018-01-14 15:30:00+00:00","close_date":"2018-01-14 16:00:00+00:00","open_rate":0.00311,"close_rate":0.0031567669172932328,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.676691729323286e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002799,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002799,"stop_loss_ratio":0.1,"min_rate":0.00311,"max_rate":0.0031567669172932328,"is_open":false,"buy_tag":null,"open_timestamp":1515943800000.0,"close_timestamp":1515945600000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.32010140812609433,"open_date":"2018-01-14 20:45:00+00:00","close_date":"2018-01-14 22:15:00+00:00","open_rate":0.00312401,"close_rate":0.003139669197994987,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":90,"profit_ratio":-0.0,"profit_abs":1.5659197994987058e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002811609,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002811609,"stop_loss_ratio":0.1,"min_rate":0.00312401,"max_rate":0.003139669197994987,"is_open":false,"buy_tag":null,"open_timestamp":1515962700000.0,"close_timestamp":1515968100000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.057247866085791646,"open_date":"2018-01-14 23:35:00+00:00","close_date":"2018-01-15 00:30:00+00:00","open_rate":0.0174679,"close_rate":0.017555458395989976,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":0.0,"profit_abs":8.755839598997492e-05,"exit_reason":"roi","initial_stop_loss_abs":0.015721110000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.015721110000000003,"stop_loss_ratio":0.1,"min_rate":0.0174679,"max_rate":0.017555458395989976,"is_open":false,"buy_tag":null,"open_timestamp":1515972900000.0,"close_timestamp":1515976200000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.013611282991367997,"open_date":"2018-01-14 23:45:00+00:00","close_date":"2018-01-15 00:25:00+00:00","open_rate":0.07346846,"close_rate":0.07383672295739348,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00036826295739347814,"exit_reason":"roi","initial_stop_loss_abs":0.066121614,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.066121614,"stop_loss_ratio":0.1,"min_rate":0.07346846,"max_rate":0.07383672295739348,"is_open":false,"buy_tag":null,"open_timestamp":1515973500000.0,"close_timestamp":1515975900000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010204706410596568,"open_date":"2018-01-15 02:25:00+00:00","close_date":"2018-01-15 03:05:00+00:00","open_rate":0.097994,"close_rate":0.09848519799498744,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004911979949874384,"exit_reason":"roi","initial_stop_loss_abs":0.0881946,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0881946,"stop_loss_ratio":0.1,"min_rate":0.097994,"max_rate":0.09848519799498744,"is_open":false,"buy_tag":null,"open_timestamp":1515983100000.0,"close_timestamp":1515985500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010353038616834042,"open_date":"2018-01-15 07:20:00+00:00","close_date":"2018-01-15 08:00:00+00:00","open_rate":0.09659,"close_rate":0.09707416040100247,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004841604010024786,"exit_reason":"roi","initial_stop_loss_abs":0.086931,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.086931,"stop_loss_ratio":0.1,"min_rate":0.09659,"max_rate":0.09707416040100247,"is_open":false,"buy_tag":null,"open_timestamp":1516000800000.0,"close_timestamp":1516003200000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.013016921998599,"open_date":"2018-01-15 08:20:00+00:00","close_date":"2018-01-15 08:55:00+00:00","open_rate":9.987e-05,"close_rate":0.00010137180451127818,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":1.501804511278178e-06,"exit_reason":"roi","initial_stop_loss_abs":8.9883e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.9883e-05,"stop_loss_ratio":0.1,"min_rate":9.987e-05,"max_rate":0.00010137180451127818,"is_open":false,"buy_tag":null,"open_timestamp":1516004400000.0,"close_timestamp":1516006500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010537752023511832,"open_date":"2018-01-15 12:10:00+00:00","close_date":"2018-01-16 02:50:00+00:00","open_rate":0.0948969,"close_rate":0.09537257368421052,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":880,"profit_ratio":0.0,"profit_abs":0.0004756736842105175,"exit_reason":"roi","initial_stop_loss_abs":0.08540721000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08540721000000001,"stop_loss_ratio":0.1,"min_rate":0.0948969,"max_rate":0.09537257368421052,"is_open":false,"buy_tag":null,"open_timestamp":1516018200000.0,"close_timestamp":1516071000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014084507042253523,"open_date":"2018-01-15 14:10:00+00:00","close_date":"2018-01-15 17:40:00+00:00","open_rate":0.071,"close_rate":0.07135588972431077,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":210,"profit_ratio":-0.0,"profit_abs":0.00035588972431077615,"exit_reason":"roi","initial_stop_loss_abs":0.0639,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0639,"stop_loss_ratio":0.1,"min_rate":0.071,"max_rate":0.07135588972431077,"is_open":false,"buy_tag":null,"open_timestamp":1516025400000.0,"close_timestamp":1516038000000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.021736763017766978,"open_date":"2018-01-15 14:30:00+00:00","close_date":"2018-01-15 15:10:00+00:00","open_rate":0.04600501,"close_rate":0.046235611553884705,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00023060155388470588,"exit_reason":"roi","initial_stop_loss_abs":0.041404509,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.041404509,"stop_loss_ratio":0.1,"min_rate":0.04600501,"max_rate":0.046235611553884705,"is_open":false,"buy_tag":null,"open_timestamp":1516026600000.0,"close_timestamp":1516029000000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.595465140919686,"open_date":"2018-01-15 18:10:00+00:00","close_date":"2018-01-15 19:25:00+00:00","open_rate":9.438e-05,"close_rate":9.485308270676693e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":75,"profit_ratio":-0.0,"profit_abs":4.7308270676692514e-07,"exit_reason":"roi","initial_stop_loss_abs":8.4942e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.4942e-05,"stop_loss_ratio":0.1,"min_rate":9.438e-05,"max_rate":9.485308270676693e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516039800000.0,"close_timestamp":1516044300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.032894726021471705,"open_date":"2018-01-15 18:35:00+00:00","close_date":"2018-01-15 19:15:00+00:00","open_rate":0.03040001,"close_rate":0.030552391002506264,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0001523810025062626,"exit_reason":"roi","initial_stop_loss_abs":0.027360009,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.027360009,"stop_loss_ratio":0.1,"min_rate":0.03040001,"max_rate":0.030552391002506264,"is_open":false,"buy_tag":null,"open_timestamp":1516041300000.0,"close_timestamp":1516043700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.13208840157615,"open_date":"2018-01-15 20:25:00+00:00","close_date":"2018-01-16 08:25:00+00:00","open_rate":5.837e-05,"close_rate":5.2533e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":720,"profit_ratio":-0.10448878,"profit_abs":-5.8369999999999985e-06,"exit_reason":"stop_loss","initial_stop_loss_abs":5.2533e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.2533e-05,"stop_loss_ratio":0.1,"min_rate":5.2533e-05,"max_rate":5.837e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516047900000.0,"close_timestamp":1516091100000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.021722130506560085,"open_date":"2018-01-15 20:40:00+00:00","close_date":"2018-01-15 22:00:00+00:00","open_rate":0.046036,"close_rate":0.04626675689223057,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.0,"profit_abs":0.00023075689223057277,"exit_reason":"roi","initial_stop_loss_abs":0.0414324,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0414324,"stop_loss_ratio":0.1,"min_rate":0.046036,"max_rate":0.04626675689223057,"is_open":false,"buy_tag":null,"open_timestamp":1516048800000.0,"close_timestamp":1516053600000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.34861425832316545,"open_date":"2018-01-16 00:30:00+00:00","close_date":"2018-01-16 01:10:00+00:00","open_rate":0.0028685,"close_rate":0.0028828784461152877,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.4378446115287727e-05,"exit_reason":"roi","initial_stop_loss_abs":0.00258165,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.00258165,"stop_loss_ratio":0.1,"min_rate":0.0028685,"max_rate":0.0028828784461152877,"is_open":false,"buy_tag":null,"open_timestamp":1516062600000.0,"close_timestamp":1516065000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014854967241083492,"open_date":"2018-01-16 01:15:00+00:00","close_date":"2018-01-16 02:35:00+00:00","open_rate":0.06731755,"close_rate":0.0676549813283208,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":0.0,"profit_abs":0.00033743132832080025,"exit_reason":"roi","initial_stop_loss_abs":0.060585795000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060585795000000005,"stop_loss_ratio":0.1,"min_rate":0.06731755,"max_rate":0.0676549813283208,"is_open":false,"buy_tag":null,"open_timestamp":1516065300000.0,"close_timestamp":1516070100000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010848794492804754,"open_date":"2018-01-16 07:45:00+00:00","close_date":"2018-01-16 08:40:00+00:00","open_rate":0.09217614,"close_rate":0.09263817578947368,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":0.0,"profit_abs":0.0004620357894736804,"exit_reason":"roi","initial_stop_loss_abs":0.082958526,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.082958526,"stop_loss_ratio":0.1,"min_rate":0.09217614,"max_rate":0.09263817578947368,"is_open":false,"buy_tag":null,"open_timestamp":1516088700000.0,"close_timestamp":1516092000000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06060606060606061,"open_date":"2018-01-16 08:35:00+00:00","close_date":"2018-01-16 08:55:00+00:00","open_rate":0.0165,"close_rate":0.016913533834586467,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":0.00041353383458646656,"exit_reason":"roi","initial_stop_loss_abs":0.01485,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.01485,"stop_loss_ratio":0.1,"min_rate":0.0165,"max_rate":0.016913533834586467,"is_open":false,"buy_tag":null,"open_timestamp":1516091700000.0,"close_timestamp":1516092900000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":12.57387149503332,"open_date":"2018-01-16 08:35:00+00:00","close_date":"2018-01-16 08:40:00+00:00","open_rate":7.953e-05,"close_rate":8.311781954887218e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":3.587819548872171e-06,"exit_reason":"roi","initial_stop_loss_abs":7.157700000000001e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":7.157700000000001e-05,"stop_loss_ratio":0.1,"min_rate":7.953e-05,"max_rate":8.311781954887218e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516091700000.0,"close_timestamp":1516092000000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022122914915269236,"open_date":"2018-01-16 08:45:00+00:00","close_date":"2018-01-16 09:50:00+00:00","open_rate":0.045202,"close_rate":0.04542857644110275,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":65,"profit_ratio":-0.0,"profit_abs":0.00022657644110275071,"exit_reason":"roi","initial_stop_loss_abs":0.0406818,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0406818,"stop_loss_ratio":0.1,"min_rate":0.045202,"max_rate":0.04542857644110275,"is_open":false,"buy_tag":null,"open_timestamp":1516092300000.0,"close_timestamp":1516096200000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.054878048780488,"open_date":"2018-01-16 09:15:00+00:00","close_date":"2018-01-16 09:45:00+00:00","open_rate":5.248e-05,"close_rate":5.326917293233082e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":7.891729323308177e-07,"exit_reason":"roi","initial_stop_loss_abs":4.7232e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7232e-05,"stop_loss_ratio":0.1,"min_rate":5.248e-05,"max_rate":5.326917293233082e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516094100000.0,"close_timestamp":1516095900000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03457434486802627,"open_date":"2018-01-16 09:15:00+00:00","close_date":"2018-01-16 09:55:00+00:00","open_rate":0.02892318,"close_rate":0.02906815834586466,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.0001449783458646603,"exit_reason":"roi","initial_stop_loss_abs":0.026030862000000002,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.026030862000000002,"stop_loss_ratio":0.1,"min_rate":0.02892318,"max_rate":0.02906815834586466,"is_open":false,"buy_tag":null,"open_timestamp":1516094100000.0,"close_timestamp":1516096500000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.38735944164405,"open_date":"2018-01-16 09:50:00+00:00","close_date":"2018-01-16 10:10:00+00:00","open_rate":5.158e-05,"close_rate":5.287273182957392e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":1.2927318295739246e-06,"exit_reason":"roi","initial_stop_loss_abs":4.6422e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6422e-05,"stop_loss_ratio":0.1,"min_rate":5.158e-05,"max_rate":5.287273182957392e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516096200000.0,"close_timestamp":1516097400000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.035357778286929785,"open_date":"2018-01-16 10:05:00+00:00","close_date":"2018-01-16 10:35:00+00:00","open_rate":0.02828232,"close_rate":0.02870761804511278,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.00042529804511277913,"exit_reason":"roi","initial_stop_loss_abs":0.025454088,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025454088,"stop_loss_ratio":0.1,"min_rate":0.02828232,"max_rate":0.02870761804511278,"is_open":false,"buy_tag":null,"open_timestamp":1516097100000.0,"close_timestamp":1516098900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022948496230938982,"open_date":"2018-01-16 10:05:00+00:00","close_date":"2018-01-16 10:40:00+00:00","open_rate":0.04357584,"close_rate":0.044231115789473675,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0006552757894736777,"exit_reason":"roi","initial_stop_loss_abs":0.039218256,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.039218256,"stop_loss_ratio":0.1,"min_rate":0.04357584,"max_rate":0.044231115789473675,"is_open":false,"buy_tag":null,"open_timestamp":1516097100000.0,"close_timestamp":1516099200000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.64975755315181,"open_date":"2018-01-16 13:45:00+00:00","close_date":"2018-01-16 14:20:00+00:00","open_rate":5.362e-05,"close_rate":5.442631578947368e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":8.063157894736843e-07,"exit_reason":"roi","initial_stop_loss_abs":4.8258e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.8258e-05,"stop_loss_ratio":0.1,"min_rate":5.362e-05,"max_rate":5.442631578947368e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516110300000.0,"close_timestamp":1516112400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.86080724254998,"open_date":"2018-01-16 17:30:00+00:00","close_date":"2018-01-16 18:25:00+00:00","open_rate":5.302e-05,"close_rate":5.328576441102756e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.6576441102756397e-07,"exit_reason":"roi","initial_stop_loss_abs":4.7718e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7718e-05,"stop_loss_ratio":0.1,"min_rate":5.302e-05,"max_rate":5.328576441102756e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516123800000.0,"close_timestamp":1516127100000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010952903718828448,"open_date":"2018-01-16 18:15:00+00:00","close_date":"2018-01-16 18:45:00+00:00","open_rate":0.09129999,"close_rate":0.09267292218045112,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.0013729321804511196,"exit_reason":"roi","initial_stop_loss_abs":0.082169991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.082169991,"stop_loss_ratio":0.1,"min_rate":0.09129999,"max_rate":0.09267292218045112,"is_open":false,"buy_tag":null,"open_timestamp":1516126500000.0,"close_timestamp":1516128300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":26.26050420168067,"open_date":"2018-01-16 18:15:00+00:00","close_date":"2018-01-16 18:35:00+00:00","open_rate":3.808e-05,"close_rate":3.903438596491228e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":9.543859649122774e-07,"exit_reason":"roi","initial_stop_loss_abs":3.4272e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.4272e-05,"stop_loss_ratio":0.1,"min_rate":3.808e-05,"max_rate":3.903438596491228e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516126500000.0,"close_timestamp":1516127700000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.035574376772493324,"open_date":"2018-01-16 19:00:00+00:00","close_date":"2018-01-16 19:30:00+00:00","open_rate":0.02811012,"close_rate":0.028532828571428567,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.00042270857142856846,"exit_reason":"roi","initial_stop_loss_abs":0.025299108,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025299108,"stop_loss_ratio":0.1,"min_rate":0.02811012,"max_rate":0.028532828571428567,"is_open":false,"buy_tag":null,"open_timestamp":1516129200000.0,"close_timestamp":1516131000000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.387028357567759,"open_date":"2018-01-16 21:25:00+00:00","close_date":"2018-01-16 22:25:00+00:00","open_rate":0.00258379,"close_rate":0.002325411,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.10448878,"profit_abs":-0.000258379,"exit_reason":"stop_loss","initial_stop_loss_abs":0.002325411,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002325411,"stop_loss_ratio":0.1,"min_rate":0.002325411,"max_rate":0.00258379,"is_open":false,"buy_tag":null,"open_timestamp":1516137900000.0,"close_timestamp":1516141500000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":39.07776475185619,"open_date":"2018-01-16 21:25:00+00:00","close_date":"2018-01-16 22:45:00+00:00","open_rate":2.559e-05,"close_rate":2.3031e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.10448878,"profit_abs":-2.5590000000000004e-06,"exit_reason":"stop_loss","initial_stop_loss_abs":2.3031e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.3031e-05,"stop_loss_ratio":0.1,"min_rate":2.3031e-05,"max_rate":2.559e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516137900000.0,"close_timestamp":1516142700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":13.123359580052494,"open_date":"2018-01-16 21:35:00+00:00","close_date":"2018-01-16 22:25:00+00:00","open_rate":7.62e-05,"close_rate":6.858e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":-0.10448878,"profit_abs":-7.619999999999998e-06,"exit_reason":"stop_loss","initial_stop_loss_abs":6.858e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":6.858e-05,"stop_loss_ratio":0.1,"min_rate":6.858e-05,"max_rate":7.62e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516138500000.0,"close_timestamp":1516141500000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.4350777048780912,"open_date":"2018-01-16 22:30:00+00:00","close_date":"2018-01-16 22:35:00+00:00","open_rate":0.00229844,"close_rate":0.002402129022556391,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":0.00010368902255639091,"exit_reason":"roi","initial_stop_loss_abs":0.0020685960000000002,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0020685960000000002,"stop_loss_ratio":0.1,"min_rate":0.00229844,"max_rate":0.002402129022556391,"is_open":false,"buy_tag":null,"open_timestamp":1516141800000.0,"close_timestamp":1516142100000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06622516556291391,"open_date":"2018-01-16 22:30:00+00:00","close_date":"2018-01-16 22:40:00+00:00","open_rate":0.0151,"close_rate":0.015781203007518795,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":10,"profit_ratio":0.03990025,"profit_abs":0.0006812030075187946,"exit_reason":"roi","initial_stop_loss_abs":0.013590000000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.013590000000000001,"stop_loss_ratio":0.1,"min_rate":0.0151,"max_rate":0.015781203007518795,"is_open":false,"buy_tag":null,"open_timestamp":1516141800000.0,"close_timestamp":1516142400000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.42431134269081283,"open_date":"2018-01-16 22:40:00+00:00","close_date":"2018-01-16 22:45:00+00:00","open_rate":0.00235676,"close_rate":0.00246308,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":0.00010632000000000003,"exit_reason":"roi","initial_stop_loss_abs":0.002121084,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002121084,"stop_loss_ratio":0.1,"min_rate":0.00235676,"max_rate":0.00246308,"is_open":false,"buy_tag":null,"open_timestamp":1516142400000.0,"close_timestamp":1516142700000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.01585559988076589,"open_date":"2018-01-16 22:45:00+00:00","close_date":"2018-01-16 23:05:00+00:00","open_rate":0.0630692,"close_rate":0.06464988170426066,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":0.0015806817042606502,"exit_reason":"roi","initial_stop_loss_abs":0.056762280000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.056762280000000005,"stop_loss_ratio":0.1,"min_rate":0.0630692,"max_rate":0.06464988170426066,"is_open":false,"buy_tag":null,"open_timestamp":1516142700000.0,"close_timestamp":1516143900000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":45.45454545454545,"open_date":"2018-01-16 22:50:00+00:00","close_date":"2018-01-16 22:55:00+00:00","open_rate":2.2e-05,"close_rate":2.299248120300751e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":9.924812030075114e-07,"exit_reason":"roi","initial_stop_loss_abs":1.98e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":1.98e-05,"stop_loss_ratio":0.1,"min_rate":2.2e-05,"max_rate":2.299248120300751e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516143000000.0,"close_timestamp":1516143300000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":20.10454362685967,"open_date":"2018-01-17 03:30:00+00:00","close_date":"2018-01-17 04:00:00+00:00","open_rate":4.974e-05,"close_rate":5.048796992481203e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":7.479699248120277e-07,"exit_reason":"roi","initial_stop_loss_abs":4.4766000000000005e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4766000000000005e-05,"stop_loss_ratio":0.1,"min_rate":4.974e-05,"max_rate":5.048796992481203e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516159800000.0,"close_timestamp":1516161600000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":14.068655036578503,"open_date":"2018-01-17 03:55:00+00:00","close_date":"2018-01-17 04:15:00+00:00","open_rate":7.108e-05,"close_rate":7.28614536340852e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":1.7814536340851996e-06,"exit_reason":"roi","initial_stop_loss_abs":6.3972e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":6.3972e-05,"stop_loss_ratio":0.1,"min_rate":7.108e-05,"max_rate":7.28614536340852e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516161300000.0,"close_timestamp":1516162500000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.0231107002542177,"open_date":"2018-01-17 09:35:00+00:00","close_date":"2018-01-17 10:15:00+00:00","open_rate":0.04327,"close_rate":0.04348689223057644,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0002168922305764362,"exit_reason":"roi","initial_stop_loss_abs":0.038943000000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.038943000000000005,"stop_loss_ratio":0.1,"min_rate":0.04327,"max_rate":0.04348689223057644,"is_open":false,"buy_tag":null,"open_timestamp":1516181700000.0,"close_timestamp":1516184100000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":20.012007204322593,"open_date":"2018-01-17 10:20:00+00:00","close_date":"2018-01-17 17:00:00+00:00","open_rate":4.997e-05,"close_rate":5.022047619047618e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":400,"profit_ratio":-0.0,"profit_abs":2.504761904761831e-07,"exit_reason":"roi","initial_stop_loss_abs":4.4973e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4973e-05,"stop_loss_ratio":0.1,"min_rate":4.997e-05,"max_rate":5.022047619047618e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516184400000.0,"close_timestamp":1516208400000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014626687444363738,"open_date":"2018-01-17 10:30:00+00:00","close_date":"2018-01-17 11:25:00+00:00","open_rate":0.06836818,"close_rate":0.06871087764411027,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":0.00034269764411026804,"exit_reason":"roi","initial_stop_loss_abs":0.061531362,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.061531362,"stop_loss_ratio":0.1,"min_rate":0.06836818,"max_rate":0.06871087764411027,"is_open":false,"buy_tag":null,"open_timestamp":1516185000000.0,"close_timestamp":1516188300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":27.548209366391184,"open_date":"2018-01-17 10:30:00+00:00","close_date":"2018-01-17 11:10:00+00:00","open_rate":3.63e-05,"close_rate":3.648195488721804e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.8195488721804031e-07,"exit_reason":"roi","initial_stop_loss_abs":3.2670000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.2670000000000004e-05,"stop_loss_ratio":0.1,"min_rate":3.63e-05,"max_rate":3.648195488721804e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516185000000.0,"close_timestamp":1516187400000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03558718861209965,"open_date":"2018-01-17 12:30:00+00:00","close_date":"2018-01-17 22:05:00+00:00","open_rate":0.0281,"close_rate":0.02824085213032581,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":575,"profit_ratio":-0.0,"profit_abs":0.0001408521303258095,"exit_reason":"roi","initial_stop_loss_abs":0.02529,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.02529,"stop_loss_ratio":0.1,"min_rate":0.0281,"max_rate":0.02824085213032581,"is_open":false,"buy_tag":null,"open_timestamp":1516192200000.0,"close_timestamp":1516226700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011559355963546878,"open_date":"2018-01-17 12:35:00+00:00","close_date":"2018-01-17 16:55:00+00:00","open_rate":0.08651001,"close_rate":0.08694364413533832,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":260,"profit_ratio":-0.0,"profit_abs":0.00043363413533832607,"exit_reason":"roi","initial_stop_loss_abs":0.077859009,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.077859009,"stop_loss_ratio":0.1,"min_rate":0.08651001,"max_rate":0.08694364413533832,"is_open":false,"buy_tag":null,"open_timestamp":1516192500000.0,"close_timestamp":1516208100000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.752529735487308,"open_date":"2018-01-18 05:00:00+00:00","close_date":"2018-01-18 05:55:00+00:00","open_rate":5.633e-05,"close_rate":5.6612355889724306e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.8235588972430847e-07,"exit_reason":"roi","initial_stop_loss_abs":5.0697e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0697e-05,"stop_loss_ratio":0.1,"min_rate":5.633e-05,"max_rate":5.6612355889724306e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516251600000.0,"close_timestamp":1516254900000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.01430923457900944,"open_date":"2018-01-18 05:20:00+00:00","close_date":"2018-01-18 05:55:00+00:00","open_rate":0.06988494,"close_rate":0.07093584135338346,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0010509013533834544,"exit_reason":"roi","initial_stop_loss_abs":0.06289644600000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06289644600000001,"stop_loss_ratio":0.1,"min_rate":0.06988494,"max_rate":0.07093584135338346,"is_open":false,"buy_tag":null,"open_timestamp":1516252800000.0,"close_timestamp":1516254900000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.034265103697024,"open_date":"2018-01-18 07:35:00+00:00","close_date":"2018-01-18 08:15:00+00:00","open_rate":5.545e-05,"close_rate":5.572794486215538e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.779448621553787e-07,"exit_reason":"roi","initial_stop_loss_abs":4.9905e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.9905e-05,"stop_loss_ratio":0.1,"min_rate":5.545e-05,"max_rate":5.572794486215538e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516260900000.0,"close_timestamp":1516263300000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06121723118136401,"open_date":"2018-01-18 09:00:00+00:00","close_date":"2018-01-18 09:40:00+00:00","open_rate":0.01633527,"close_rate":0.016417151052631574,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":8.188105263157511e-05,"exit_reason":"roi","initial_stop_loss_abs":0.014701743,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014701743,"stop_loss_ratio":0.1,"min_rate":0.01633527,"max_rate":0.016417151052631574,"is_open":false,"buy_tag":null,"open_timestamp":1516266000000.0,"close_timestamp":1516268400000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3707356136045141,"open_date":"2018-01-18 16:40:00+00:00","close_date":"2018-01-18 17:20:00+00:00","open_rate":0.00269734,"close_rate":0.002710860501253133,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.3520501253133123e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002427606,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002427606,"stop_loss_ratio":0.1,"min_rate":0.00269734,"max_rate":0.002710860501253133,"is_open":false,"buy_tag":null,"open_timestamp":1516293600000.0,"close_timestamp":1516296000000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":22.346368715083802,"open_date":"2018-01-18 18:05:00+00:00","close_date":"2018-01-18 18:30:00+00:00","open_rate":4.475e-05,"close_rate":4.587155388471177e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":1.1215538847117757e-06,"exit_reason":"roi","initial_stop_loss_abs":4.0274999999999996e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.0274999999999996e-05,"stop_loss_ratio":0.1,"min_rate":4.475e-05,"max_rate":4.587155388471177e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516298700000.0,"close_timestamp":1516300200000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":35.842293906810035,"open_date":"2018-01-18 18:25:00+00:00","close_date":"2018-01-18 18:55:00+00:00","open_rate":2.79e-05,"close_rate":2.8319548872180444e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.1954887218044365e-07,"exit_reason":"roi","initial_stop_loss_abs":2.5110000000000002e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.5110000000000002e-05,"stop_loss_ratio":0.1,"min_rate":2.79e-05,"max_rate":2.8319548872180444e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516299900000.0,"close_timestamp":1516301700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022525942001105574,"open_date":"2018-01-18 20:10:00+00:00","close_date":"2018-01-18 20:50:00+00:00","open_rate":0.04439326,"close_rate":0.04461578260651629,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.00022252260651629135,"exit_reason":"roi","initial_stop_loss_abs":0.039953933999999997,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.039953933999999997,"stop_loss_ratio":0.1,"min_rate":0.04439326,"max_rate":0.04461578260651629,"is_open":false,"buy_tag":null,"open_timestamp":1516306200000.0,"close_timestamp":1516308600000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":22.271714922048996,"open_date":"2018-01-18 21:30:00+00:00","close_date":"2018-01-19 00:35:00+00:00","open_rate":4.49e-05,"close_rate":4.51250626566416e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":185,"profit_ratio":0.0,"profit_abs":2.2506265664159932e-07,"exit_reason":"roi","initial_stop_loss_abs":4.041e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.041e-05,"stop_loss_ratio":0.1,"min_rate":4.49e-05,"max_rate":4.51250626566416e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516311000000.0,"close_timestamp":1516322100000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03502626970227671,"open_date":"2018-01-18 21:55:00+00:00","close_date":"2018-01-19 05:05:00+00:00","open_rate":0.02855,"close_rate":0.028693107769423555,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":430,"profit_ratio":-0.0,"profit_abs":0.00014310776942355607,"exit_reason":"roi","initial_stop_loss_abs":0.025695,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025695,"stop_loss_ratio":0.1,"min_rate":0.02855,"max_rate":0.028693107769423555,"is_open":false,"buy_tag":null,"open_timestamp":1516312500000.0,"close_timestamp":1516338300000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.25327812284334,"open_date":"2018-01-18 22:10:00+00:00","close_date":"2018-01-18 22:50:00+00:00","open_rate":5.796e-05,"close_rate":5.8250526315789473e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":2.905263157894727e-07,"exit_reason":"roi","initial_stop_loss_abs":5.2164000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.2164000000000004e-05,"stop_loss_ratio":0.1,"min_rate":5.796e-05,"max_rate":5.8250526315789473e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516313400000.0,"close_timestamp":1516315800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02303975994413319,"open_date":"2018-01-18 23:50:00+00:00","close_date":"2018-01-19 00:30:00+00:00","open_rate":0.04340323,"close_rate":0.04362079005012531,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.0002175600501253122,"exit_reason":"roi","initial_stop_loss_abs":0.039062907,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.039062907,"stop_loss_ratio":0.1,"min_rate":0.04340323,"max_rate":0.04362079005012531,"is_open":false,"buy_tag":null,"open_timestamp":1516319400000.0,"close_timestamp":1516321800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02244943545282195,"open_date":"2018-01-19 16:45:00+00:00","close_date":"2018-01-19 17:35:00+00:00","open_rate":0.04454455,"close_rate":0.04476783095238095,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":0.0,"profit_abs":0.0002232809523809512,"exit_reason":"roi","initial_stop_loss_abs":0.040090095000000006,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.040090095000000006,"stop_loss_ratio":0.1,"min_rate":0.04454455,"max_rate":0.04476783095238095,"is_open":false,"buy_tag":null,"open_timestamp":1516380300000.0,"close_timestamp":1516383300000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.793594306049823,"open_date":"2018-01-19 17:15:00+00:00","close_date":"2018-01-19 19:55:00+00:00","open_rate":5.62e-05,"close_rate":5.648170426065162e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":160,"profit_ratio":-0.0,"profit_abs":2.817042606516199e-07,"exit_reason":"roi","initial_stop_loss_abs":5.058e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.058e-05,"stop_loss_ratio":0.1,"min_rate":5.62e-05,"max_rate":5.648170426065162e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516382100000.0,"close_timestamp":1516391700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":23.046784973496194,"open_date":"2018-01-19 17:20:00+00:00","close_date":"2018-01-19 20:15:00+00:00","open_rate":4.339e-05,"close_rate":4.360749373433584e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":175,"profit_ratio":-0.0,"profit_abs":2.174937343358337e-07,"exit_reason":"roi","initial_stop_loss_abs":3.9051e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.9051e-05,"stop_loss_ratio":0.1,"min_rate":4.339e-05,"max_rate":4.360749373433584e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516382400000.0,"close_timestamp":1516392900000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":9.910802775024777,"open_date":"2018-01-20 04:45:00+00:00","close_date":"2018-01-20 17:35:00+00:00","open_rate":0.0001009,"close_rate":0.00010140576441102755,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":770,"profit_ratio":0.0,"profit_abs":5.057644110275549e-07,"exit_reason":"roi","initial_stop_loss_abs":9.081e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":9.081e-05,"stop_loss_ratio":0.1,"min_rate":0.0001009,"max_rate":0.00010140576441102755,"is_open":false,"buy_tag":null,"open_timestamp":1516423500000.0,"close_timestamp":1516469700000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3696789338459548,"open_date":"2018-01-20 04:50:00+00:00","close_date":"2018-01-20 15:15:00+00:00","open_rate":0.00270505,"close_rate":0.002718609147869674,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":625,"profit_ratio":-0.0,"profit_abs":1.3559147869673764e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002434545,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002434545,"stop_loss_ratio":0.1,"min_rate":0.00270505,"max_rate":0.002718609147869674,"is_open":false,"buy_tag":null,"open_timestamp":1516423800000.0,"close_timestamp":1516461300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.033333311111125925,"open_date":"2018-01-20 04:50:00+00:00","close_date":"2018-01-20 07:00:00+00:00","open_rate":0.03000002,"close_rate":0.030150396040100245,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":130,"profit_ratio":-0.0,"profit_abs":0.00015037604010024672,"exit_reason":"roi","initial_stop_loss_abs":0.027000018,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.027000018,"stop_loss_ratio":0.1,"min_rate":0.03000002,"max_rate":0.030150396040100245,"is_open":false,"buy_tag":null,"open_timestamp":1516423800000.0,"close_timestamp":1516431600000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.315018315018317,"open_date":"2018-01-20 09:00:00+00:00","close_date":"2018-01-20 09:40:00+00:00","open_rate":5.46e-05,"close_rate":5.4873684210526304e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.736842105263053e-07,"exit_reason":"roi","initial_stop_loss_abs":4.914e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.914e-05,"stop_loss_ratio":0.1,"min_rate":5.46e-05,"max_rate":5.4873684210526304e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516438800000.0,"close_timestamp":1516441200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03244412634781012,"open_date":"2018-01-20 18:25:00+00:00","close_date":"2018-01-25 03:50:00+00:00","open_rate":0.03082222,"close_rate":0.027739998,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":6325,"profit_ratio":-0.10448878,"profit_abs":-0.0030822220000000025,"exit_reason":"stop_loss","initial_stop_loss_abs":0.027739998000000002,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.027739998000000002,"stop_loss_ratio":0.1,"min_rate":0.027739998,"max_rate":0.03082222,"is_open":false,"buy_tag":null,"open_timestamp":1516472700000.0,"close_timestamp":1516852200000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011148273260677065,"open_date":"2018-01-20 22:25:00+00:00","close_date":"2018-01-20 23:15:00+00:00","open_rate":0.08969999,"close_rate":0.09014961401002504,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":-0.0,"profit_abs":0.00044962401002504593,"exit_reason":"roi","initial_stop_loss_abs":0.080729991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.080729991,"stop_loss_ratio":0.1,"min_rate":0.08969999,"max_rate":0.09014961401002504,"is_open":false,"buy_tag":null,"open_timestamp":1516487100000.0,"close_timestamp":1516490100000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06125570520324337,"open_date":"2018-01-21 02:50:00+00:00","close_date":"2018-01-21 14:30:00+00:00","open_rate":0.01632501,"close_rate":0.01640683962406015,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":700,"profit_ratio":0.0,"profit_abs":8.182962406014932e-05,"exit_reason":"roi","initial_stop_loss_abs":0.014692509000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014692509000000001,"stop_loss_ratio":0.1,"min_rate":0.01632501,"max_rate":0.01640683962406015,"is_open":false,"buy_tag":null,"open_timestamp":1516503000000.0,"close_timestamp":1516545000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.01417675579120474,"open_date":"2018-01-21 10:20:00+00:00","close_date":"2018-01-21 11:00:00+00:00","open_rate":0.070538,"close_rate":0.07089157393483708,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00035357393483707866,"exit_reason":"roi","initial_stop_loss_abs":0.0634842,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0634842,"stop_loss_ratio":0.1,"min_rate":0.070538,"max_rate":0.07089157393483708,"is_open":false,"buy_tag":null,"open_timestamp":1516530000000.0,"close_timestamp":1516532400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.864365214110546,"open_date":"2018-01-21 15:50:00+00:00","close_date":"2018-01-21 18:45:00+00:00","open_rate":5.301e-05,"close_rate":5.327571428571427e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":175,"profit_ratio":-0.0,"profit_abs":2.657142857142672e-07,"exit_reason":"roi","initial_stop_loss_abs":4.7709e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7709e-05,"stop_loss_ratio":0.1,"min_rate":5.301e-05,"max_rate":5.327571428571427e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516549800000.0,"close_timestamp":1516560300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":25.284450063211125,"open_date":"2018-01-21 16:20:00+00:00","close_date":"2018-01-21 17:00:00+00:00","open_rate":3.955e-05,"close_rate":3.9748245614035085e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":1.9824561403508552e-07,"exit_reason":"roi","initial_stop_loss_abs":3.5595e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.5595e-05,"stop_loss_ratio":0.1,"min_rate":3.955e-05,"max_rate":3.9748245614035085e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516551600000.0,"close_timestamp":1516554000000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38683971296493297,"open_date":"2018-01-21 21:15:00+00:00","close_date":"2018-01-21 21:45:00+00:00","open_rate":0.00258505,"close_rate":0.002623922932330827,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":3.8872932330826816e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002326545,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002326545,"stop_loss_ratio":0.1,"min_rate":0.00258505,"max_rate":0.002623922932330827,"is_open":false,"buy_tag":null,"open_timestamp":1516569300000.0,"close_timestamp":1516571100000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":25.621316935690498,"open_date":"2018-01-21 21:15:00+00:00","close_date":"2018-01-21 21:55:00+00:00","open_rate":3.903e-05,"close_rate":3.922563909774435e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.9563909774435151e-07,"exit_reason":"roi","initial_stop_loss_abs":3.5127e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.5127e-05,"stop_loss_ratio":0.1,"min_rate":3.903e-05,"max_rate":3.922563909774435e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516569300000.0,"close_timestamp":1516571700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.098548510313215,"open_date":"2018-01-22 00:35:00+00:00","close_date":"2018-01-22 10:35:00+00:00","open_rate":5.236e-05,"close_rate":5.262245614035087e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":600,"profit_ratio":-0.0,"profit_abs":2.624561403508717e-07,"exit_reason":"roi","initial_stop_loss_abs":4.7124e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7124e-05,"stop_loss_ratio":0.1,"min_rate":5.236e-05,"max_rate":5.262245614035087e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516581300000.0,"close_timestamp":1516617300000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.076650420912717,"open_date":"2018-01-22 01:30:00+00:00","close_date":"2018-01-22 02:10:00+00:00","open_rate":9.028e-05,"close_rate":9.07325313283208e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":4.5253132832080657e-07,"exit_reason":"roi","initial_stop_loss_abs":8.1252e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.1252e-05,"stop_loss_ratio":0.1,"min_rate":9.028e-05,"max_rate":9.07325313283208e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516584600000.0,"close_timestamp":1516587000000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3721622627465575,"open_date":"2018-01-22 12:25:00+00:00","close_date":"2018-01-22 14:35:00+00:00","open_rate":0.002687,"close_rate":0.002700468671679198,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":130,"profit_ratio":-0.0,"profit_abs":1.3468671679197925e-05,"exit_reason":"roi","initial_stop_loss_abs":0.0024183000000000004,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0024183000000000004,"stop_loss_ratio":0.1,"min_rate":0.002687,"max_rate":0.002700468671679198,"is_open":false,"buy_tag":null,"open_timestamp":1516623900000.0,"close_timestamp":1516631700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":23.99232245681382,"open_date":"2018-01-22 13:15:00+00:00","close_date":"2018-01-22 13:55:00+00:00","open_rate":4.168e-05,"close_rate":4.188892230576441e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.0892230576441054e-07,"exit_reason":"roi","initial_stop_loss_abs":3.7512e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.7512e-05,"stop_loss_ratio":0.1,"min_rate":4.168e-05,"max_rate":4.188892230576441e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516626900000.0,"close_timestamp":1516629300000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.336583153837434,"open_date":"2018-01-22 14:00:00+00:00","close_date":"2018-01-22 14:30:00+00:00","open_rate":8.821e-05,"close_rate":8.953646616541353e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":1.326466165413529e-06,"exit_reason":"roi","initial_stop_loss_abs":7.9389e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":7.9389e-05,"stop_loss_ratio":0.1,"min_rate":8.821e-05,"max_rate":8.953646616541353e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516629600000.0,"close_timestamp":1516631400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.334880123743233,"open_date":"2018-01-22 15:55:00+00:00","close_date":"2018-01-22 16:40:00+00:00","open_rate":5.172e-05,"close_rate":5.1979248120300745e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":2.592481203007459e-07,"exit_reason":"roi","initial_stop_loss_abs":4.6548e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6548e-05,"stop_loss_ratio":0.1,"min_rate":5.172e-05,"max_rate":5.1979248120300745e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516636500000.0,"close_timestamp":1516639200000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":33.04692663582287,"open_date":"2018-01-22 16:05:00+00:00","close_date":"2018-01-22 16:25:00+00:00","open_rate":3.026e-05,"close_rate":3.101839598997494e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":7.5839598997494e-07,"exit_reason":"roi","initial_stop_loss_abs":2.7234e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7234e-05,"stop_loss_ratio":0.1,"min_rate":3.026e-05,"max_rate":3.101839598997494e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516637100000.0,"close_timestamp":1516638300000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014156285390713478,"open_date":"2018-01-22 19:50:00+00:00","close_date":"2018-01-23 00:10:00+00:00","open_rate":0.07064,"close_rate":0.07099408521303258,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":260,"profit_ratio":0.0,"profit_abs":0.00035408521303258167,"exit_reason":"roi","initial_stop_loss_abs":0.063576,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.063576,"stop_loss_ratio":0.1,"min_rate":0.07064,"max_rate":0.07099408521303258,"is_open":false,"buy_tag":null,"open_timestamp":1516650600000.0,"close_timestamp":1516666200000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06080938507725528,"open_date":"2018-01-22 21:25:00+00:00","close_date":"2018-01-22 22:05:00+00:00","open_rate":0.01644483,"close_rate":0.01652726022556391,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":8.243022556390922e-05,"exit_reason":"roi","initial_stop_loss_abs":0.014800347,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014800347,"stop_loss_ratio":0.1,"min_rate":0.01644483,"max_rate":0.01652726022556391,"is_open":false,"buy_tag":null,"open_timestamp":1516656300000.0,"close_timestamp":1516658700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":23.08935580697299,"open_date":"2018-01-23 00:05:00+00:00","close_date":"2018-01-23 00:35:00+00:00","open_rate":4.331e-05,"close_rate":4.3961278195488714e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":6.512781954887175e-07,"exit_reason":"roi","initial_stop_loss_abs":3.8979e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.8979e-05,"stop_loss_ratio":0.1,"min_rate":4.331e-05,"max_rate":4.3961278195488714e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516665900000.0,"close_timestamp":1516667700000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":31.250000000000004,"open_date":"2018-01-23 01:50:00+00:00","close_date":"2018-01-23 02:15:00+00:00","open_rate":3.2e-05,"close_rate":3.2802005012531326e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":8.020050125313278e-07,"exit_reason":"roi","initial_stop_loss_abs":2.88e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.88e-05,"stop_loss_ratio":0.1,"min_rate":3.2e-05,"max_rate":3.2802005012531326e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516672200000.0,"close_timestamp":1516673700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010907854156754155,"open_date":"2018-01-23 04:25:00+00:00","close_date":"2018-01-23 05:15:00+00:00","open_rate":0.09167706,"close_rate":0.09213659413533835,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":0.0,"profit_abs":0.0004595341353383492,"exit_reason":"roi","initial_stop_loss_abs":0.08250935400000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08250935400000001,"stop_loss_ratio":0.1,"min_rate":0.09167706,"max_rate":0.09213659413533835,"is_open":false,"buy_tag":null,"open_timestamp":1516681500000.0,"close_timestamp":1516684500000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014440474918339115,"open_date":"2018-01-23 07:35:00+00:00","close_date":"2018-01-23 09:00:00+00:00","open_rate":0.0692498,"close_rate":0.06959691679197995,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":85,"profit_ratio":0.0,"profit_abs":0.0003471167919799484,"exit_reason":"roi","initial_stop_loss_abs":0.06232482,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06232482,"stop_loss_ratio":0.1,"min_rate":0.0692498,"max_rate":0.06959691679197995,"is_open":false,"buy_tag":null,"open_timestamp":1516692900000.0,"close_timestamp":1516698000000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":31.426775612822127,"open_date":"2018-01-23 10:50:00+00:00","close_date":"2018-01-23 13:05:00+00:00","open_rate":3.182e-05,"close_rate":3.197949874686716e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":135,"profit_ratio":0.0,"profit_abs":1.594987468671663e-07,"exit_reason":"roi","initial_stop_loss_abs":2.8638e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.8638e-05,"stop_loss_ratio":0.1,"min_rate":3.182e-05,"max_rate":3.197949874686716e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516704600000.0,"close_timestamp":1516712700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024461839530332683,"open_date":"2018-01-23 11:05:00+00:00","close_date":"2018-01-23 16:05:00+00:00","open_rate":0.04088,"close_rate":0.04108491228070175,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":300,"profit_ratio":-0.0,"profit_abs":0.0002049122807017481,"exit_reason":"roi","initial_stop_loss_abs":0.036792,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036792,"stop_loss_ratio":0.1,"min_rate":0.04088,"max_rate":0.04108491228070175,"is_open":false,"buy_tag":null,"open_timestamp":1516705500000.0,"close_timestamp":1516723500000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.417475728155342,"open_date":"2018-01-23 14:55:00+00:00","close_date":"2018-01-23 15:35:00+00:00","open_rate":5.15e-05,"close_rate":5.175814536340851e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.5814536340851513e-07,"exit_reason":"roi","initial_stop_loss_abs":4.635e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.635e-05,"stop_loss_ratio":0.1,"min_rate":5.15e-05,"max_rate":5.175814536340851e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516719300000.0,"close_timestamp":1516721700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011023294646713328,"open_date":"2018-01-23 16:35:00+00:00","close_date":"2018-01-24 00:05:00+00:00","open_rate":0.09071698,"close_rate":0.09117170170426064,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":450,"profit_ratio":0.0,"profit_abs":0.00045472170426064107,"exit_reason":"roi","initial_stop_loss_abs":0.081645282,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.081645282,"stop_loss_ratio":0.1,"min_rate":0.09071698,"max_rate":0.09117170170426064,"is_open":false,"buy_tag":null,"open_timestamp":1516725300000.0,"close_timestamp":1516752300000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":31.969309462915604,"open_date":"2018-01-23 17:25:00+00:00","close_date":"2018-01-23 18:45:00+00:00","open_rate":3.128e-05,"close_rate":3.1436791979949865e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.0,"profit_abs":1.5679197994986587e-07,"exit_reason":"roi","initial_stop_loss_abs":2.8152e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.8152e-05,"stop_loss_ratio":0.1,"min_rate":3.128e-05,"max_rate":3.1436791979949865e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516728300000.0,"close_timestamp":1516733100000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.465724751439037,"open_date":"2018-01-23 20:15:00+00:00","close_date":"2018-01-23 22:00:00+00:00","open_rate":9.555e-05,"close_rate":9.602894736842104e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":105,"profit_ratio":-0.0,"profit_abs":4.789473684210343e-07,"exit_reason":"roi","initial_stop_loss_abs":8.5995e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.5995e-05,"stop_loss_ratio":0.1,"min_rate":9.555e-05,"max_rate":9.602894736842104e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516738500000.0,"close_timestamp":1516744800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02450979791426522,"open_date":"2018-01-23 22:30:00+00:00","close_date":"2018-01-23 23:10:00+00:00","open_rate":0.04080001,"close_rate":0.0410045213283208,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00020451132832080554,"exit_reason":"roi","initial_stop_loss_abs":0.036720009,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036720009,"stop_loss_ratio":0.1,"min_rate":0.04080001,"max_rate":0.0410045213283208,"is_open":false,"buy_tag":null,"open_timestamp":1516746600000.0,"close_timestamp":1516749000000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.368584156498162,"open_date":"2018-01-23 23:50:00+00:00","close_date":"2018-01-24 03:35:00+00:00","open_rate":5.163e-05,"close_rate":5.18887969924812e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":225,"profit_ratio":-0.0,"profit_abs":2.587969924812037e-07,"exit_reason":"roi","initial_stop_loss_abs":4.6467e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6467e-05,"stop_loss_ratio":0.1,"min_rate":5.163e-05,"max_rate":5.18887969924812e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516751400000.0,"close_timestamp":1516764900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024747691102289384,"open_date":"2018-01-24 00:20:00+00:00","close_date":"2018-01-24 01:50:00+00:00","open_rate":0.04040781,"close_rate":0.04061035541353383,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":90,"profit_ratio":0.0,"profit_abs":0.0002025454135338306,"exit_reason":"roi","initial_stop_loss_abs":0.036367029,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036367029,"stop_loss_ratio":0.1,"min_rate":0.04040781,"max_rate":0.04061035541353383,"is_open":false,"buy_tag":null,"open_timestamp":1516753200000.0,"close_timestamp":1516758600000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.485580670303975,"open_date":"2018-01-24 06:45:00+00:00","close_date":"2018-01-24 07:25:00+00:00","open_rate":5.132e-05,"close_rate":5.157724310776942e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.5724310776941724e-07,"exit_reason":"roi","initial_stop_loss_abs":4.6188000000000006e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6188000000000006e-05,"stop_loss_ratio":0.1,"min_rate":5.132e-05,"max_rate":5.157724310776942e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516776300000.0,"close_timestamp":1516778700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.23816852635629,"open_date":"2018-01-24 14:15:00+00:00","close_date":"2018-01-24 14:25:00+00:00","open_rate":5.198e-05,"close_rate":5.432496240601503e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":10,"profit_ratio":0.03990025,"profit_abs":2.344962406015033e-06,"exit_reason":"roi","initial_stop_loss_abs":4.6782e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6782e-05,"stop_loss_ratio":0.1,"min_rate":5.198e-05,"max_rate":5.432496240601503e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516803300000.0,"close_timestamp":1516803900000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":32.74394237066143,"open_date":"2018-01-24 14:50:00+00:00","close_date":"2018-01-24 16:35:00+00:00","open_rate":3.054e-05,"close_rate":3.069308270676692e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":105,"profit_ratio":-0.0,"profit_abs":1.5308270676691466e-07,"exit_reason":"roi","initial_stop_loss_abs":2.7486000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7486000000000004e-05,"stop_loss_ratio":0.1,"min_rate":3.054e-05,"max_rate":3.069308270676692e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516805400000.0,"close_timestamp":1516811700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.795638562020944,"open_date":"2018-01-24 15:10:00+00:00","close_date":"2018-01-24 16:15:00+00:00","open_rate":9.263e-05,"close_rate":9.309431077694236e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":65,"profit_ratio":0.0,"profit_abs":4.6431077694236234e-07,"exit_reason":"roi","initial_stop_loss_abs":8.3367e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.3367e-05,"stop_loss_ratio":0.1,"min_rate":9.263e-05,"max_rate":9.309431077694236e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516806600000.0,"close_timestamp":1516810500000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.13565469713457,"open_date":"2018-01-24 22:40:00+00:00","close_date":"2018-01-24 23:25:00+00:00","open_rate":5.514e-05,"close_rate":5.54163909774436e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":2.7639097744360576e-07,"exit_reason":"roi","initial_stop_loss_abs":4.9625999999999995e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.9625999999999995e-05,"stop_loss_ratio":0.1,"min_rate":5.514e-05,"max_rate":5.54163909774436e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516833600000.0,"close_timestamp":1516836300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":20.3210729526519,"open_date":"2018-01-25 00:50:00+00:00","close_date":"2018-01-25 01:30:00+00:00","open_rate":4.921e-05,"close_rate":4.9456666666666664e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":2.4666666666666543e-07,"exit_reason":"roi","initial_stop_loss_abs":4.4289e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4289e-05,"stop_loss_ratio":0.1,"min_rate":4.921e-05,"max_rate":4.9456666666666664e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516841400000.0,"close_timestamp":1516843800000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38461538461538464,"open_date":"2018-01-25 08:15:00+00:00","close_date":"2018-01-25 12:15:00+00:00","open_rate":0.0026,"close_rate":0.002613032581453634,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":240,"profit_ratio":0.0,"profit_abs":1.3032581453634e-05,"exit_reason":"roi","initial_stop_loss_abs":0.00234,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.00234,"stop_loss_ratio":0.1,"min_rate":0.0026,"max_rate":0.002613032581453634,"is_open":false,"buy_tag":null,"open_timestamp":1516868100000.0,"close_timestamp":1516882500000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03571593119825878,"open_date":"2018-01-25 10:25:00+00:00","close_date":"2018-01-25 16:15:00+00:00","open_rate":0.02799871,"close_rate":0.028139054411027563,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":350,"profit_ratio":-0.0,"profit_abs":0.00014034441102756326,"exit_reason":"roi","initial_stop_loss_abs":0.025198839,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025198839,"stop_loss_ratio":0.1,"min_rate":0.02799871,"max_rate":0.028139054411027563,"is_open":false,"buy_tag":null,"open_timestamp":1516875900000.0,"close_timestamp":1516896900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024516401717913302,"open_date":"2018-01-25 11:00:00+00:00","close_date":"2018-01-25 11:45:00+00:00","open_rate":0.04078902,"close_rate":0.0409934762406015,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":0.00020445624060149575,"exit_reason":"roi","initial_stop_loss_abs":0.036710118,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036710118,"stop_loss_ratio":0.1,"min_rate":0.04078902,"max_rate":0.0409934762406015,"is_open":false,"buy_tag":null,"open_timestamp":1516878000000.0,"close_timestamp":1516880700000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":34.602076124567475,"open_date":"2018-01-25 13:05:00+00:00","close_date":"2018-01-25 13:45:00+00:00","open_rate":2.89e-05,"close_rate":2.904486215538847e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.4486215538846723e-07,"exit_reason":"roi","initial_stop_loss_abs":2.601e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.601e-05,"stop_loss_ratio":0.1,"min_rate":2.89e-05,"max_rate":2.904486215538847e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516885500000.0,"close_timestamp":1516887900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02432912439481303,"open_date":"2018-01-25 13:20:00+00:00","close_date":"2018-01-25 14:05:00+00:00","open_rate":0.041103,"close_rate":0.04130903007518797,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":0.00020603007518796984,"exit_reason":"roi","initial_stop_loss_abs":0.0369927,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0369927,"stop_loss_ratio":0.1,"min_rate":0.041103,"max_rate":0.04130903007518797,"is_open":false,"buy_tag":null,"open_timestamp":1516886400000.0,"close_timestamp":1516889100000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":18.422991893883566,"open_date":"2018-01-25 15:45:00+00:00","close_date":"2018-01-25 16:15:00+00:00","open_rate":5.428e-05,"close_rate":5.509624060150376e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":8.162406015037611e-07,"exit_reason":"roi","initial_stop_loss_abs":4.8852000000000006e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.8852000000000006e-05,"stop_loss_ratio":0.1,"min_rate":5.428e-05,"max_rate":5.509624060150376e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516895100000.0,"close_timestamp":1516896900000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":18.47063169560399,"open_date":"2018-01-25 17:45:00+00:00","close_date":"2018-01-25 23:15:00+00:00","open_rate":5.414e-05,"close_rate":5.441137844611528e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":330,"profit_ratio":-0.0,"profit_abs":2.713784461152774e-07,"exit_reason":"roi","initial_stop_loss_abs":4.8726e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.8726e-05,"stop_loss_ratio":0.1,"min_rate":5.414e-05,"max_rate":5.441137844611528e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516902300000.0,"close_timestamp":1516922100000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024150056861308878,"open_date":"2018-01-25 21:15:00+00:00","close_date":"2018-01-25 21:55:00+00:00","open_rate":0.04140777,"close_rate":0.0416153277443609,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0002075577443608964,"exit_reason":"roi","initial_stop_loss_abs":0.037266993000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.037266993000000005,"stop_loss_ratio":0.1,"min_rate":0.04140777,"max_rate":0.0416153277443609,"is_open":false,"buy_tag":null,"open_timestamp":1516914900000.0,"close_timestamp":1516917300000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3932224183965176,"open_date":"2018-01-26 02:05:00+00:00","close_date":"2018-01-26 02:45:00+00:00","open_rate":0.00254309,"close_rate":0.002555837318295739,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":1.2747318295739177e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002288781,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002288781,"stop_loss_ratio":0.1,"min_rate":0.00254309,"max_rate":0.002555837318295739,"is_open":false,"buy_tag":null,"open_timestamp":1516932300000.0,"close_timestamp":1516934700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.834849295523455,"open_date":"2018-01-26 02:55:00+00:00","close_date":"2018-01-26 15:10:00+00:00","open_rate":5.607e-05,"close_rate":5.6351052631578935e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":735,"profit_ratio":-0.0,"profit_abs":2.810526315789381e-07,"exit_reason":"roi","initial_stop_loss_abs":5.0463e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0463e-05,"stop_loss_ratio":0.1,"min_rate":5.607e-05,"max_rate":5.6351052631578935e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516935300000.0,"close_timestamp":1516979400000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.39400171784748983,"open_date":"2018-01-26 06:10:00+00:00","close_date":"2018-01-26 09:25:00+00:00","open_rate":0.00253806,"close_rate":0.0025507821052631577,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":195,"profit_ratio":0.0,"profit_abs":1.2722105263157733e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002284254,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002284254,"stop_loss_ratio":0.1,"min_rate":0.00253806,"max_rate":0.0025507821052631577,"is_open":false,"buy_tag":null,"open_timestamp":1516947000000.0,"close_timestamp":1516958700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024096385542168672,"open_date":"2018-01-26 07:25:00+00:00","close_date":"2018-01-26 09:55:00+00:00","open_rate":0.0415,"close_rate":0.04170802005012531,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":150,"profit_ratio":-0.0,"profit_abs":0.00020802005012530989,"exit_reason":"roi","initial_stop_loss_abs":0.03735,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.03735,"stop_loss_ratio":0.1,"min_rate":0.0415,"max_rate":0.04170802005012531,"is_open":false,"buy_tag":null,"open_timestamp":1516951500000.0,"close_timestamp":1516960500000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":18.793459875963165,"open_date":"2018-01-26 09:55:00+00:00","close_date":"2018-01-26 10:25:00+00:00","open_rate":5.321e-05,"close_rate":5.401015037593984e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":8.00150375939842e-07,"exit_reason":"roi","initial_stop_loss_abs":4.7889e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7889e-05,"stop_loss_ratio":0.1,"min_rate":5.321e-05,"max_rate":5.401015037593984e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516960500000.0,"close_timestamp":1516962300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.036074437437185386,"open_date":"2018-01-26 16:05:00+00:00","close_date":"2018-01-26 16:45:00+00:00","open_rate":0.02772046,"close_rate":0.02785940967418546,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00013894967418546025,"exit_reason":"roi","initial_stop_loss_abs":0.024948414,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.024948414,"stop_loss_ratio":0.1,"min_rate":0.02772046,"max_rate":0.02785940967418546,"is_open":false,"buy_tag":null,"open_timestamp":1516982700000.0,"close_timestamp":1516985100000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010569326272036914,"open_date":"2018-01-26 23:35:00+00:00","close_date":"2018-01-27 00:15:00+00:00","open_rate":0.09461341,"close_rate":0.09508766268170424,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.00047425268170424306,"exit_reason":"roi","initial_stop_loss_abs":0.085152069,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.085152069,"stop_loss_ratio":0.1,"min_rate":0.09461341,"max_rate":0.09508766268170424,"is_open":false,"buy_tag":null,"open_timestamp":1517009700000.0,"close_timestamp":1517012100000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":17.809439002671414,"open_date":"2018-01-27 00:35:00+00:00","close_date":"2018-01-27 01:30:00+00:00","open_rate":5.615e-05,"close_rate":5.643145363408521e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.814536340852038e-07,"exit_reason":"roi","initial_stop_loss_abs":5.0535e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0535e-05,"stop_loss_ratio":0.1,"min_rate":5.615e-05,"max_rate":5.643145363408521e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517013300000.0,"close_timestamp":1517016600000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.998560115190784,"open_date":"2018-01-27 00:45:00+00:00","close_date":"2018-01-30 04:45:00+00:00","open_rate":5.556e-05,"close_rate":5.144e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":4560,"profit_ratio":-0.07877175,"profit_abs":-4.120000000000001e-06,"exit_reason":"force_exit","initial_stop_loss_abs":5.0004000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0004000000000004e-05,"stop_loss_ratio":0.1,"min_rate":5.144e-05,"max_rate":5.556e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517013900000.0,"close_timestamp":1517287500000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014492751522789634,"open_date":"2018-01-27 02:30:00+00:00","close_date":"2018-01-27 11:25:00+00:00","open_rate":0.06900001,"close_rate":0.06934587471177944,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":535,"profit_ratio":-0.0,"profit_abs":0.0003458647117794422,"exit_reason":"roi","initial_stop_loss_abs":0.062100009000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.062100009000000005,"stop_loss_ratio":0.1,"min_rate":0.06900001,"max_rate":0.06934587471177944,"is_open":false,"buy_tag":null,"open_timestamp":1517020200000.0,"close_timestamp":1517052300000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010582027378879437,"open_date":"2018-01-27 06:25:00+00:00","close_date":"2018-01-27 07:05:00+00:00","open_rate":0.09449985,"close_rate":0.0949735334586466,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004736834586466093,"exit_reason":"roi","initial_stop_loss_abs":0.085049865,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.085049865,"stop_loss_ratio":0.1,"min_rate":0.09449985,"max_rate":0.0949735334586466,"is_open":false,"buy_tag":null,"open_timestamp":1517034300000.0,"close_timestamp":1517036700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02434885085598385,"open_date":"2018-01-27 09:40:00+00:00","close_date":"2018-01-30 04:40:00+00:00","open_rate":0.0410697,"close_rate":0.03928809,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":4020,"profit_ratio":-0.04815133,"profit_abs":-0.001781610000000003,"exit_reason":"force_exit","initial_stop_loss_abs":0.03696273,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.03696273,"stop_loss_ratio":0.1,"min_rate":0.03928809,"max_rate":0.0410697,"is_open":false,"buy_tag":null,"open_timestamp":1517046000000.0,"close_timestamp":1517287200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03508771929824561,"open_date":"2018-01-27 11:45:00+00:00","close_date":"2018-01-27 12:30:00+00:00","open_rate":0.0285,"close_rate":0.02864285714285714,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":0.00014285714285713902,"exit_reason":"roi","initial_stop_loss_abs":0.025650000000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025650000000000003,"stop_loss_ratio":0.1,"min_rate":0.0285,"max_rate":0.02864285714285714,"is_open":false,"buy_tag":null,"open_timestamp":1517053500000.0,"close_timestamp":1517056200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.034887307020861215,"open_date":"2018-01-27 12:35:00+00:00","close_date":"2018-01-27 15:25:00+00:00","open_rate":0.02866372,"close_rate":0.02880739779448621,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":170,"profit_ratio":-0.0,"profit_abs":0.00014367779448621124,"exit_reason":"roi","initial_stop_loss_abs":0.025797348,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025797348,"stop_loss_ratio":0.1,"min_rate":0.02866372,"max_rate":0.02880739779448621,"is_open":false,"buy_tag":null,"open_timestamp":1517056500000.0,"close_timestamp":1517066700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010484268355332824,"open_date":"2018-01-27 15:50:00+00:00","close_date":"2018-01-27 16:50:00+00:00","open_rate":0.095381,"close_rate":0.09585910025062656,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.0,"profit_abs":0.00047810025062657024,"exit_reason":"roi","initial_stop_loss_abs":0.0858429,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0858429,"stop_loss_ratio":0.1,"min_rate":0.095381,"max_rate":0.09585910025062656,"is_open":false,"buy_tag":null,"open_timestamp":1517068200000.0,"close_timestamp":1517071800000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014794886650455417,"open_date":"2018-01-27 17:05:00+00:00","close_date":"2018-01-27 17:45:00+00:00","open_rate":0.06759092,"close_rate":0.06792972160401002,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00033880160401002224,"exit_reason":"roi","initial_stop_loss_abs":0.060831828,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060831828,"stop_loss_ratio":0.1,"min_rate":0.06759092,"max_rate":0.06792972160401002,"is_open":false,"buy_tag":null,"open_timestamp":1517072700000.0,"close_timestamp":1517075100000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38684569885609726,"open_date":"2018-01-27 23:40:00+00:00","close_date":"2018-01-28 01:05:00+00:00","open_rate":0.00258501,"close_rate":0.002597967443609022,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":85,"profit_ratio":-0.0,"profit_abs":1.2957443609021985e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002326509,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002326509,"stop_loss_ratio":0.1,"min_rate":0.00258501,"max_rate":0.002597967443609022,"is_open":false,"buy_tag":null,"open_timestamp":1517096400000.0,"close_timestamp":1517101500000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014928710926711672,"open_date":"2018-01-28 02:25:00+00:00","close_date":"2018-01-28 08:10:00+00:00","open_rate":0.06698502,"close_rate":0.0673207845112782,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":345,"profit_ratio":-0.0,"profit_abs":0.00033576451127818874,"exit_reason":"roi","initial_stop_loss_abs":0.060286518000000004,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060286518000000004,"stop_loss_ratio":0.1,"min_rate":0.06698502,"max_rate":0.0673207845112782,"is_open":false,"buy_tag":null,"open_timestamp":1517106300000.0,"close_timestamp":1517127000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014767187899175548,"open_date":"2018-01-28 10:25:00+00:00","close_date":"2018-01-28 16:30:00+00:00","open_rate":0.0677177,"close_rate":0.06805713709273183,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":365,"profit_ratio":-0.0,"profit_abs":0.0003394370927318202,"exit_reason":"roi","initial_stop_loss_abs":0.06094593000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06094593000000001,"stop_loss_ratio":0.1,"min_rate":0.0677177,"max_rate":0.06805713709273183,"is_open":false,"buy_tag":null,"open_timestamp":1517135100000.0,"close_timestamp":1517157000000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":19.175455417066157,"open_date":"2018-01-28 20:35:00+00:00","close_date":"2018-01-28 21:35:00+00:00","open_rate":5.215e-05,"close_rate":5.2411403508771925e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":0.0,"profit_abs":2.6140350877192417e-07,"exit_reason":"roi","initial_stop_loss_abs":4.6935000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6935000000000004e-05,"stop_loss_ratio":0.1,"min_rate":5.215e-05,"max_rate":5.2411403508771925e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517171700000.0,"close_timestamp":1517175300000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.36521808998243305,"open_date":"2018-01-28 22:00:00+00:00","close_date":"2018-01-28 22:30:00+00:00","open_rate":0.00273809,"close_rate":0.002779264285714285,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.117428571428529e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002464281,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002464281,"stop_loss_ratio":0.1,"min_rate":0.00273809,"max_rate":0.002779264285714285,"is_open":false,"buy_tag":null,"open_timestamp":1517176800000.0,"close_timestamp":1517178600000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3641236272539253,"open_date":"2018-01-29 00:00:00+00:00","close_date":"2018-01-29 00:30:00+00:00","open_rate":0.00274632,"close_rate":0.002787618045112782,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.129804511278194e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002471688,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002471688,"stop_loss_ratio":0.1,"min_rate":0.00274632,"max_rate":0.002787618045112782,"is_open":false,"buy_tag":null,"open_timestamp":1517184000000.0,"close_timestamp":1517185800000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.061634117689115045,"open_date":"2018-01-29 02:15:00+00:00","close_date":"2018-01-29 03:00:00+00:00","open_rate":0.01622478,"close_rate":0.016306107218045113,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":0.0,"profit_abs":8.132721804511231e-05,"exit_reason":"roi","initial_stop_loss_abs":0.014602302000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014602302000000001,"stop_loss_ratio":0.1,"min_rate":0.01622478,"max_rate":0.016306107218045113,"is_open":false,"buy_tag":null,"open_timestamp":1517192100000.0,"close_timestamp":1517194800000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014492753623188404,"open_date":"2018-01-29 03:05:00+00:00","close_date":"2018-01-29 03:45:00+00:00","open_rate":0.069,"close_rate":0.06934586466165413,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00034586466165412166,"exit_reason":"roi","initial_stop_loss_abs":0.06210000000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06210000000000001,"stop_loss_ratio":0.1,"min_rate":0.069,"max_rate":0.06934586466165413,"is_open":false,"buy_tag":null,"open_timestamp":1517195100000.0,"close_timestamp":1517197500000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.42204454597373,"open_date":"2018-01-29 05:20:00+00:00","close_date":"2018-01-29 06:55:00+00:00","open_rate":8.755e-05,"close_rate":8.798884711779448e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":95,"profit_ratio":-0.0,"profit_abs":4.3884711779447504e-07,"exit_reason":"roi","initial_stop_loss_abs":7.879500000000001e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":7.879500000000001e-05,"stop_loss_ratio":0.1,"min_rate":8.755e-05,"max_rate":8.798884711779448e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517203200000.0,"close_timestamp":1517208900000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014650376815016871,"open_date":"2018-01-29 07:00:00+00:00","close_date":"2018-01-29 19:25:00+00:00","open_rate":0.06825763,"close_rate":0.06859977350877192,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":745,"profit_ratio":-0.0,"profit_abs":0.00034214350877191657,"exit_reason":"roi","initial_stop_loss_abs":0.061431867,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.061431867,"stop_loss_ratio":0.1,"min_rate":0.06825763,"max_rate":0.06859977350877192,"is_open":false,"buy_tag":null,"open_timestamp":1517209200000.0,"close_timestamp":1517253900000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014894490408841846,"open_date":"2018-01-29 19:45:00+00:00","close_date":"2018-01-29 20:25:00+00:00","open_rate":0.06713892,"close_rate":0.06747545593984962,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0003365359398496137,"exit_reason":"roi","initial_stop_loss_abs":0.060425028000000006,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060425028000000006,"stop_loss_ratio":0.1,"min_rate":0.06713892,"max_rate":0.06747545593984962,"is_open":false,"buy_tag":null,"open_timestamp":1517255100000.0,"close_timestamp":1517257500000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.193194537721066,"open_date":"2018-01-29 23:30:00+00:00","close_date":"2018-01-30 04:45:00+00:00","open_rate":8.934e-05,"close_rate":8.8e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":315,"profit_ratio":-0.0199116,"profit_abs":-1.3399999999999973e-06,"exit_reason":"force_exit","initial_stop_loss_abs":8.0406e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.0406e-05,"stop_loss_ratio":0.1,"min_rate":8.8e-05,"max_rate":8.934e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517268600000.0,"close_timestamp":1517287500000.0}],"locks":[],"best_pair":{"key":"LTC/BTC","trades":8,"profit_mean":0.00748129625,"profit_mean_pct":0.748129625,"profit_sum":0.05985037,"profit_sum_pct":5.99,"profit_total_abs":0.0015944746365914707,"profit_total":0.15944746365914708,"profit_total_pct":15.94,"duration_avg":"1:59:00","wins":8,"draws":0,"losses":0},"worst_pair":{"key":"XMR/BTC","trades":16,"profit_mean":-0.0027899012500000007,"profit_mean_pct":-0.2789901250000001,"profit_sum":-0.04463842000000001,"profit_sum_pct":-4.46,"profit_total_abs":0.0006671885263157366,"profit_total":0.06671885263157366,"profit_total_pct":6.67,"duration_avg":"8:41:00","wins":15,"draws":0,"losses":1},"results_per_pair":[{"key":"ETH/BTC","trades":21,"profit_mean":0.0009500057142857142,"profit_mean_pct":0.09500057142857142,"profit_sum":0.01995012,"profit_sum_pct":2.0,"profit_total_abs":0.011505731278195264,"profit_total":1.1505731278195264,"profit_total_pct":115.06,"duration_avg":"2:17:00","wins":21,"draws":0,"losses":0},{"key":"DASH/BTC","trades":16,"profit_mean":0.0018703237499999997,"profit_mean_pct":0.18703237499999997,"profit_sum":0.029925179999999996,"profit_sum_pct":2.99,"profit_total_abs":0.007475052681704161,"profit_total":0.7475052681704161,"profit_total_pct":74.75,"duration_avg":"3:03:00","wins":16,"draws":0,"losses":0},{"key":"ZEC/BTC","trades":21,"profit_mean":-0.00039290904761904774,"profit_mean_pct":-0.03929090476190478,"profit_sum":-0.008251090000000003,"profit_sum_pct":-0.83,"profit_total_abs":0.004452605639097655,"profit_total":0.4452605639097655,"profit_total_pct":44.53,"duration_avg":"4:17:00","wins":20,"draws":0,"losses":1},{"key":"LTC/BTC","trades":8,"profit_mean":0.00748129625,"profit_mean_pct":0.748129625,"profit_sum":0.05985037,"profit_sum_pct":5.99,"profit_total_abs":0.0015944746365914707,"profit_total":0.15944746365914708,"profit_total_pct":15.94,"duration_avg":"1:59:00","wins":8,"draws":0,"losses":0},{"key":"XMR/BTC","trades":16,"profit_mean":-0.0027899012500000007,"profit_mean_pct":-0.2789901250000001,"profit_sum":-0.04463842000000001,"profit_sum_pct":-4.46,"profit_total_abs":0.0006671885263157366,"profit_total":0.06671885263157366,"profit_total_pct":6.67,"duration_avg":"8:41:00","wins":15,"draws":0,"losses":1},{"key":"ETC/BTC","trades":20,"profit_mean":0.0022568569999999997,"profit_mean_pct":0.22568569999999996,"profit_sum":0.04513713999999999,"profit_sum_pct":4.51,"profit_total_abs":0.00036538235338345404,"profit_total":0.0365382353383454,"profit_total_pct":3.65,"duration_avg":"1:45:00","wins":19,"draws":0,"losses":1},{"key":"TRX/BTC","trades":15,"profit_mean":0.0023467073333333323,"profit_mean_pct":0.23467073333333321,"profit_sum":0.035200609999999986,"profit_sum_pct":3.52,"profit_total_abs":1.1329523809523682e-05,"profit_total":0.0011329523809523682,"profit_total_pct":0.11,"duration_avg":"2:28:00","wins":13,"draws":0,"losses":2},{"key":"XLM/BTC","trades":21,"profit_mean":0.0026243899999999994,"profit_mean_pct":0.2624389999999999,"profit_sum":0.05511218999999999,"profit_sum_pct":5.51,"profit_total_abs":7.340779448621465e-06,"profit_total":0.0007340779448621465,"profit_total_pct":0.07,"duration_avg":"3:21:00","wins":20,"draws":0,"losses":1},{"key":"ADA/BTC","trades":29,"profit_mean":-0.0011598141379310352,"profit_mean_pct":-0.11598141379310352,"profit_sum":-0.03363461000000002,"profit_sum_pct":-3.36,"profit_total_abs":4.916634085212862e-06,"profit_total":0.0004916634085212862,"profit_total_pct":0.05,"duration_avg":"5:35:00","wins":27,"draws":0,"losses":2},{"key":"NXT/BTC","trades":12,"profit_mean":-0.0012261025000000006,"profit_mean_pct":-0.12261025000000006,"profit_sum":-0.014713230000000008,"profit_sum_pct":-1.47,"profit_total_abs":1.4774411027568458e-06,"profit_total":0.00014774411027568458,"profit_total_pct":0.01,"duration_avg":"0:57:00","wins":11,"draws":0,"losses":1},{"key":"TOTAL","trades":179,"profit_mean":0.0008041243575418989,"profit_mean_pct":0.0804124357541899,"profit_sum":0.1439382599999999,"profit_sum_pct":14.39,"profit_total_abs":0.026085499493733857,"profit_total":2.6085499493733857,"profit_total_pct":260.85,"duration_avg":"3:40:00","wins":170,"draws":0,"losses":9}],"results_per_enter_tag":[{"key":"TOTAL","trades":179,"profit_mean":0.0008041243575418989,"profit_mean_pct":0.0804124357541899,"profit_sum":0.1439382599999999,"profit_sum_pct":14.39,"profit_total_abs":0.026085499493733857,"profit_total":2.6085499493733857,"profit_total_pct":260.85,"duration_avg":"3:40:00","wins":170,"draws":0,"losses":9}],"exit_reason_summary":[{"exit_reason":"roi","trades":170,"wins":170,"draws":0,"losses":0,"profit_mean":0.005398268352941177,"profit_mean_pct":0.54,"profit_sum":0.91770562,"profit_sum_pct":91.77,"profit_total_abs":0.031232837493733862,"profit_total":0.30590187333333335,"profit_total_pct":30.59},{"exit_reason":"stop_loss","trades":6,"wins":0,"draws":0,"losses":6,"profit_mean":-0.10448878000000002,"profit_mean_pct":-10.45,"profit_sum":-0.6269326800000001,"profit_sum_pct":-62.69,"profit_total_abs":-0.0033602680000000026,"profit_total":-0.20897756000000003,"profit_total_pct":-20.9},{"exit_reason":"force_exit","trades":3,"wins":0,"draws":0,"losses":3,"profit_mean":-0.04894489333333333,"profit_mean_pct":-4.89,"profit_sum":-0.14683468,"profit_sum_pct":-14.68,"profit_total_abs":-0.001787070000000003,"profit_total":-0.04894489333333333,"profit_total_pct":-4.89}],"left_open_trades":[{"key":"TOTAL","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0}],"total_trades":179,"total_volume":0.17900000000000005,"avg_stake_amount":0.0010000000000000002,"profit_mean":0.0008041243575418989,"profit_median":0.0,"profit_total":2.6085499493733857,"profit_total_abs":0.026085499493733857,"backtest_start":"2018-01-10 07:15:00","backtest_start_ts":1515568500000,"backtest_end":"2018-01-30 04:45:00","backtest_end_ts":1517287500000,"backtest_days":19,"backtest_run_start_ts":"2020-10-01 18:00:00+00:00","backtest_run_end_ts":"2020-10-01 18:01:00+00:00","trades_per_day":9.42,"market_change":1.22,"pairlist":[],"stake_amount":0.001,"stake_currency":"BTC","stake_currency_decimals":8,"starting_balance":0.01,"dry_run_wallet":0.01,"final_balance":0.03608549949373386,"rejected_signals":0,"max_open_trades":3,"max_open_trades_setting":3,"timeframe":"5m","timeframe_detail":"","timerange":"","enable_protections":false,"strategy_name":"StrategyTestV2","stoploss":0.1,"trailing_stop":false,"trailing_stop_positive":null,"trailing_stop_positive_offset":0.0,"trailing_only_offset_is_reached":false,"use_custom_stoploss":false,"minimal_roi":{},"use_exit_signal":true,"exit_profit_only":false,"exit_profit_offset":false,"ignore_roi_if_entry_signal":false,"backtest_best_day":0.17955111999999998,"backtest_worst_day":-0.14683468,"backtest_best_day_abs":0.0071570099,"backtest_worst_day_abs":-0.0023093218,"winning_days":19,"draw_days":0,"losing_days":2,"daily_profit":[["2018-01-10",0.0025815306],["2018-01-11",0.0049356655],["2018-01-12",0.0006395218],["2018-01-13",0.0002574589],["2018-01-14",0.0010443828],["2018-01-15",0.0024030209],["2018-01-16",0.0071570099],["2018-01-17",0.001137038],["2018-01-18",0.0013712174],["2018-01-19",0.000584673],["2018-01-20",0.0006143386],["2018-01-21",0.0004749361],["2018-01-22",9.91669e-05],["2018-01-23",0.0015726664],["2018-01-24",0.0006610219],["2018-01-25",-0.0023093218],["2018-01-26",0.0003735204],["2018-01-27",0.0023975191],["2018-01-28",0.0007295947],["2018-01-29",0.0011476082],["2018-01-30",-0.00178707]],"wins":48,"losses":9,"draws":122,"holding_avg":"3:40:00","holding_avg_s":13200.0,"winner_holding_avg":"0:24:00","winner_holding_avg_s":1440.0,"loser_holding_avg":"1 day, 5:57:00","loser_holding_avg_s":107820.0,"max_drawdown":0.21142322000000008,"max_drawdown_account":0.08674033488183289,"max_drawdown_abs":0.0030822220000000025,"drawdown_start":"2018-01-25 01:30:00","drawdown_start_ts":1516843800000.0,"drawdown_end":"2018-01-25 03:50:00","drawdown_end_ts":1516852200000.0,"max_drawdown_low":0.02245167355388436,"max_drawdown_high":0.025533895553884363,"csum_min":0.01000434887218045,"csum_max":0.03608683949373386},"TestStrategy":{"trades":[{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.37344398340249,"open_date":"2018-01-10 07:15:00+00:00","close_date":"2018-01-10 07:20:00+00:00","open_rate":9.64e-05,"close_rate":0.00010074887218045112,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":4.348872180451118e-06,"exit_reason":"roi","initial_stop_loss_abs":8.676e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.676e-05,"stop_loss_ratio":0.1,"min_rate":9.64e-05,"max_rate":0.00010074887218045112,"is_open":false,"buy_tag":null,"open_timestamp":1515568500000.0,"close_timestamp":1515568800000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":21.026072329688816,"open_date":"2018-01-10 07:15:00+00:00","close_date":"2018-01-10 07:30:00+00:00","open_rate":4.756e-05,"close_rate":4.9705563909774425e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":15,"profit_ratio":0.03990025,"profit_abs":2.1455639097744267e-06,"exit_reason":"roi","initial_stop_loss_abs":4.2804e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.2804e-05,"stop_loss_ratio":0.1,"min_rate":4.756e-05,"max_rate":4.9705563909774425e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515568500000.0,"close_timestamp":1515569400000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":29.94908655286014,"open_date":"2018-01-10 07:25:00+00:00","close_date":"2018-01-10 07:35:00+00:00","open_rate":3.339e-05,"close_rate":3.489631578947368e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":10,"profit_ratio":0.03990025,"profit_abs":1.506315789473681e-06,"exit_reason":"roi","initial_stop_loss_abs":3.0050999999999997e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.0050999999999997e-05,"stop_loss_ratio":0.1,"min_rate":3.339e-05,"max_rate":3.489631578947368e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515569100000.0,"close_timestamp":1515569700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.313531353135314,"open_date":"2018-01-10 07:25:00+00:00","close_date":"2018-01-10 07:40:00+00:00","open_rate":9.696e-05,"close_rate":0.00010133413533834584,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":15,"profit_ratio":0.03990025,"profit_abs":4.3741353383458455e-06,"exit_reason":"roi","initial_stop_loss_abs":8.7264e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.7264e-05,"stop_loss_ratio":0.1,"min_rate":9.696e-05,"max_rate":0.00010133413533834584,"is_open":false,"buy_tag":null,"open_timestamp":1515569100000.0,"close_timestamp":1515570000000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010604453870625663,"open_date":"2018-01-10 07:35:00+00:00","close_date":"2018-01-10 08:35:00+00:00","open_rate":0.0943,"close_rate":0.09477268170426063,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.0,"profit_abs":0.0004726817042606385,"exit_reason":"roi","initial_stop_loss_abs":0.08487,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08487,"stop_loss_ratio":0.1,"min_rate":0.0943,"max_rate":0.09477268170426063,"is_open":false,"buy_tag":null,"open_timestamp":1515569700000.0,"close_timestamp":1515573300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03677001860930642,"open_date":"2018-01-10 07:40:00+00:00","close_date":"2018-01-10 08:10:00+00:00","open_rate":0.02719607,"close_rate":0.02760503345864661,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.00040896345864661204,"exit_reason":"roi","initial_stop_loss_abs":0.024476463,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.024476463,"stop_loss_ratio":0.1,"min_rate":0.02719607,"max_rate":0.02760503345864661,"is_open":false,"buy_tag":null,"open_timestamp":1515570000000.0,"close_timestamp":1515571800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.021575196463739,"open_date":"2018-01-10 08:15:00+00:00","close_date":"2018-01-10 09:55:00+00:00","open_rate":0.04634952,"close_rate":0.046581848421052625,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":100,"profit_ratio":0.0,"profit_abs":0.0002323284210526272,"exit_reason":"roi","initial_stop_loss_abs":0.041714568,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.041714568,"stop_loss_ratio":0.1,"min_rate":0.04634952,"max_rate":0.046581848421052625,"is_open":false,"buy_tag":null,"open_timestamp":1515572100000.0,"close_timestamp":1515578100000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":32.615786040443574,"open_date":"2018-01-10 14:45:00+00:00","close_date":"2018-01-10 15:50:00+00:00","open_rate":3.066e-05,"close_rate":3.081368421052631e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":65,"profit_ratio":-0.0,"profit_abs":1.5368421052630647e-07,"exit_reason":"roi","initial_stop_loss_abs":2.7594e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7594e-05,"stop_loss_ratio":0.1,"min_rate":3.066e-05,"max_rate":3.081368421052631e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515595500000.0,"close_timestamp":1515599400000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.05917194776300452,"open_date":"2018-01-10 16:35:00+00:00","close_date":"2018-01-10 17:15:00+00:00","open_rate":0.0168999,"close_rate":0.016984611278195488,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":8.471127819548868e-05,"exit_reason":"roi","initial_stop_loss_abs":0.01520991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.01520991,"stop_loss_ratio":0.1,"min_rate":0.0168999,"max_rate":0.016984611278195488,"is_open":false,"buy_tag":null,"open_timestamp":1515602100000.0,"close_timestamp":1515604500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010949822656672253,"open_date":"2018-01-10 16:40:00+00:00","close_date":"2018-01-10 17:20:00+00:00","open_rate":0.09132568,"close_rate":0.0917834528320802,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004577728320801916,"exit_reason":"roi","initial_stop_loss_abs":0.08219311200000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08219311200000001,"stop_loss_ratio":0.1,"min_rate":0.09132568,"max_rate":0.0917834528320802,"is_open":false,"buy_tag":null,"open_timestamp":1515602400000.0,"close_timestamp":1515604800000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011238476768326556,"open_date":"2018-01-10 18:50:00+00:00","close_date":"2018-01-10 19:45:00+00:00","open_rate":0.08898003,"close_rate":0.08942604518796991,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":0.00044601518796991146,"exit_reason":"roi","initial_stop_loss_abs":0.080082027,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.080082027,"stop_loss_ratio":0.1,"min_rate":0.08898003,"max_rate":0.08942604518796991,"is_open":false,"buy_tag":null,"open_timestamp":1515610200000.0,"close_timestamp":1515613500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011682232072680307,"open_date":"2018-01-10 22:15:00+00:00","close_date":"2018-01-10 23:00:00+00:00","open_rate":0.08560008,"close_rate":0.08602915308270676,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":0.0,"profit_abs":0.00042907308270676014,"exit_reason":"roi","initial_stop_loss_abs":0.077040072,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.077040072,"stop_loss_ratio":0.1,"min_rate":0.08560008,"max_rate":0.08602915308270676,"is_open":false,"buy_tag":null,"open_timestamp":1515622500000.0,"close_timestamp":1515625200000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.4014726015023105,"open_date":"2018-01-10 22:50:00+00:00","close_date":"2018-01-10 23:20:00+00:00","open_rate":0.00249083,"close_rate":0.0025282860902255634,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":3.745609022556351e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002241747,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002241747,"stop_loss_ratio":0.1,"min_rate":0.00249083,"max_rate":0.0025282860902255634,"is_open":false,"buy_tag":null,"open_timestamp":1515624600000.0,"close_timestamp":1515626400000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":33.090668431502316,"open_date":"2018-01-10 23:15:00+00:00","close_date":"2018-01-11 00:15:00+00:00","open_rate":3.022e-05,"close_rate":3.037147869674185e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.0,"profit_abs":1.5147869674185174e-07,"exit_reason":"roi","initial_stop_loss_abs":2.7198e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7198e-05,"stop_loss_ratio":0.1,"min_rate":3.022e-05,"max_rate":3.037147869674185e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515626100000.0,"close_timestamp":1515629700000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.41034058268362744,"open_date":"2018-01-10 23:40:00+00:00","close_date":"2018-01-11 00:05:00+00:00","open_rate":0.002437,"close_rate":0.0024980776942355883,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":6.107769423558838e-05,"exit_reason":"roi","initial_stop_loss_abs":0.0021933,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0021933,"stop_loss_ratio":0.1,"min_rate":0.002437,"max_rate":0.0024980776942355883,"is_open":false,"buy_tag":null,"open_timestamp":1515627600000.0,"close_timestamp":1515629100000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02095643931654345,"open_date":"2018-01-11 00:00:00+00:00","close_date":"2018-01-11 00:35:00+00:00","open_rate":0.04771803,"close_rate":0.04843559436090225,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0007175643609022495,"exit_reason":"roi","initial_stop_loss_abs":0.042946227000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.042946227000000003,"stop_loss_ratio":0.1,"min_rate":0.04771803,"max_rate":0.04843559436090225,"is_open":false,"buy_tag":null,"open_timestamp":1515628800000.0,"close_timestamp":1515630900000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":27.389756231169542,"open_date":"2018-01-11 03:40:00+00:00","close_date":"2018-01-11 04:25:00+00:00","open_rate":3.651e-05,"close_rate":3.2859000000000005e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.10448878,"profit_abs":-3.650999999999996e-06,"exit_reason":"stop_loss","initial_stop_loss_abs":3.2859000000000005e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.2859000000000005e-05,"stop_loss_ratio":0.1,"min_rate":3.2859000000000005e-05,"max_rate":3.651e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515642000000.0,"close_timestamp":1515644700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011332594070446804,"open_date":"2018-01-11 03:55:00+00:00","close_date":"2018-01-11 04:25:00+00:00","open_rate":0.08824105,"close_rate":0.08956798308270676,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.0013269330827067605,"exit_reason":"roi","initial_stop_loss_abs":0.079416945,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.079416945,"stop_loss_ratio":0.1,"min_rate":0.08824105,"max_rate":0.08956798308270676,"is_open":false,"buy_tag":null,"open_timestamp":1515642900000.0,"close_timestamp":1515644700000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.411522633744856,"open_date":"2018-01-11 04:00:00+00:00","close_date":"2018-01-11 04:50:00+00:00","open_rate":0.00243,"close_rate":0.002442180451127819,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":-0.0,"profit_abs":1.2180451127819219e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002187,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002187,"stop_loss_ratio":0.1,"min_rate":0.00243,"max_rate":0.002442180451127819,"is_open":false,"buy_tag":null,"open_timestamp":1515643200000.0,"close_timestamp":1515646200000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022001890402423376,"open_date":"2018-01-11 04:30:00+00:00","close_date":"2018-01-11 04:55:00+00:00","open_rate":0.04545064,"close_rate":0.046589753784461146,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":0.001139113784461146,"exit_reason":"roi","initial_stop_loss_abs":0.040905576,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.040905576,"stop_loss_ratio":0.1,"min_rate":0.04545064,"max_rate":0.046589753784461146,"is_open":false,"buy_tag":null,"open_timestamp":1515645000000.0,"close_timestamp":1515646500000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":29.655990510083036,"open_date":"2018-01-11 04:30:00+00:00","close_date":"2018-01-11 04:50:00+00:00","open_rate":3.372e-05,"close_rate":3.456511278195488e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":8.4511278195488e-07,"exit_reason":"roi","initial_stop_loss_abs":3.0348e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.0348e-05,"stop_loss_ratio":0.1,"min_rate":3.372e-05,"max_rate":3.456511278195488e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515645000000.0,"close_timestamp":1515646200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.037821482602118005,"open_date":"2018-01-11 04:55:00+00:00","close_date":"2018-01-11 05:15:00+00:00","open_rate":0.02644,"close_rate":0.02710265664160401,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":0.0006626566416040071,"exit_reason":"roi","initial_stop_loss_abs":0.023796,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.023796,"stop_loss_ratio":0.1,"min_rate":0.02644,"max_rate":0.02710265664160401,"is_open":false,"buy_tag":null,"open_timestamp":1515646500000.0,"close_timestamp":1515647700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011348161597821153,"open_date":"2018-01-11 11:20:00+00:00","close_date":"2018-01-11 12:00:00+00:00","open_rate":0.08812,"close_rate":0.08856170426065162,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004417042606516125,"exit_reason":"roi","initial_stop_loss_abs":0.079308,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.079308,"stop_loss_ratio":0.1,"min_rate":0.08812,"max_rate":0.08856170426065162,"is_open":false,"buy_tag":null,"open_timestamp":1515669600000.0,"close_timestamp":1515672000000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.037263696923919086,"open_date":"2018-01-11 11:35:00+00:00","close_date":"2018-01-11 12:15:00+00:00","open_rate":0.02683577,"close_rate":0.026970285137844607,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00013451513784460897,"exit_reason":"roi","initial_stop_loss_abs":0.024152193,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.024152193,"stop_loss_ratio":0.1,"min_rate":0.02683577,"max_rate":0.026970285137844607,"is_open":false,"buy_tag":null,"open_timestamp":1515670500000.0,"close_timestamp":1515672900000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":20.329335230737954,"open_date":"2018-01-11 14:00:00+00:00","close_date":"2018-01-11 14:25:00+00:00","open_rate":4.919e-05,"close_rate":5.04228320802005e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":1.232832080200495e-06,"exit_reason":"roi","initial_stop_loss_abs":4.4271000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4271000000000004e-05,"stop_loss_ratio":0.1,"min_rate":4.919e-05,"max_rate":5.04228320802005e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515679200000.0,"close_timestamp":1515680700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.01138317402960718,"open_date":"2018-01-11 19:25:00+00:00","close_date":"2018-01-11 20:35:00+00:00","open_rate":0.08784896,"close_rate":0.08828930566416039,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":70,"profit_ratio":-0.0,"profit_abs":0.0004403456641603881,"exit_reason":"roi","initial_stop_loss_abs":0.079064064,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.079064064,"stop_loss_ratio":0.1,"min_rate":0.08784896,"max_rate":0.08828930566416039,"is_open":false,"buy_tag":null,"open_timestamp":1515698700000.0,"close_timestamp":1515702900000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.58863858961802,"open_date":"2018-01-11 22:35:00+00:00","close_date":"2018-01-11 23:30:00+00:00","open_rate":5.105e-05,"close_rate":5.130588972431077e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.558897243107704e-07,"exit_reason":"roi","initial_stop_loss_abs":4.5945e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.5945e-05,"stop_loss_ratio":0.1,"min_rate":5.105e-05,"max_rate":5.130588972431077e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515710100000.0,"close_timestamp":1515713400000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":25.252525252525253,"open_date":"2018-01-11 22:55:00+00:00","close_date":"2018-01-11 23:25:00+00:00","open_rate":3.96e-05,"close_rate":4.019548872180451e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":5.954887218045116e-07,"exit_reason":"roi","initial_stop_loss_abs":3.5640000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.5640000000000004e-05,"stop_loss_ratio":0.1,"min_rate":3.96e-05,"max_rate":4.019548872180451e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515711300000.0,"close_timestamp":1515713100000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":34.66204506065858,"open_date":"2018-01-11 22:55:00+00:00","close_date":"2018-01-11 23:35:00+00:00","open_rate":2.885e-05,"close_rate":2.899461152882205e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.4461152882205115e-07,"exit_reason":"roi","initial_stop_loss_abs":2.5965e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.5965e-05,"stop_loss_ratio":0.1,"min_rate":2.885e-05,"max_rate":2.899461152882205e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515711300000.0,"close_timestamp":1515713700000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03780718336483932,"open_date":"2018-01-11 23:30:00+00:00","close_date":"2018-01-12 00:05:00+00:00","open_rate":0.02645,"close_rate":0.026847744360902256,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0003977443609022545,"exit_reason":"roi","initial_stop_loss_abs":0.023805000000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.023805000000000003,"stop_loss_ratio":0.1,"min_rate":0.02645,"max_rate":0.026847744360902256,"is_open":false,"buy_tag":null,"open_timestamp":1515713400000.0,"close_timestamp":1515715500000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.020833333333333332,"open_date":"2018-01-11 23:55:00+00:00","close_date":"2018-01-12 01:15:00+00:00","open_rate":0.048,"close_rate":0.04824060150375939,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.0,"profit_abs":0.00024060150375938838,"exit_reason":"roi","initial_stop_loss_abs":0.0432,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0432,"stop_loss_ratio":0.1,"min_rate":0.048,"max_rate":0.04824060150375939,"is_open":false,"buy_tag":null,"open_timestamp":1515714900000.0,"close_timestamp":1515719700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":21.31287297527707,"open_date":"2018-01-12 21:15:00+00:00","close_date":"2018-01-12 21:40:00+00:00","open_rate":4.692e-05,"close_rate":4.809593984962405e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":1.1759398496240516e-06,"exit_reason":"roi","initial_stop_loss_abs":4.2227999999999996e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.2227999999999996e-05,"stop_loss_ratio":0.1,"min_rate":4.692e-05,"max_rate":4.809593984962405e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515791700000.0,"close_timestamp":1515793200000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38915654211062944,"open_date":"2018-01-13 00:55:00+00:00","close_date":"2018-01-13 06:20:00+00:00","open_rate":0.00256966,"close_rate":0.0025825405012531327,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":325,"profit_ratio":-0.0,"profit_abs":1.2880501253132587e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002312694,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002312694,"stop_loss_ratio":0.1,"min_rate":0.00256966,"max_rate":0.0025825405012531327,"is_open":false,"buy_tag":null,"open_timestamp":1515804900000.0,"close_timestamp":1515824400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":15.96933886937081,"open_date":"2018-01-13 10:55:00+00:00","close_date":"2018-01-13 11:35:00+00:00","open_rate":6.262e-05,"close_rate":6.293388471177944e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":3.138847117794446e-07,"exit_reason":"roi","initial_stop_loss_abs":5.6358e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.6358e-05,"stop_loss_ratio":0.1,"min_rate":6.262e-05,"max_rate":6.293388471177944e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515840900000.0,"close_timestamp":1515843300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":21.141649048625794,"open_date":"2018-01-13 13:05:00+00:00","close_date":"2018-01-15 14:10:00+00:00","open_rate":4.73e-05,"close_rate":4.753709273182957e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":2945,"profit_ratio":0.0,"profit_abs":2.3709273182957117e-07,"exit_reason":"roi","initial_stop_loss_abs":4.257e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.257e-05,"stop_loss_ratio":0.1,"min_rate":4.73e-05,"max_rate":4.753709273182957e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515848700000.0,"close_timestamp":1516025400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":16.49348507339601,"open_date":"2018-01-13 13:30:00+00:00","close_date":"2018-01-13 14:45:00+00:00","open_rate":6.063e-05,"close_rate":6.0933909774436085e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":75,"profit_ratio":-0.0,"profit_abs":3.039097744360846e-07,"exit_reason":"roi","initial_stop_loss_abs":5.4567e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.4567e-05,"stop_loss_ratio":0.1,"min_rate":6.063e-05,"max_rate":6.0933909774436085e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515850200000.0,"close_timestamp":1515854700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":9.023641941887746,"open_date":"2018-01-13 13:40:00+00:00","close_date":"2018-01-13 23:30:00+00:00","open_rate":0.00011082,"close_rate":0.00011137548872180448,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":590,"profit_ratio":-0.0,"profit_abs":5.554887218044781e-07,"exit_reason":"roi","initial_stop_loss_abs":9.9738e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":9.9738e-05,"stop_loss_ratio":0.1,"min_rate":0.00011082,"max_rate":0.00011137548872180448,"is_open":false,"buy_tag":null,"open_timestamp":1515850800000.0,"close_timestamp":1515886200000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":16.863406408094438,"open_date":"2018-01-13 15:15:00+00:00","close_date":"2018-01-13 15:55:00+00:00","open_rate":5.93e-05,"close_rate":5.9597243107769415e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.9724310776941686e-07,"exit_reason":"roi","initial_stop_loss_abs":5.337e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.337e-05,"stop_loss_ratio":0.1,"min_rate":5.93e-05,"max_rate":5.9597243107769415e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515856500000.0,"close_timestamp":1515858900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.020618543947292404,"open_date":"2018-01-13 16:30:00+00:00","close_date":"2018-01-13 17:10:00+00:00","open_rate":0.04850003,"close_rate":0.04874313791979949,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00024310791979949287,"exit_reason":"roi","initial_stop_loss_abs":0.043650027,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.043650027,"stop_loss_ratio":0.1,"min_rate":0.04850003,"max_rate":0.04874313791979949,"is_open":false,"buy_tag":null,"open_timestamp":1515861000000.0,"close_timestamp":1515863400000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010178097365511457,"open_date":"2018-01-13 22:05:00+00:00","close_date":"2018-01-14 06:25:00+00:00","open_rate":0.09825019,"close_rate":0.09874267215538848,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":500,"profit_ratio":-0.0,"profit_abs":0.0004924821553884823,"exit_reason":"roi","initial_stop_loss_abs":0.088425171,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.088425171,"stop_loss_ratio":0.1,"min_rate":0.09825019,"max_rate":0.09874267215538848,"is_open":false,"buy_tag":null,"open_timestamp":1515881100000.0,"close_timestamp":1515911100000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":16.616816218012627,"open_date":"2018-01-14 00:20:00+00:00","close_date":"2018-01-14 22:55:00+00:00","open_rate":6.018e-05,"close_rate":6.048165413533834e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":1355,"profit_ratio":0.0,"profit_abs":3.0165413533833987e-07,"exit_reason":"roi","initial_stop_loss_abs":5.4162e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.4162e-05,"stop_loss_ratio":0.1,"min_rate":6.018e-05,"max_rate":6.048165413533834e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515889200000.0,"close_timestamp":1515970500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010246952581919518,"open_date":"2018-01-14 12:45:00+00:00","close_date":"2018-01-14 13:25:00+00:00","open_rate":0.09758999,"close_rate":0.0980791628822055,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004891728822054991,"exit_reason":"roi","initial_stop_loss_abs":0.087830991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.087830991,"stop_loss_ratio":0.1,"min_rate":0.09758999,"max_rate":0.0980791628822055,"is_open":false,"buy_tag":null,"open_timestamp":1515933900000.0,"close_timestamp":1515936300000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3215434083601286,"open_date":"2018-01-14 15:30:00+00:00","close_date":"2018-01-14 16:00:00+00:00","open_rate":0.00311,"close_rate":0.0031567669172932328,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.676691729323286e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002799,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002799,"stop_loss_ratio":0.1,"min_rate":0.00311,"max_rate":0.0031567669172932328,"is_open":false,"buy_tag":null,"open_timestamp":1515943800000.0,"close_timestamp":1515945600000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.32010140812609433,"open_date":"2018-01-14 20:45:00+00:00","close_date":"2018-01-14 22:15:00+00:00","open_rate":0.00312401,"close_rate":0.003139669197994987,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":90,"profit_ratio":-0.0,"profit_abs":1.5659197994987058e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002811609,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002811609,"stop_loss_ratio":0.1,"min_rate":0.00312401,"max_rate":0.003139669197994987,"is_open":false,"buy_tag":null,"open_timestamp":1515962700000.0,"close_timestamp":1515968100000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.057247866085791646,"open_date":"2018-01-14 23:35:00+00:00","close_date":"2018-01-15 00:30:00+00:00","open_rate":0.0174679,"close_rate":0.017555458395989976,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":0.0,"profit_abs":8.755839598997492e-05,"exit_reason":"roi","initial_stop_loss_abs":0.015721110000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.015721110000000003,"stop_loss_ratio":0.1,"min_rate":0.0174679,"max_rate":0.017555458395989976,"is_open":false,"buy_tag":null,"open_timestamp":1515972900000.0,"close_timestamp":1515976200000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.013611282991367997,"open_date":"2018-01-14 23:45:00+00:00","close_date":"2018-01-15 00:25:00+00:00","open_rate":0.07346846,"close_rate":0.07383672295739348,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00036826295739347814,"exit_reason":"roi","initial_stop_loss_abs":0.066121614,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.066121614,"stop_loss_ratio":0.1,"min_rate":0.07346846,"max_rate":0.07383672295739348,"is_open":false,"buy_tag":null,"open_timestamp":1515973500000.0,"close_timestamp":1515975900000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010204706410596568,"open_date":"2018-01-15 02:25:00+00:00","close_date":"2018-01-15 03:05:00+00:00","open_rate":0.097994,"close_rate":0.09848519799498744,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004911979949874384,"exit_reason":"roi","initial_stop_loss_abs":0.0881946,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0881946,"stop_loss_ratio":0.1,"min_rate":0.097994,"max_rate":0.09848519799498744,"is_open":false,"buy_tag":null,"open_timestamp":1515983100000.0,"close_timestamp":1515985500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010353038616834042,"open_date":"2018-01-15 07:20:00+00:00","close_date":"2018-01-15 08:00:00+00:00","open_rate":0.09659,"close_rate":0.09707416040100247,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004841604010024786,"exit_reason":"roi","initial_stop_loss_abs":0.086931,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.086931,"stop_loss_ratio":0.1,"min_rate":0.09659,"max_rate":0.09707416040100247,"is_open":false,"buy_tag":null,"open_timestamp":1516000800000.0,"close_timestamp":1516003200000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.013016921998599,"open_date":"2018-01-15 08:20:00+00:00","close_date":"2018-01-15 08:55:00+00:00","open_rate":9.987e-05,"close_rate":0.00010137180451127818,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":1.501804511278178e-06,"exit_reason":"roi","initial_stop_loss_abs":8.9883e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.9883e-05,"stop_loss_ratio":0.1,"min_rate":9.987e-05,"max_rate":0.00010137180451127818,"is_open":false,"buy_tag":null,"open_timestamp":1516004400000.0,"close_timestamp":1516006500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010537752023511832,"open_date":"2018-01-15 12:10:00+00:00","close_date":"2018-01-16 02:50:00+00:00","open_rate":0.0948969,"close_rate":0.09537257368421052,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":880,"profit_ratio":0.0,"profit_abs":0.0004756736842105175,"exit_reason":"roi","initial_stop_loss_abs":0.08540721000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08540721000000001,"stop_loss_ratio":0.1,"min_rate":0.0948969,"max_rate":0.09537257368421052,"is_open":false,"buy_tag":null,"open_timestamp":1516018200000.0,"close_timestamp":1516071000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014084507042253523,"open_date":"2018-01-15 14:10:00+00:00","close_date":"2018-01-15 17:40:00+00:00","open_rate":0.071,"close_rate":0.07135588972431077,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":210,"profit_ratio":-0.0,"profit_abs":0.00035588972431077615,"exit_reason":"roi","initial_stop_loss_abs":0.0639,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0639,"stop_loss_ratio":0.1,"min_rate":0.071,"max_rate":0.07135588972431077,"is_open":false,"buy_tag":null,"open_timestamp":1516025400000.0,"close_timestamp":1516038000000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.021736763017766978,"open_date":"2018-01-15 14:30:00+00:00","close_date":"2018-01-15 15:10:00+00:00","open_rate":0.04600501,"close_rate":0.046235611553884705,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00023060155388470588,"exit_reason":"roi","initial_stop_loss_abs":0.041404509,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.041404509,"stop_loss_ratio":0.1,"min_rate":0.04600501,"max_rate":0.046235611553884705,"is_open":false,"buy_tag":null,"open_timestamp":1516026600000.0,"close_timestamp":1516029000000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.595465140919686,"open_date":"2018-01-15 18:10:00+00:00","close_date":"2018-01-15 19:25:00+00:00","open_rate":9.438e-05,"close_rate":9.485308270676693e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":75,"profit_ratio":-0.0,"profit_abs":4.7308270676692514e-07,"exit_reason":"roi","initial_stop_loss_abs":8.4942e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.4942e-05,"stop_loss_ratio":0.1,"min_rate":9.438e-05,"max_rate":9.485308270676693e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516039800000.0,"close_timestamp":1516044300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.032894726021471705,"open_date":"2018-01-15 18:35:00+00:00","close_date":"2018-01-15 19:15:00+00:00","open_rate":0.03040001,"close_rate":0.030552391002506264,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0001523810025062626,"exit_reason":"roi","initial_stop_loss_abs":0.027360009,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.027360009,"stop_loss_ratio":0.1,"min_rate":0.03040001,"max_rate":0.030552391002506264,"is_open":false,"buy_tag":null,"open_timestamp":1516041300000.0,"close_timestamp":1516043700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.13208840157615,"open_date":"2018-01-15 20:25:00+00:00","close_date":"2018-01-16 08:25:00+00:00","open_rate":5.837e-05,"close_rate":5.2533e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":720,"profit_ratio":-0.10448878,"profit_abs":-5.8369999999999985e-06,"exit_reason":"stop_loss","initial_stop_loss_abs":5.2533e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.2533e-05,"stop_loss_ratio":0.1,"min_rate":5.2533e-05,"max_rate":5.837e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516047900000.0,"close_timestamp":1516091100000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.021722130506560085,"open_date":"2018-01-15 20:40:00+00:00","close_date":"2018-01-15 22:00:00+00:00","open_rate":0.046036,"close_rate":0.04626675689223057,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.0,"profit_abs":0.00023075689223057277,"exit_reason":"roi","initial_stop_loss_abs":0.0414324,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0414324,"stop_loss_ratio":0.1,"min_rate":0.046036,"max_rate":0.04626675689223057,"is_open":false,"buy_tag":null,"open_timestamp":1516048800000.0,"close_timestamp":1516053600000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.34861425832316545,"open_date":"2018-01-16 00:30:00+00:00","close_date":"2018-01-16 01:10:00+00:00","open_rate":0.0028685,"close_rate":0.0028828784461152877,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.4378446115287727e-05,"exit_reason":"roi","initial_stop_loss_abs":0.00258165,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.00258165,"stop_loss_ratio":0.1,"min_rate":0.0028685,"max_rate":0.0028828784461152877,"is_open":false,"buy_tag":null,"open_timestamp":1516062600000.0,"close_timestamp":1516065000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014854967241083492,"open_date":"2018-01-16 01:15:00+00:00","close_date":"2018-01-16 02:35:00+00:00","open_rate":0.06731755,"close_rate":0.0676549813283208,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":0.0,"profit_abs":0.00033743132832080025,"exit_reason":"roi","initial_stop_loss_abs":0.060585795000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060585795000000005,"stop_loss_ratio":0.1,"min_rate":0.06731755,"max_rate":0.0676549813283208,"is_open":false,"buy_tag":null,"open_timestamp":1516065300000.0,"close_timestamp":1516070100000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010848794492804754,"open_date":"2018-01-16 07:45:00+00:00","close_date":"2018-01-16 08:40:00+00:00","open_rate":0.09217614,"close_rate":0.09263817578947368,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":0.0,"profit_abs":0.0004620357894736804,"exit_reason":"roi","initial_stop_loss_abs":0.082958526,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.082958526,"stop_loss_ratio":0.1,"min_rate":0.09217614,"max_rate":0.09263817578947368,"is_open":false,"buy_tag":null,"open_timestamp":1516088700000.0,"close_timestamp":1516092000000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06060606060606061,"open_date":"2018-01-16 08:35:00+00:00","close_date":"2018-01-16 08:55:00+00:00","open_rate":0.0165,"close_rate":0.016913533834586467,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":0.00041353383458646656,"exit_reason":"roi","initial_stop_loss_abs":0.01485,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.01485,"stop_loss_ratio":0.1,"min_rate":0.0165,"max_rate":0.016913533834586467,"is_open":false,"buy_tag":null,"open_timestamp":1516091700000.0,"close_timestamp":1516092900000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":12.57387149503332,"open_date":"2018-01-16 08:35:00+00:00","close_date":"2018-01-16 08:40:00+00:00","open_rate":7.953e-05,"close_rate":8.311781954887218e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":3.587819548872171e-06,"exit_reason":"roi","initial_stop_loss_abs":7.157700000000001e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":7.157700000000001e-05,"stop_loss_ratio":0.1,"min_rate":7.953e-05,"max_rate":8.311781954887218e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516091700000.0,"close_timestamp":1516092000000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022122914915269236,"open_date":"2018-01-16 08:45:00+00:00","close_date":"2018-01-16 09:50:00+00:00","open_rate":0.045202,"close_rate":0.04542857644110275,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":65,"profit_ratio":-0.0,"profit_abs":0.00022657644110275071,"exit_reason":"roi","initial_stop_loss_abs":0.0406818,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0406818,"stop_loss_ratio":0.1,"min_rate":0.045202,"max_rate":0.04542857644110275,"is_open":false,"buy_tag":null,"open_timestamp":1516092300000.0,"close_timestamp":1516096200000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.054878048780488,"open_date":"2018-01-16 09:15:00+00:00","close_date":"2018-01-16 09:45:00+00:00","open_rate":5.248e-05,"close_rate":5.326917293233082e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":7.891729323308177e-07,"exit_reason":"roi","initial_stop_loss_abs":4.7232e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7232e-05,"stop_loss_ratio":0.1,"min_rate":5.248e-05,"max_rate":5.326917293233082e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516094100000.0,"close_timestamp":1516095900000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03457434486802627,"open_date":"2018-01-16 09:15:00+00:00","close_date":"2018-01-16 09:55:00+00:00","open_rate":0.02892318,"close_rate":0.02906815834586466,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.0001449783458646603,"exit_reason":"roi","initial_stop_loss_abs":0.026030862000000002,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.026030862000000002,"stop_loss_ratio":0.1,"min_rate":0.02892318,"max_rate":0.02906815834586466,"is_open":false,"buy_tag":null,"open_timestamp":1516094100000.0,"close_timestamp":1516096500000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.38735944164405,"open_date":"2018-01-16 09:50:00+00:00","close_date":"2018-01-16 10:10:00+00:00","open_rate":5.158e-05,"close_rate":5.287273182957392e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":1.2927318295739246e-06,"exit_reason":"roi","initial_stop_loss_abs":4.6422e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6422e-05,"stop_loss_ratio":0.1,"min_rate":5.158e-05,"max_rate":5.287273182957392e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516096200000.0,"close_timestamp":1516097400000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.035357778286929785,"open_date":"2018-01-16 10:05:00+00:00","close_date":"2018-01-16 10:35:00+00:00","open_rate":0.02828232,"close_rate":0.02870761804511278,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.00042529804511277913,"exit_reason":"roi","initial_stop_loss_abs":0.025454088,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025454088,"stop_loss_ratio":0.1,"min_rate":0.02828232,"max_rate":0.02870761804511278,"is_open":false,"buy_tag":null,"open_timestamp":1516097100000.0,"close_timestamp":1516098900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022948496230938982,"open_date":"2018-01-16 10:05:00+00:00","close_date":"2018-01-16 10:40:00+00:00","open_rate":0.04357584,"close_rate":0.044231115789473675,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0006552757894736777,"exit_reason":"roi","initial_stop_loss_abs":0.039218256,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.039218256,"stop_loss_ratio":0.1,"min_rate":0.04357584,"max_rate":0.044231115789473675,"is_open":false,"buy_tag":null,"open_timestamp":1516097100000.0,"close_timestamp":1516099200000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.64975755315181,"open_date":"2018-01-16 13:45:00+00:00","close_date":"2018-01-16 14:20:00+00:00","open_rate":5.362e-05,"close_rate":5.442631578947368e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":8.063157894736843e-07,"exit_reason":"roi","initial_stop_loss_abs":4.8258e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.8258e-05,"stop_loss_ratio":0.1,"min_rate":5.362e-05,"max_rate":5.442631578947368e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516110300000.0,"close_timestamp":1516112400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.86080724254998,"open_date":"2018-01-16 17:30:00+00:00","close_date":"2018-01-16 18:25:00+00:00","open_rate":5.302e-05,"close_rate":5.328576441102756e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.6576441102756397e-07,"exit_reason":"roi","initial_stop_loss_abs":4.7718e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7718e-05,"stop_loss_ratio":0.1,"min_rate":5.302e-05,"max_rate":5.328576441102756e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516123800000.0,"close_timestamp":1516127100000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010952903718828448,"open_date":"2018-01-16 18:15:00+00:00","close_date":"2018-01-16 18:45:00+00:00","open_rate":0.09129999,"close_rate":0.09267292218045112,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.0013729321804511196,"exit_reason":"roi","initial_stop_loss_abs":0.082169991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.082169991,"stop_loss_ratio":0.1,"min_rate":0.09129999,"max_rate":0.09267292218045112,"is_open":false,"buy_tag":null,"open_timestamp":1516126500000.0,"close_timestamp":1516128300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":26.26050420168067,"open_date":"2018-01-16 18:15:00+00:00","close_date":"2018-01-16 18:35:00+00:00","open_rate":3.808e-05,"close_rate":3.903438596491228e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":9.543859649122774e-07,"exit_reason":"roi","initial_stop_loss_abs":3.4272e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.4272e-05,"stop_loss_ratio":0.1,"min_rate":3.808e-05,"max_rate":3.903438596491228e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516126500000.0,"close_timestamp":1516127700000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.035574376772493324,"open_date":"2018-01-16 19:00:00+00:00","close_date":"2018-01-16 19:30:00+00:00","open_rate":0.02811012,"close_rate":0.028532828571428567,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.00042270857142856846,"exit_reason":"roi","initial_stop_loss_abs":0.025299108,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025299108,"stop_loss_ratio":0.1,"min_rate":0.02811012,"max_rate":0.028532828571428567,"is_open":false,"buy_tag":null,"open_timestamp":1516129200000.0,"close_timestamp":1516131000000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.387028357567759,"open_date":"2018-01-16 21:25:00+00:00","close_date":"2018-01-16 22:25:00+00:00","open_rate":0.00258379,"close_rate":0.002325411,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.10448878,"profit_abs":-0.000258379,"exit_reason":"stop_loss","initial_stop_loss_abs":0.002325411,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002325411,"stop_loss_ratio":0.1,"min_rate":0.002325411,"max_rate":0.00258379,"is_open":false,"buy_tag":null,"open_timestamp":1516137900000.0,"close_timestamp":1516141500000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":39.07776475185619,"open_date":"2018-01-16 21:25:00+00:00","close_date":"2018-01-16 22:45:00+00:00","open_rate":2.559e-05,"close_rate":2.3031e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.10448878,"profit_abs":-2.5590000000000004e-06,"exit_reason":"stop_loss","initial_stop_loss_abs":2.3031e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.3031e-05,"stop_loss_ratio":0.1,"min_rate":2.3031e-05,"max_rate":2.559e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516137900000.0,"close_timestamp":1516142700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":13.123359580052494,"open_date":"2018-01-16 21:35:00+00:00","close_date":"2018-01-16 22:25:00+00:00","open_rate":7.62e-05,"close_rate":6.858e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":-0.10448878,"profit_abs":-7.619999999999998e-06,"exit_reason":"stop_loss","initial_stop_loss_abs":6.858e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":6.858e-05,"stop_loss_ratio":0.1,"min_rate":6.858e-05,"max_rate":7.62e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516138500000.0,"close_timestamp":1516141500000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.4350777048780912,"open_date":"2018-01-16 22:30:00+00:00","close_date":"2018-01-16 22:35:00+00:00","open_rate":0.00229844,"close_rate":0.002402129022556391,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":0.00010368902255639091,"exit_reason":"roi","initial_stop_loss_abs":0.0020685960000000002,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0020685960000000002,"stop_loss_ratio":0.1,"min_rate":0.00229844,"max_rate":0.002402129022556391,"is_open":false,"buy_tag":null,"open_timestamp":1516141800000.0,"close_timestamp":1516142100000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06622516556291391,"open_date":"2018-01-16 22:30:00+00:00","close_date":"2018-01-16 22:40:00+00:00","open_rate":0.0151,"close_rate":0.015781203007518795,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":10,"profit_ratio":0.03990025,"profit_abs":0.0006812030075187946,"exit_reason":"roi","initial_stop_loss_abs":0.013590000000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.013590000000000001,"stop_loss_ratio":0.1,"min_rate":0.0151,"max_rate":0.015781203007518795,"is_open":false,"buy_tag":null,"open_timestamp":1516141800000.0,"close_timestamp":1516142400000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.42431134269081283,"open_date":"2018-01-16 22:40:00+00:00","close_date":"2018-01-16 22:45:00+00:00","open_rate":0.00235676,"close_rate":0.00246308,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":0.00010632000000000003,"exit_reason":"roi","initial_stop_loss_abs":0.002121084,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002121084,"stop_loss_ratio":0.1,"min_rate":0.00235676,"max_rate":0.00246308,"is_open":false,"buy_tag":null,"open_timestamp":1516142400000.0,"close_timestamp":1516142700000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.01585559988076589,"open_date":"2018-01-16 22:45:00+00:00","close_date":"2018-01-16 23:05:00+00:00","open_rate":0.0630692,"close_rate":0.06464988170426066,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":0.0015806817042606502,"exit_reason":"roi","initial_stop_loss_abs":0.056762280000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.056762280000000005,"stop_loss_ratio":0.1,"min_rate":0.0630692,"max_rate":0.06464988170426066,"is_open":false,"buy_tag":null,"open_timestamp":1516142700000.0,"close_timestamp":1516143900000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":45.45454545454545,"open_date":"2018-01-16 22:50:00+00:00","close_date":"2018-01-16 22:55:00+00:00","open_rate":2.2e-05,"close_rate":2.299248120300751e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":9.924812030075114e-07,"exit_reason":"roi","initial_stop_loss_abs":1.98e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":1.98e-05,"stop_loss_ratio":0.1,"min_rate":2.2e-05,"max_rate":2.299248120300751e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516143000000.0,"close_timestamp":1516143300000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":20.10454362685967,"open_date":"2018-01-17 03:30:00+00:00","close_date":"2018-01-17 04:00:00+00:00","open_rate":4.974e-05,"close_rate":5.048796992481203e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":7.479699248120277e-07,"exit_reason":"roi","initial_stop_loss_abs":4.4766000000000005e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4766000000000005e-05,"stop_loss_ratio":0.1,"min_rate":4.974e-05,"max_rate":5.048796992481203e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516159800000.0,"close_timestamp":1516161600000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":14.068655036578503,"open_date":"2018-01-17 03:55:00+00:00","close_date":"2018-01-17 04:15:00+00:00","open_rate":7.108e-05,"close_rate":7.28614536340852e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":1.7814536340851996e-06,"exit_reason":"roi","initial_stop_loss_abs":6.3972e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":6.3972e-05,"stop_loss_ratio":0.1,"min_rate":7.108e-05,"max_rate":7.28614536340852e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516161300000.0,"close_timestamp":1516162500000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.0231107002542177,"open_date":"2018-01-17 09:35:00+00:00","close_date":"2018-01-17 10:15:00+00:00","open_rate":0.04327,"close_rate":0.04348689223057644,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0002168922305764362,"exit_reason":"roi","initial_stop_loss_abs":0.038943000000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.038943000000000005,"stop_loss_ratio":0.1,"min_rate":0.04327,"max_rate":0.04348689223057644,"is_open":false,"buy_tag":null,"open_timestamp":1516181700000.0,"close_timestamp":1516184100000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":20.012007204322593,"open_date":"2018-01-17 10:20:00+00:00","close_date":"2018-01-17 17:00:00+00:00","open_rate":4.997e-05,"close_rate":5.022047619047618e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":400,"profit_ratio":-0.0,"profit_abs":2.504761904761831e-07,"exit_reason":"roi","initial_stop_loss_abs":4.4973e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4973e-05,"stop_loss_ratio":0.1,"min_rate":4.997e-05,"max_rate":5.022047619047618e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516184400000.0,"close_timestamp":1516208400000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014626687444363738,"open_date":"2018-01-17 10:30:00+00:00","close_date":"2018-01-17 11:25:00+00:00","open_rate":0.06836818,"close_rate":0.06871087764411027,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":0.00034269764411026804,"exit_reason":"roi","initial_stop_loss_abs":0.061531362,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.061531362,"stop_loss_ratio":0.1,"min_rate":0.06836818,"max_rate":0.06871087764411027,"is_open":false,"buy_tag":null,"open_timestamp":1516185000000.0,"close_timestamp":1516188300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":27.548209366391184,"open_date":"2018-01-17 10:30:00+00:00","close_date":"2018-01-17 11:10:00+00:00","open_rate":3.63e-05,"close_rate":3.648195488721804e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.8195488721804031e-07,"exit_reason":"roi","initial_stop_loss_abs":3.2670000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.2670000000000004e-05,"stop_loss_ratio":0.1,"min_rate":3.63e-05,"max_rate":3.648195488721804e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516185000000.0,"close_timestamp":1516187400000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03558718861209965,"open_date":"2018-01-17 12:30:00+00:00","close_date":"2018-01-17 22:05:00+00:00","open_rate":0.0281,"close_rate":0.02824085213032581,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":575,"profit_ratio":-0.0,"profit_abs":0.0001408521303258095,"exit_reason":"roi","initial_stop_loss_abs":0.02529,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.02529,"stop_loss_ratio":0.1,"min_rate":0.0281,"max_rate":0.02824085213032581,"is_open":false,"buy_tag":null,"open_timestamp":1516192200000.0,"close_timestamp":1516226700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011559355963546878,"open_date":"2018-01-17 12:35:00+00:00","close_date":"2018-01-17 16:55:00+00:00","open_rate":0.08651001,"close_rate":0.08694364413533832,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":260,"profit_ratio":-0.0,"profit_abs":0.00043363413533832607,"exit_reason":"roi","initial_stop_loss_abs":0.077859009,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.077859009,"stop_loss_ratio":0.1,"min_rate":0.08651001,"max_rate":0.08694364413533832,"is_open":false,"buy_tag":null,"open_timestamp":1516192500000.0,"close_timestamp":1516208100000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.752529735487308,"open_date":"2018-01-18 05:00:00+00:00","close_date":"2018-01-18 05:55:00+00:00","open_rate":5.633e-05,"close_rate":5.6612355889724306e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.8235588972430847e-07,"exit_reason":"roi","initial_stop_loss_abs":5.0697e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0697e-05,"stop_loss_ratio":0.1,"min_rate":5.633e-05,"max_rate":5.6612355889724306e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516251600000.0,"close_timestamp":1516254900000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.01430923457900944,"open_date":"2018-01-18 05:20:00+00:00","close_date":"2018-01-18 05:55:00+00:00","open_rate":0.06988494,"close_rate":0.07093584135338346,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0010509013533834544,"exit_reason":"roi","initial_stop_loss_abs":0.06289644600000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06289644600000001,"stop_loss_ratio":0.1,"min_rate":0.06988494,"max_rate":0.07093584135338346,"is_open":false,"buy_tag":null,"open_timestamp":1516252800000.0,"close_timestamp":1516254900000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.034265103697024,"open_date":"2018-01-18 07:35:00+00:00","close_date":"2018-01-18 08:15:00+00:00","open_rate":5.545e-05,"close_rate":5.572794486215538e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.779448621553787e-07,"exit_reason":"roi","initial_stop_loss_abs":4.9905e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.9905e-05,"stop_loss_ratio":0.1,"min_rate":5.545e-05,"max_rate":5.572794486215538e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516260900000.0,"close_timestamp":1516263300000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06121723118136401,"open_date":"2018-01-18 09:00:00+00:00","close_date":"2018-01-18 09:40:00+00:00","open_rate":0.01633527,"close_rate":0.016417151052631574,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":8.188105263157511e-05,"exit_reason":"roi","initial_stop_loss_abs":0.014701743,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014701743,"stop_loss_ratio":0.1,"min_rate":0.01633527,"max_rate":0.016417151052631574,"is_open":false,"buy_tag":null,"open_timestamp":1516266000000.0,"close_timestamp":1516268400000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3707356136045141,"open_date":"2018-01-18 16:40:00+00:00","close_date":"2018-01-18 17:20:00+00:00","open_rate":0.00269734,"close_rate":0.002710860501253133,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.3520501253133123e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002427606,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002427606,"stop_loss_ratio":0.1,"min_rate":0.00269734,"max_rate":0.002710860501253133,"is_open":false,"buy_tag":null,"open_timestamp":1516293600000.0,"close_timestamp":1516296000000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":22.346368715083802,"open_date":"2018-01-18 18:05:00+00:00","close_date":"2018-01-18 18:30:00+00:00","open_rate":4.475e-05,"close_rate":4.587155388471177e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":1.1215538847117757e-06,"exit_reason":"roi","initial_stop_loss_abs":4.0274999999999996e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.0274999999999996e-05,"stop_loss_ratio":0.1,"min_rate":4.475e-05,"max_rate":4.587155388471177e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516298700000.0,"close_timestamp":1516300200000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":35.842293906810035,"open_date":"2018-01-18 18:25:00+00:00","close_date":"2018-01-18 18:55:00+00:00","open_rate":2.79e-05,"close_rate":2.8319548872180444e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.1954887218044365e-07,"exit_reason":"roi","initial_stop_loss_abs":2.5110000000000002e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.5110000000000002e-05,"stop_loss_ratio":0.1,"min_rate":2.79e-05,"max_rate":2.8319548872180444e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516299900000.0,"close_timestamp":1516301700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022525942001105574,"open_date":"2018-01-18 20:10:00+00:00","close_date":"2018-01-18 20:50:00+00:00","open_rate":0.04439326,"close_rate":0.04461578260651629,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.00022252260651629135,"exit_reason":"roi","initial_stop_loss_abs":0.039953933999999997,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.039953933999999997,"stop_loss_ratio":0.1,"min_rate":0.04439326,"max_rate":0.04461578260651629,"is_open":false,"buy_tag":null,"open_timestamp":1516306200000.0,"close_timestamp":1516308600000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":22.271714922048996,"open_date":"2018-01-18 21:30:00+00:00","close_date":"2018-01-19 00:35:00+00:00","open_rate":4.49e-05,"close_rate":4.51250626566416e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":185,"profit_ratio":0.0,"profit_abs":2.2506265664159932e-07,"exit_reason":"roi","initial_stop_loss_abs":4.041e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.041e-05,"stop_loss_ratio":0.1,"min_rate":4.49e-05,"max_rate":4.51250626566416e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516311000000.0,"close_timestamp":1516322100000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03502626970227671,"open_date":"2018-01-18 21:55:00+00:00","close_date":"2018-01-19 05:05:00+00:00","open_rate":0.02855,"close_rate":0.028693107769423555,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":430,"profit_ratio":-0.0,"profit_abs":0.00014310776942355607,"exit_reason":"roi","initial_stop_loss_abs":0.025695,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025695,"stop_loss_ratio":0.1,"min_rate":0.02855,"max_rate":0.028693107769423555,"is_open":false,"buy_tag":null,"open_timestamp":1516312500000.0,"close_timestamp":1516338300000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.25327812284334,"open_date":"2018-01-18 22:10:00+00:00","close_date":"2018-01-18 22:50:00+00:00","open_rate":5.796e-05,"close_rate":5.8250526315789473e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":2.905263157894727e-07,"exit_reason":"roi","initial_stop_loss_abs":5.2164000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.2164000000000004e-05,"stop_loss_ratio":0.1,"min_rate":5.796e-05,"max_rate":5.8250526315789473e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516313400000.0,"close_timestamp":1516315800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02303975994413319,"open_date":"2018-01-18 23:50:00+00:00","close_date":"2018-01-19 00:30:00+00:00","open_rate":0.04340323,"close_rate":0.04362079005012531,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.0002175600501253122,"exit_reason":"roi","initial_stop_loss_abs":0.039062907,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.039062907,"stop_loss_ratio":0.1,"min_rate":0.04340323,"max_rate":0.04362079005012531,"is_open":false,"buy_tag":null,"open_timestamp":1516319400000.0,"close_timestamp":1516321800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02244943545282195,"open_date":"2018-01-19 16:45:00+00:00","close_date":"2018-01-19 17:35:00+00:00","open_rate":0.04454455,"close_rate":0.04476783095238095,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":0.0,"profit_abs":0.0002232809523809512,"exit_reason":"roi","initial_stop_loss_abs":0.040090095000000006,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.040090095000000006,"stop_loss_ratio":0.1,"min_rate":0.04454455,"max_rate":0.04476783095238095,"is_open":false,"buy_tag":null,"open_timestamp":1516380300000.0,"close_timestamp":1516383300000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.793594306049823,"open_date":"2018-01-19 17:15:00+00:00","close_date":"2018-01-19 19:55:00+00:00","open_rate":5.62e-05,"close_rate":5.648170426065162e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":160,"profit_ratio":-0.0,"profit_abs":2.817042606516199e-07,"exit_reason":"roi","initial_stop_loss_abs":5.058e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.058e-05,"stop_loss_ratio":0.1,"min_rate":5.62e-05,"max_rate":5.648170426065162e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516382100000.0,"close_timestamp":1516391700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":23.046784973496194,"open_date":"2018-01-19 17:20:00+00:00","close_date":"2018-01-19 20:15:00+00:00","open_rate":4.339e-05,"close_rate":4.360749373433584e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":175,"profit_ratio":-0.0,"profit_abs":2.174937343358337e-07,"exit_reason":"roi","initial_stop_loss_abs":3.9051e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.9051e-05,"stop_loss_ratio":0.1,"min_rate":4.339e-05,"max_rate":4.360749373433584e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516382400000.0,"close_timestamp":1516392900000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":9.910802775024777,"open_date":"2018-01-20 04:45:00+00:00","close_date":"2018-01-20 17:35:00+00:00","open_rate":0.0001009,"close_rate":0.00010140576441102755,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":770,"profit_ratio":0.0,"profit_abs":5.057644110275549e-07,"exit_reason":"roi","initial_stop_loss_abs":9.081e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":9.081e-05,"stop_loss_ratio":0.1,"min_rate":0.0001009,"max_rate":0.00010140576441102755,"is_open":false,"buy_tag":null,"open_timestamp":1516423500000.0,"close_timestamp":1516469700000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3696789338459548,"open_date":"2018-01-20 04:50:00+00:00","close_date":"2018-01-20 15:15:00+00:00","open_rate":0.00270505,"close_rate":0.002718609147869674,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":625,"profit_ratio":-0.0,"profit_abs":1.3559147869673764e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002434545,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002434545,"stop_loss_ratio":0.1,"min_rate":0.00270505,"max_rate":0.002718609147869674,"is_open":false,"buy_tag":null,"open_timestamp":1516423800000.0,"close_timestamp":1516461300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.033333311111125925,"open_date":"2018-01-20 04:50:00+00:00","close_date":"2018-01-20 07:00:00+00:00","open_rate":0.03000002,"close_rate":0.030150396040100245,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":130,"profit_ratio":-0.0,"profit_abs":0.00015037604010024672,"exit_reason":"roi","initial_stop_loss_abs":0.027000018,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.027000018,"stop_loss_ratio":0.1,"min_rate":0.03000002,"max_rate":0.030150396040100245,"is_open":false,"buy_tag":null,"open_timestamp":1516423800000.0,"close_timestamp":1516431600000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.315018315018317,"open_date":"2018-01-20 09:00:00+00:00","close_date":"2018-01-20 09:40:00+00:00","open_rate":5.46e-05,"close_rate":5.4873684210526304e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.736842105263053e-07,"exit_reason":"roi","initial_stop_loss_abs":4.914e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.914e-05,"stop_loss_ratio":0.1,"min_rate":5.46e-05,"max_rate":5.4873684210526304e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516438800000.0,"close_timestamp":1516441200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03244412634781012,"open_date":"2018-01-20 18:25:00+00:00","close_date":"2018-01-25 03:50:00+00:00","open_rate":0.03082222,"close_rate":0.027739998,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":6325,"profit_ratio":-0.10448878,"profit_abs":-0.0030822220000000025,"exit_reason":"stop_loss","initial_stop_loss_abs":0.027739998000000002,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.027739998000000002,"stop_loss_ratio":0.1,"min_rate":0.027739998,"max_rate":0.03082222,"is_open":false,"buy_tag":null,"open_timestamp":1516472700000.0,"close_timestamp":1516852200000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011148273260677065,"open_date":"2018-01-20 22:25:00+00:00","close_date":"2018-01-20 23:15:00+00:00","open_rate":0.08969999,"close_rate":0.09014961401002504,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":-0.0,"profit_abs":0.00044962401002504593,"exit_reason":"roi","initial_stop_loss_abs":0.080729991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.080729991,"stop_loss_ratio":0.1,"min_rate":0.08969999,"max_rate":0.09014961401002504,"is_open":false,"buy_tag":null,"open_timestamp":1516487100000.0,"close_timestamp":1516490100000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06125570520324337,"open_date":"2018-01-21 02:50:00+00:00","close_date":"2018-01-21 14:30:00+00:00","open_rate":0.01632501,"close_rate":0.01640683962406015,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":700,"profit_ratio":0.0,"profit_abs":8.182962406014932e-05,"exit_reason":"roi","initial_stop_loss_abs":0.014692509000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014692509000000001,"stop_loss_ratio":0.1,"min_rate":0.01632501,"max_rate":0.01640683962406015,"is_open":false,"buy_tag":null,"open_timestamp":1516503000000.0,"close_timestamp":1516545000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.01417675579120474,"open_date":"2018-01-21 10:20:00+00:00","close_date":"2018-01-21 11:00:00+00:00","open_rate":0.070538,"close_rate":0.07089157393483708,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00035357393483707866,"exit_reason":"roi","initial_stop_loss_abs":0.0634842,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0634842,"stop_loss_ratio":0.1,"min_rate":0.070538,"max_rate":0.07089157393483708,"is_open":false,"buy_tag":null,"open_timestamp":1516530000000.0,"close_timestamp":1516532400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.864365214110546,"open_date":"2018-01-21 15:50:00+00:00","close_date":"2018-01-21 18:45:00+00:00","open_rate":5.301e-05,"close_rate":5.327571428571427e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":175,"profit_ratio":-0.0,"profit_abs":2.657142857142672e-07,"exit_reason":"roi","initial_stop_loss_abs":4.7709e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7709e-05,"stop_loss_ratio":0.1,"min_rate":5.301e-05,"max_rate":5.327571428571427e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516549800000.0,"close_timestamp":1516560300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":25.284450063211125,"open_date":"2018-01-21 16:20:00+00:00","close_date":"2018-01-21 17:00:00+00:00","open_rate":3.955e-05,"close_rate":3.9748245614035085e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":1.9824561403508552e-07,"exit_reason":"roi","initial_stop_loss_abs":3.5595e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.5595e-05,"stop_loss_ratio":0.1,"min_rate":3.955e-05,"max_rate":3.9748245614035085e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516551600000.0,"close_timestamp":1516554000000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38683971296493297,"open_date":"2018-01-21 21:15:00+00:00","close_date":"2018-01-21 21:45:00+00:00","open_rate":0.00258505,"close_rate":0.002623922932330827,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":3.8872932330826816e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002326545,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002326545,"stop_loss_ratio":0.1,"min_rate":0.00258505,"max_rate":0.002623922932330827,"is_open":false,"buy_tag":null,"open_timestamp":1516569300000.0,"close_timestamp":1516571100000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":25.621316935690498,"open_date":"2018-01-21 21:15:00+00:00","close_date":"2018-01-21 21:55:00+00:00","open_rate":3.903e-05,"close_rate":3.922563909774435e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.9563909774435151e-07,"exit_reason":"roi","initial_stop_loss_abs":3.5127e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.5127e-05,"stop_loss_ratio":0.1,"min_rate":3.903e-05,"max_rate":3.922563909774435e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516569300000.0,"close_timestamp":1516571700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.098548510313215,"open_date":"2018-01-22 00:35:00+00:00","close_date":"2018-01-22 10:35:00+00:00","open_rate":5.236e-05,"close_rate":5.262245614035087e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":600,"profit_ratio":-0.0,"profit_abs":2.624561403508717e-07,"exit_reason":"roi","initial_stop_loss_abs":4.7124e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7124e-05,"stop_loss_ratio":0.1,"min_rate":5.236e-05,"max_rate":5.262245614035087e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516581300000.0,"close_timestamp":1516617300000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.076650420912717,"open_date":"2018-01-22 01:30:00+00:00","close_date":"2018-01-22 02:10:00+00:00","open_rate":9.028e-05,"close_rate":9.07325313283208e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":4.5253132832080657e-07,"exit_reason":"roi","initial_stop_loss_abs":8.1252e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.1252e-05,"stop_loss_ratio":0.1,"min_rate":9.028e-05,"max_rate":9.07325313283208e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516584600000.0,"close_timestamp":1516587000000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3721622627465575,"open_date":"2018-01-22 12:25:00+00:00","close_date":"2018-01-22 14:35:00+00:00","open_rate":0.002687,"close_rate":0.002700468671679198,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":130,"profit_ratio":-0.0,"profit_abs":1.3468671679197925e-05,"exit_reason":"roi","initial_stop_loss_abs":0.0024183000000000004,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0024183000000000004,"stop_loss_ratio":0.1,"min_rate":0.002687,"max_rate":0.002700468671679198,"is_open":false,"buy_tag":null,"open_timestamp":1516623900000.0,"close_timestamp":1516631700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":23.99232245681382,"open_date":"2018-01-22 13:15:00+00:00","close_date":"2018-01-22 13:55:00+00:00","open_rate":4.168e-05,"close_rate":4.188892230576441e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.0892230576441054e-07,"exit_reason":"roi","initial_stop_loss_abs":3.7512e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.7512e-05,"stop_loss_ratio":0.1,"min_rate":4.168e-05,"max_rate":4.188892230576441e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516626900000.0,"close_timestamp":1516629300000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.336583153837434,"open_date":"2018-01-22 14:00:00+00:00","close_date":"2018-01-22 14:30:00+00:00","open_rate":8.821e-05,"close_rate":8.953646616541353e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":1.326466165413529e-06,"exit_reason":"roi","initial_stop_loss_abs":7.9389e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":7.9389e-05,"stop_loss_ratio":0.1,"min_rate":8.821e-05,"max_rate":8.953646616541353e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516629600000.0,"close_timestamp":1516631400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.334880123743233,"open_date":"2018-01-22 15:55:00+00:00","close_date":"2018-01-22 16:40:00+00:00","open_rate":5.172e-05,"close_rate":5.1979248120300745e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":2.592481203007459e-07,"exit_reason":"roi","initial_stop_loss_abs":4.6548e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6548e-05,"stop_loss_ratio":0.1,"min_rate":5.172e-05,"max_rate":5.1979248120300745e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516636500000.0,"close_timestamp":1516639200000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":33.04692663582287,"open_date":"2018-01-22 16:05:00+00:00","close_date":"2018-01-22 16:25:00+00:00","open_rate":3.026e-05,"close_rate":3.101839598997494e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":7.5839598997494e-07,"exit_reason":"roi","initial_stop_loss_abs":2.7234e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7234e-05,"stop_loss_ratio":0.1,"min_rate":3.026e-05,"max_rate":3.101839598997494e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516637100000.0,"close_timestamp":1516638300000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014156285390713478,"open_date":"2018-01-22 19:50:00+00:00","close_date":"2018-01-23 00:10:00+00:00","open_rate":0.07064,"close_rate":0.07099408521303258,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":260,"profit_ratio":0.0,"profit_abs":0.00035408521303258167,"exit_reason":"roi","initial_stop_loss_abs":0.063576,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.063576,"stop_loss_ratio":0.1,"min_rate":0.07064,"max_rate":0.07099408521303258,"is_open":false,"buy_tag":null,"open_timestamp":1516650600000.0,"close_timestamp":1516666200000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06080938507725528,"open_date":"2018-01-22 21:25:00+00:00","close_date":"2018-01-22 22:05:00+00:00","open_rate":0.01644483,"close_rate":0.01652726022556391,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":8.243022556390922e-05,"exit_reason":"roi","initial_stop_loss_abs":0.014800347,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014800347,"stop_loss_ratio":0.1,"min_rate":0.01644483,"max_rate":0.01652726022556391,"is_open":false,"buy_tag":null,"open_timestamp":1516656300000.0,"close_timestamp":1516658700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":23.08935580697299,"open_date":"2018-01-23 00:05:00+00:00","close_date":"2018-01-23 00:35:00+00:00","open_rate":4.331e-05,"close_rate":4.3961278195488714e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":6.512781954887175e-07,"exit_reason":"roi","initial_stop_loss_abs":3.8979e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.8979e-05,"stop_loss_ratio":0.1,"min_rate":4.331e-05,"max_rate":4.3961278195488714e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516665900000.0,"close_timestamp":1516667700000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":31.250000000000004,"open_date":"2018-01-23 01:50:00+00:00","close_date":"2018-01-23 02:15:00+00:00","open_rate":3.2e-05,"close_rate":3.2802005012531326e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":8.020050125313278e-07,"exit_reason":"roi","initial_stop_loss_abs":2.88e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.88e-05,"stop_loss_ratio":0.1,"min_rate":3.2e-05,"max_rate":3.2802005012531326e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516672200000.0,"close_timestamp":1516673700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010907854156754155,"open_date":"2018-01-23 04:25:00+00:00","close_date":"2018-01-23 05:15:00+00:00","open_rate":0.09167706,"close_rate":0.09213659413533835,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":0.0,"profit_abs":0.0004595341353383492,"exit_reason":"roi","initial_stop_loss_abs":0.08250935400000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08250935400000001,"stop_loss_ratio":0.1,"min_rate":0.09167706,"max_rate":0.09213659413533835,"is_open":false,"buy_tag":null,"open_timestamp":1516681500000.0,"close_timestamp":1516684500000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014440474918339115,"open_date":"2018-01-23 07:35:00+00:00","close_date":"2018-01-23 09:00:00+00:00","open_rate":0.0692498,"close_rate":0.06959691679197995,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":85,"profit_ratio":0.0,"profit_abs":0.0003471167919799484,"exit_reason":"roi","initial_stop_loss_abs":0.06232482,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06232482,"stop_loss_ratio":0.1,"min_rate":0.0692498,"max_rate":0.06959691679197995,"is_open":false,"buy_tag":null,"open_timestamp":1516692900000.0,"close_timestamp":1516698000000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":31.426775612822127,"open_date":"2018-01-23 10:50:00+00:00","close_date":"2018-01-23 13:05:00+00:00","open_rate":3.182e-05,"close_rate":3.197949874686716e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":135,"profit_ratio":0.0,"profit_abs":1.594987468671663e-07,"exit_reason":"roi","initial_stop_loss_abs":2.8638e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.8638e-05,"stop_loss_ratio":0.1,"min_rate":3.182e-05,"max_rate":3.197949874686716e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516704600000.0,"close_timestamp":1516712700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024461839530332683,"open_date":"2018-01-23 11:05:00+00:00","close_date":"2018-01-23 16:05:00+00:00","open_rate":0.04088,"close_rate":0.04108491228070175,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":300,"profit_ratio":-0.0,"profit_abs":0.0002049122807017481,"exit_reason":"roi","initial_stop_loss_abs":0.036792,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036792,"stop_loss_ratio":0.1,"min_rate":0.04088,"max_rate":0.04108491228070175,"is_open":false,"buy_tag":null,"open_timestamp":1516705500000.0,"close_timestamp":1516723500000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.417475728155342,"open_date":"2018-01-23 14:55:00+00:00","close_date":"2018-01-23 15:35:00+00:00","open_rate":5.15e-05,"close_rate":5.175814536340851e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.5814536340851513e-07,"exit_reason":"roi","initial_stop_loss_abs":4.635e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.635e-05,"stop_loss_ratio":0.1,"min_rate":5.15e-05,"max_rate":5.175814536340851e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516719300000.0,"close_timestamp":1516721700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011023294646713328,"open_date":"2018-01-23 16:35:00+00:00","close_date":"2018-01-24 00:05:00+00:00","open_rate":0.09071698,"close_rate":0.09117170170426064,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":450,"profit_ratio":0.0,"profit_abs":0.00045472170426064107,"exit_reason":"roi","initial_stop_loss_abs":0.081645282,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.081645282,"stop_loss_ratio":0.1,"min_rate":0.09071698,"max_rate":0.09117170170426064,"is_open":false,"buy_tag":null,"open_timestamp":1516725300000.0,"close_timestamp":1516752300000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":31.969309462915604,"open_date":"2018-01-23 17:25:00+00:00","close_date":"2018-01-23 18:45:00+00:00","open_rate":3.128e-05,"close_rate":3.1436791979949865e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.0,"profit_abs":1.5679197994986587e-07,"exit_reason":"roi","initial_stop_loss_abs":2.8152e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.8152e-05,"stop_loss_ratio":0.1,"min_rate":3.128e-05,"max_rate":3.1436791979949865e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516728300000.0,"close_timestamp":1516733100000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.465724751439037,"open_date":"2018-01-23 20:15:00+00:00","close_date":"2018-01-23 22:00:00+00:00","open_rate":9.555e-05,"close_rate":9.602894736842104e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":105,"profit_ratio":-0.0,"profit_abs":4.789473684210343e-07,"exit_reason":"roi","initial_stop_loss_abs":8.5995e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.5995e-05,"stop_loss_ratio":0.1,"min_rate":9.555e-05,"max_rate":9.602894736842104e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516738500000.0,"close_timestamp":1516744800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02450979791426522,"open_date":"2018-01-23 22:30:00+00:00","close_date":"2018-01-23 23:10:00+00:00","open_rate":0.04080001,"close_rate":0.0410045213283208,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00020451132832080554,"exit_reason":"roi","initial_stop_loss_abs":0.036720009,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036720009,"stop_loss_ratio":0.1,"min_rate":0.04080001,"max_rate":0.0410045213283208,"is_open":false,"buy_tag":null,"open_timestamp":1516746600000.0,"close_timestamp":1516749000000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.368584156498162,"open_date":"2018-01-23 23:50:00+00:00","close_date":"2018-01-24 03:35:00+00:00","open_rate":5.163e-05,"close_rate":5.18887969924812e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":225,"profit_ratio":-0.0,"profit_abs":2.587969924812037e-07,"exit_reason":"roi","initial_stop_loss_abs":4.6467e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6467e-05,"stop_loss_ratio":0.1,"min_rate":5.163e-05,"max_rate":5.18887969924812e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516751400000.0,"close_timestamp":1516764900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024747691102289384,"open_date":"2018-01-24 00:20:00+00:00","close_date":"2018-01-24 01:50:00+00:00","open_rate":0.04040781,"close_rate":0.04061035541353383,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":90,"profit_ratio":0.0,"profit_abs":0.0002025454135338306,"exit_reason":"roi","initial_stop_loss_abs":0.036367029,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036367029,"stop_loss_ratio":0.1,"min_rate":0.04040781,"max_rate":0.04061035541353383,"is_open":false,"buy_tag":null,"open_timestamp":1516753200000.0,"close_timestamp":1516758600000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.485580670303975,"open_date":"2018-01-24 06:45:00+00:00","close_date":"2018-01-24 07:25:00+00:00","open_rate":5.132e-05,"close_rate":5.157724310776942e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.5724310776941724e-07,"exit_reason":"roi","initial_stop_loss_abs":4.6188000000000006e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6188000000000006e-05,"stop_loss_ratio":0.1,"min_rate":5.132e-05,"max_rate":5.157724310776942e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516776300000.0,"close_timestamp":1516778700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.23816852635629,"open_date":"2018-01-24 14:15:00+00:00","close_date":"2018-01-24 14:25:00+00:00","open_rate":5.198e-05,"close_rate":5.432496240601503e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":10,"profit_ratio":0.03990025,"profit_abs":2.344962406015033e-06,"exit_reason":"roi","initial_stop_loss_abs":4.6782e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6782e-05,"stop_loss_ratio":0.1,"min_rate":5.198e-05,"max_rate":5.432496240601503e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516803300000.0,"close_timestamp":1516803900000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":32.74394237066143,"open_date":"2018-01-24 14:50:00+00:00","close_date":"2018-01-24 16:35:00+00:00","open_rate":3.054e-05,"close_rate":3.069308270676692e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":105,"profit_ratio":-0.0,"profit_abs":1.5308270676691466e-07,"exit_reason":"roi","initial_stop_loss_abs":2.7486000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7486000000000004e-05,"stop_loss_ratio":0.1,"min_rate":3.054e-05,"max_rate":3.069308270676692e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516805400000.0,"close_timestamp":1516811700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.795638562020944,"open_date":"2018-01-24 15:10:00+00:00","close_date":"2018-01-24 16:15:00+00:00","open_rate":9.263e-05,"close_rate":9.309431077694236e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":65,"profit_ratio":0.0,"profit_abs":4.6431077694236234e-07,"exit_reason":"roi","initial_stop_loss_abs":8.3367e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.3367e-05,"stop_loss_ratio":0.1,"min_rate":9.263e-05,"max_rate":9.309431077694236e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516806600000.0,"close_timestamp":1516810500000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.13565469713457,"open_date":"2018-01-24 22:40:00+00:00","close_date":"2018-01-24 23:25:00+00:00","open_rate":5.514e-05,"close_rate":5.54163909774436e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":2.7639097744360576e-07,"exit_reason":"roi","initial_stop_loss_abs":4.9625999999999995e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.9625999999999995e-05,"stop_loss_ratio":0.1,"min_rate":5.514e-05,"max_rate":5.54163909774436e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516833600000.0,"close_timestamp":1516836300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":20.3210729526519,"open_date":"2018-01-25 00:50:00+00:00","close_date":"2018-01-25 01:30:00+00:00","open_rate":4.921e-05,"close_rate":4.9456666666666664e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":2.4666666666666543e-07,"exit_reason":"roi","initial_stop_loss_abs":4.4289e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4289e-05,"stop_loss_ratio":0.1,"min_rate":4.921e-05,"max_rate":4.9456666666666664e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516841400000.0,"close_timestamp":1516843800000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38461538461538464,"open_date":"2018-01-25 08:15:00+00:00","close_date":"2018-01-25 12:15:00+00:00","open_rate":0.0026,"close_rate":0.002613032581453634,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":240,"profit_ratio":0.0,"profit_abs":1.3032581453634e-05,"exit_reason":"roi","initial_stop_loss_abs":0.00234,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.00234,"stop_loss_ratio":0.1,"min_rate":0.0026,"max_rate":0.002613032581453634,"is_open":false,"buy_tag":null,"open_timestamp":1516868100000.0,"close_timestamp":1516882500000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03571593119825878,"open_date":"2018-01-25 10:25:00+00:00","close_date":"2018-01-25 16:15:00+00:00","open_rate":0.02799871,"close_rate":0.028139054411027563,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":350,"profit_ratio":-0.0,"profit_abs":0.00014034441102756326,"exit_reason":"roi","initial_stop_loss_abs":0.025198839,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025198839,"stop_loss_ratio":0.1,"min_rate":0.02799871,"max_rate":0.028139054411027563,"is_open":false,"buy_tag":null,"open_timestamp":1516875900000.0,"close_timestamp":1516896900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024516401717913302,"open_date":"2018-01-25 11:00:00+00:00","close_date":"2018-01-25 11:45:00+00:00","open_rate":0.04078902,"close_rate":0.0409934762406015,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":0.00020445624060149575,"exit_reason":"roi","initial_stop_loss_abs":0.036710118,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036710118,"stop_loss_ratio":0.1,"min_rate":0.04078902,"max_rate":0.0409934762406015,"is_open":false,"buy_tag":null,"open_timestamp":1516878000000.0,"close_timestamp":1516880700000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":34.602076124567475,"open_date":"2018-01-25 13:05:00+00:00","close_date":"2018-01-25 13:45:00+00:00","open_rate":2.89e-05,"close_rate":2.904486215538847e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.4486215538846723e-07,"exit_reason":"roi","initial_stop_loss_abs":2.601e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.601e-05,"stop_loss_ratio":0.1,"min_rate":2.89e-05,"max_rate":2.904486215538847e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516885500000.0,"close_timestamp":1516887900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02432912439481303,"open_date":"2018-01-25 13:20:00+00:00","close_date":"2018-01-25 14:05:00+00:00","open_rate":0.041103,"close_rate":0.04130903007518797,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":0.00020603007518796984,"exit_reason":"roi","initial_stop_loss_abs":0.0369927,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0369927,"stop_loss_ratio":0.1,"min_rate":0.041103,"max_rate":0.04130903007518797,"is_open":false,"buy_tag":null,"open_timestamp":1516886400000.0,"close_timestamp":1516889100000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":18.422991893883566,"open_date":"2018-01-25 15:45:00+00:00","close_date":"2018-01-25 16:15:00+00:00","open_rate":5.428e-05,"close_rate":5.509624060150376e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":8.162406015037611e-07,"exit_reason":"roi","initial_stop_loss_abs":4.8852000000000006e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.8852000000000006e-05,"stop_loss_ratio":0.1,"min_rate":5.428e-05,"max_rate":5.509624060150376e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516895100000.0,"close_timestamp":1516896900000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":18.47063169560399,"open_date":"2018-01-25 17:45:00+00:00","close_date":"2018-01-25 23:15:00+00:00","open_rate":5.414e-05,"close_rate":5.441137844611528e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":330,"profit_ratio":-0.0,"profit_abs":2.713784461152774e-07,"exit_reason":"roi","initial_stop_loss_abs":4.8726e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.8726e-05,"stop_loss_ratio":0.1,"min_rate":5.414e-05,"max_rate":5.441137844611528e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516902300000.0,"close_timestamp":1516922100000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024150056861308878,"open_date":"2018-01-25 21:15:00+00:00","close_date":"2018-01-25 21:55:00+00:00","open_rate":0.04140777,"close_rate":0.0416153277443609,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0002075577443608964,"exit_reason":"roi","initial_stop_loss_abs":0.037266993000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.037266993000000005,"stop_loss_ratio":0.1,"min_rate":0.04140777,"max_rate":0.0416153277443609,"is_open":false,"buy_tag":null,"open_timestamp":1516914900000.0,"close_timestamp":1516917300000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3932224183965176,"open_date":"2018-01-26 02:05:00+00:00","close_date":"2018-01-26 02:45:00+00:00","open_rate":0.00254309,"close_rate":0.002555837318295739,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":1.2747318295739177e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002288781,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002288781,"stop_loss_ratio":0.1,"min_rate":0.00254309,"max_rate":0.002555837318295739,"is_open":false,"buy_tag":null,"open_timestamp":1516932300000.0,"close_timestamp":1516934700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.834849295523455,"open_date":"2018-01-26 02:55:00+00:00","close_date":"2018-01-26 15:10:00+00:00","open_rate":5.607e-05,"close_rate":5.6351052631578935e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":735,"profit_ratio":-0.0,"profit_abs":2.810526315789381e-07,"exit_reason":"roi","initial_stop_loss_abs":5.0463e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0463e-05,"stop_loss_ratio":0.1,"min_rate":5.607e-05,"max_rate":5.6351052631578935e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516935300000.0,"close_timestamp":1516979400000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.39400171784748983,"open_date":"2018-01-26 06:10:00+00:00","close_date":"2018-01-26 09:25:00+00:00","open_rate":0.00253806,"close_rate":0.0025507821052631577,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":195,"profit_ratio":0.0,"profit_abs":1.2722105263157733e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002284254,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002284254,"stop_loss_ratio":0.1,"min_rate":0.00253806,"max_rate":0.0025507821052631577,"is_open":false,"buy_tag":null,"open_timestamp":1516947000000.0,"close_timestamp":1516958700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024096385542168672,"open_date":"2018-01-26 07:25:00+00:00","close_date":"2018-01-26 09:55:00+00:00","open_rate":0.0415,"close_rate":0.04170802005012531,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":150,"profit_ratio":-0.0,"profit_abs":0.00020802005012530989,"exit_reason":"roi","initial_stop_loss_abs":0.03735,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.03735,"stop_loss_ratio":0.1,"min_rate":0.0415,"max_rate":0.04170802005012531,"is_open":false,"buy_tag":null,"open_timestamp":1516951500000.0,"close_timestamp":1516960500000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":18.793459875963165,"open_date":"2018-01-26 09:55:00+00:00","close_date":"2018-01-26 10:25:00+00:00","open_rate":5.321e-05,"close_rate":5.401015037593984e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":8.00150375939842e-07,"exit_reason":"roi","initial_stop_loss_abs":4.7889e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7889e-05,"stop_loss_ratio":0.1,"min_rate":5.321e-05,"max_rate":5.401015037593984e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516960500000.0,"close_timestamp":1516962300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.036074437437185386,"open_date":"2018-01-26 16:05:00+00:00","close_date":"2018-01-26 16:45:00+00:00","open_rate":0.02772046,"close_rate":0.02785940967418546,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00013894967418546025,"exit_reason":"roi","initial_stop_loss_abs":0.024948414,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.024948414,"stop_loss_ratio":0.1,"min_rate":0.02772046,"max_rate":0.02785940967418546,"is_open":false,"buy_tag":null,"open_timestamp":1516982700000.0,"close_timestamp":1516985100000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010569326272036914,"open_date":"2018-01-26 23:35:00+00:00","close_date":"2018-01-27 00:15:00+00:00","open_rate":0.09461341,"close_rate":0.09508766268170424,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.00047425268170424306,"exit_reason":"roi","initial_stop_loss_abs":0.085152069,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.085152069,"stop_loss_ratio":0.1,"min_rate":0.09461341,"max_rate":0.09508766268170424,"is_open":false,"buy_tag":null,"open_timestamp":1517009700000.0,"close_timestamp":1517012100000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":17.809439002671414,"open_date":"2018-01-27 00:35:00+00:00","close_date":"2018-01-27 01:30:00+00:00","open_rate":5.615e-05,"close_rate":5.643145363408521e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.814536340852038e-07,"exit_reason":"roi","initial_stop_loss_abs":5.0535e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0535e-05,"stop_loss_ratio":0.1,"min_rate":5.615e-05,"max_rate":5.643145363408521e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517013300000.0,"close_timestamp":1517016600000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.998560115190784,"open_date":"2018-01-27 00:45:00+00:00","close_date":"2018-01-30 04:45:00+00:00","open_rate":5.556e-05,"close_rate":5.144e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":4560,"profit_ratio":-0.07877175,"profit_abs":-4.120000000000001e-06,"exit_reason":"force_exit","initial_stop_loss_abs":5.0004000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0004000000000004e-05,"stop_loss_ratio":0.1,"min_rate":5.144e-05,"max_rate":5.556e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517013900000.0,"close_timestamp":1517287500000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014492751522789634,"open_date":"2018-01-27 02:30:00+00:00","close_date":"2018-01-27 11:25:00+00:00","open_rate":0.06900001,"close_rate":0.06934587471177944,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":535,"profit_ratio":-0.0,"profit_abs":0.0003458647117794422,"exit_reason":"roi","initial_stop_loss_abs":0.062100009000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.062100009000000005,"stop_loss_ratio":0.1,"min_rate":0.06900001,"max_rate":0.06934587471177944,"is_open":false,"buy_tag":null,"open_timestamp":1517020200000.0,"close_timestamp":1517052300000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010582027378879437,"open_date":"2018-01-27 06:25:00+00:00","close_date":"2018-01-27 07:05:00+00:00","open_rate":0.09449985,"close_rate":0.0949735334586466,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004736834586466093,"exit_reason":"roi","initial_stop_loss_abs":0.085049865,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.085049865,"stop_loss_ratio":0.1,"min_rate":0.09449985,"max_rate":0.0949735334586466,"is_open":false,"buy_tag":null,"open_timestamp":1517034300000.0,"close_timestamp":1517036700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02434885085598385,"open_date":"2018-01-27 09:40:00+00:00","close_date":"2018-01-30 04:40:00+00:00","open_rate":0.0410697,"close_rate":0.03928809,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":4020,"profit_ratio":-0.04815133,"profit_abs":-0.001781610000000003,"exit_reason":"force_exit","initial_stop_loss_abs":0.03696273,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.03696273,"stop_loss_ratio":0.1,"min_rate":0.03928809,"max_rate":0.0410697,"is_open":false,"buy_tag":null,"open_timestamp":1517046000000.0,"close_timestamp":1517287200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03508771929824561,"open_date":"2018-01-27 11:45:00+00:00","close_date":"2018-01-27 12:30:00+00:00","open_rate":0.0285,"close_rate":0.02864285714285714,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":0.00014285714285713902,"exit_reason":"roi","initial_stop_loss_abs":0.025650000000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025650000000000003,"stop_loss_ratio":0.1,"min_rate":0.0285,"max_rate":0.02864285714285714,"is_open":false,"buy_tag":null,"open_timestamp":1517053500000.0,"close_timestamp":1517056200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.034887307020861215,"open_date":"2018-01-27 12:35:00+00:00","close_date":"2018-01-27 15:25:00+00:00","open_rate":0.02866372,"close_rate":0.02880739779448621,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":170,"profit_ratio":-0.0,"profit_abs":0.00014367779448621124,"exit_reason":"roi","initial_stop_loss_abs":0.025797348,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025797348,"stop_loss_ratio":0.1,"min_rate":0.02866372,"max_rate":0.02880739779448621,"is_open":false,"buy_tag":null,"open_timestamp":1517056500000.0,"close_timestamp":1517066700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010484268355332824,"open_date":"2018-01-27 15:50:00+00:00","close_date":"2018-01-27 16:50:00+00:00","open_rate":0.095381,"close_rate":0.09585910025062656,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.0,"profit_abs":0.00047810025062657024,"exit_reason":"roi","initial_stop_loss_abs":0.0858429,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0858429,"stop_loss_ratio":0.1,"min_rate":0.095381,"max_rate":0.09585910025062656,"is_open":false,"buy_tag":null,"open_timestamp":1517068200000.0,"close_timestamp":1517071800000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014794886650455417,"open_date":"2018-01-27 17:05:00+00:00","close_date":"2018-01-27 17:45:00+00:00","open_rate":0.06759092,"close_rate":0.06792972160401002,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00033880160401002224,"exit_reason":"roi","initial_stop_loss_abs":0.060831828,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060831828,"stop_loss_ratio":0.1,"min_rate":0.06759092,"max_rate":0.06792972160401002,"is_open":false,"buy_tag":null,"open_timestamp":1517072700000.0,"close_timestamp":1517075100000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38684569885609726,"open_date":"2018-01-27 23:40:00+00:00","close_date":"2018-01-28 01:05:00+00:00","open_rate":0.00258501,"close_rate":0.002597967443609022,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":85,"profit_ratio":-0.0,"profit_abs":1.2957443609021985e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002326509,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002326509,"stop_loss_ratio":0.1,"min_rate":0.00258501,"max_rate":0.002597967443609022,"is_open":false,"buy_tag":null,"open_timestamp":1517096400000.0,"close_timestamp":1517101500000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014928710926711672,"open_date":"2018-01-28 02:25:00+00:00","close_date":"2018-01-28 08:10:00+00:00","open_rate":0.06698502,"close_rate":0.0673207845112782,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":345,"profit_ratio":-0.0,"profit_abs":0.00033576451127818874,"exit_reason":"roi","initial_stop_loss_abs":0.060286518000000004,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060286518000000004,"stop_loss_ratio":0.1,"min_rate":0.06698502,"max_rate":0.0673207845112782,"is_open":false,"buy_tag":null,"open_timestamp":1517106300000.0,"close_timestamp":1517127000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014767187899175548,"open_date":"2018-01-28 10:25:00+00:00","close_date":"2018-01-28 16:30:00+00:00","open_rate":0.0677177,"close_rate":0.06805713709273183,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":365,"profit_ratio":-0.0,"profit_abs":0.0003394370927318202,"exit_reason":"roi","initial_stop_loss_abs":0.06094593000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06094593000000001,"stop_loss_ratio":0.1,"min_rate":0.0677177,"max_rate":0.06805713709273183,"is_open":false,"buy_tag":null,"open_timestamp":1517135100000.0,"close_timestamp":1517157000000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":19.175455417066157,"open_date":"2018-01-28 20:35:00+00:00","close_date":"2018-01-28 21:35:00+00:00","open_rate":5.215e-05,"close_rate":5.2411403508771925e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":0.0,"profit_abs":2.6140350877192417e-07,"exit_reason":"roi","initial_stop_loss_abs":4.6935000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6935000000000004e-05,"stop_loss_ratio":0.1,"min_rate":5.215e-05,"max_rate":5.2411403508771925e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517171700000.0,"close_timestamp":1517175300000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.36521808998243305,"open_date":"2018-01-28 22:00:00+00:00","close_date":"2018-01-28 22:30:00+00:00","open_rate":0.00273809,"close_rate":0.002779264285714285,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.117428571428529e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002464281,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002464281,"stop_loss_ratio":0.1,"min_rate":0.00273809,"max_rate":0.002779264285714285,"is_open":false,"buy_tag":null,"open_timestamp":1517176800000.0,"close_timestamp":1517178600000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3641236272539253,"open_date":"2018-01-29 00:00:00+00:00","close_date":"2018-01-29 00:30:00+00:00","open_rate":0.00274632,"close_rate":0.002787618045112782,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.129804511278194e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002471688,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002471688,"stop_loss_ratio":0.1,"min_rate":0.00274632,"max_rate":0.002787618045112782,"is_open":false,"buy_tag":null,"open_timestamp":1517184000000.0,"close_timestamp":1517185800000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.061634117689115045,"open_date":"2018-01-29 02:15:00+00:00","close_date":"2018-01-29 03:00:00+00:00","open_rate":0.01622478,"close_rate":0.016306107218045113,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":0.0,"profit_abs":8.132721804511231e-05,"exit_reason":"roi","initial_stop_loss_abs":0.014602302000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014602302000000001,"stop_loss_ratio":0.1,"min_rate":0.01622478,"max_rate":0.016306107218045113,"is_open":false,"buy_tag":null,"open_timestamp":1517192100000.0,"close_timestamp":1517194800000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014492753623188404,"open_date":"2018-01-29 03:05:00+00:00","close_date":"2018-01-29 03:45:00+00:00","open_rate":0.069,"close_rate":0.06934586466165413,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00034586466165412166,"exit_reason":"roi","initial_stop_loss_abs":0.06210000000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06210000000000001,"stop_loss_ratio":0.1,"min_rate":0.069,"max_rate":0.06934586466165413,"is_open":false,"buy_tag":null,"open_timestamp":1517195100000.0,"close_timestamp":1517197500000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.42204454597373,"open_date":"2018-01-29 05:20:00+00:00","close_date":"2018-01-29 06:55:00+00:00","open_rate":8.755e-05,"close_rate":8.798884711779448e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":95,"profit_ratio":-0.0,"profit_abs":4.3884711779447504e-07,"exit_reason":"roi","initial_stop_loss_abs":7.879500000000001e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":7.879500000000001e-05,"stop_loss_ratio":0.1,"min_rate":8.755e-05,"max_rate":8.798884711779448e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517203200000.0,"close_timestamp":1517208900000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014650376815016871,"open_date":"2018-01-29 07:00:00+00:00","close_date":"2018-01-29 19:25:00+00:00","open_rate":0.06825763,"close_rate":0.06859977350877192,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":745,"profit_ratio":-0.0,"profit_abs":0.00034214350877191657,"exit_reason":"roi","initial_stop_loss_abs":0.061431867,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.061431867,"stop_loss_ratio":0.1,"min_rate":0.06825763,"max_rate":0.06859977350877192,"is_open":false,"buy_tag":null,"open_timestamp":1517209200000.0,"close_timestamp":1517253900000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014894490408841846,"open_date":"2018-01-29 19:45:00+00:00","close_date":"2018-01-29 20:25:00+00:00","open_rate":0.06713892,"close_rate":0.06747545593984962,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0003365359398496137,"exit_reason":"roi","initial_stop_loss_abs":0.060425028000000006,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060425028000000006,"stop_loss_ratio":0.1,"min_rate":0.06713892,"max_rate":0.06747545593984962,"is_open":false,"buy_tag":null,"open_timestamp":1517255100000.0,"close_timestamp":1517257500000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.193194537721066,"open_date":"2018-01-29 23:30:00+00:00","close_date":"2018-01-30 04:45:00+00:00","open_rate":8.934e-05,"close_rate":8.8e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":315,"profit_ratio":-0.0199116,"profit_abs":-1.3399999999999973e-06,"exit_reason":"force_exit","initial_stop_loss_abs":8.0406e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.0406e-05,"stop_loss_ratio":0.1,"min_rate":8.8e-05,"max_rate":8.934e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517268600000.0,"close_timestamp":1517287500000.0}],"locks":[],"best_pair":{"key":"LTC/BTC","trades":8,"profit_mean":0.00748129625,"profit_mean_pct":0.748129625,"profit_sum":0.05985037,"profit_sum_pct":5.99,"profit_total_abs":0.0015944746365914707,"profit_total":0.15944746365914708,"profit_total_pct":15.94,"duration_avg":"1:59:00","wins":8,"draws":0,"losses":0},"worst_pair":{"key":"XMR/BTC","trades":16,"profit_mean":-0.0027899012500000007,"profit_mean_pct":-0.2789901250000001,"profit_sum":-0.04463842000000001,"profit_sum_pct":-4.46,"profit_total_abs":0.0006671885263157366,"profit_total":0.06671885263157366,"profit_total_pct":6.67,"duration_avg":"8:41:00","wins":15,"draws":0,"losses":1},"results_per_pair":[{"key":"ETH/BTC","trades":21,"profit_mean":0.0009500057142857142,"profit_mean_pct":0.09500057142857142,"profit_sum":0.01995012,"profit_sum_pct":2.0,"profit_total_abs":0.011505731278195264,"profit_total":1.1505731278195264,"profit_total_pct":115.06,"duration_avg":"2:17:00","wins":21,"draws":0,"losses":0},{"key":"DASH/BTC","trades":16,"profit_mean":0.0018703237499999997,"profit_mean_pct":0.18703237499999997,"profit_sum":0.029925179999999996,"profit_sum_pct":2.99,"profit_total_abs":0.007475052681704161,"profit_total":0.7475052681704161,"profit_total_pct":74.75,"duration_avg":"3:03:00","wins":16,"draws":0,"losses":0},{"key":"ZEC/BTC","trades":21,"profit_mean":-0.00039290904761904774,"profit_mean_pct":-0.03929090476190478,"profit_sum":-0.008251090000000003,"profit_sum_pct":-0.83,"profit_total_abs":0.004452605639097655,"profit_total":0.4452605639097655,"profit_total_pct":44.53,"duration_avg":"4:17:00","wins":20,"draws":0,"losses":1},{"key":"LTC/BTC","trades":8,"profit_mean":0.00748129625,"profit_mean_pct":0.748129625,"profit_sum":0.05985037,"profit_sum_pct":5.99,"profit_total_abs":0.0015944746365914707,"profit_total":0.15944746365914708,"profit_total_pct":15.94,"duration_avg":"1:59:00","wins":8,"draws":0,"losses":0},{"key":"XMR/BTC","trades":16,"profit_mean":-0.0027899012500000007,"profit_mean_pct":-0.2789901250000001,"profit_sum":-0.04463842000000001,"profit_sum_pct":-4.46,"profit_total_abs":0.0006671885263157366,"profit_total":0.06671885263157366,"profit_total_pct":6.67,"duration_avg":"8:41:00","wins":15,"draws":0,"losses":1},{"key":"ETC/BTC","trades":20,"profit_mean":0.0022568569999999997,"profit_mean_pct":0.22568569999999996,"profit_sum":0.04513713999999999,"profit_sum_pct":4.51,"profit_total_abs":0.00036538235338345404,"profit_total":0.0365382353383454,"profit_total_pct":3.65,"duration_avg":"1:45:00","wins":19,"draws":0,"losses":1},{"key":"TRX/BTC","trades":15,"profit_mean":0.0023467073333333323,"profit_mean_pct":0.23467073333333321,"profit_sum":0.035200609999999986,"profit_sum_pct":3.52,"profit_total_abs":1.1329523809523682e-05,"profit_total":0.0011329523809523682,"profit_total_pct":0.11,"duration_avg":"2:28:00","wins":13,"draws":0,"losses":2},{"key":"XLM/BTC","trades":21,"profit_mean":0.0026243899999999994,"profit_mean_pct":0.2624389999999999,"profit_sum":0.05511218999999999,"profit_sum_pct":5.51,"profit_total_abs":7.340779448621465e-06,"profit_total":0.0007340779448621465,"profit_total_pct":0.07,"duration_avg":"3:21:00","wins":20,"draws":0,"losses":1},{"key":"ADA/BTC","trades":29,"profit_mean":-0.0011598141379310352,"profit_mean_pct":-0.11598141379310352,"profit_sum":-0.03363461000000002,"profit_sum_pct":-3.36,"profit_total_abs":4.916634085212862e-06,"profit_total":0.0004916634085212862,"profit_total_pct":0.05,"duration_avg":"5:35:00","wins":27,"draws":0,"losses":2},{"key":"NXT/BTC","trades":12,"profit_mean":-0.0012261025000000006,"profit_mean_pct":-0.12261025000000006,"profit_sum":-0.014713230000000008,"profit_sum_pct":-1.47,"profit_total_abs":1.4774411027568458e-06,"profit_total":0.00014774411027568458,"profit_total_pct":0.01,"duration_avg":"0:57:00","wins":11,"draws":0,"losses":1},{"key":"TOTAL","trades":179,"profit_mean":0.0008041243575418989,"profit_mean_pct":0.0804124357541899,"profit_sum":0.1439382599999999,"profit_sum_pct":14.39,"profit_total_abs":0.026085499493733857,"profit_total":2.6085499493733857,"profit_total_pct":260.85,"duration_avg":"3:40:00","wins":170,"draws":0,"losses":9}],"results_per_enter_tag":[{"key":"TOTAL","trades":179,"profit_mean":0.0008041243575418989,"profit_mean_pct":0.0804124357541899,"profit_sum":0.1439382599999999,"profit_sum_pct":14.39,"profit_total_abs":0.026085499493733857,"profit_total":2.6085499493733857,"profit_total_pct":260.85,"duration_avg":"3:40:00","wins":170,"draws":0,"losses":9}],"exit_reason_summary":[{"exit_reason":"roi","trades":170,"wins":170,"draws":0,"losses":0,"profit_mean":0.005398268352941177,"profit_mean_pct":0.54,"profit_sum":0.91770562,"profit_sum_pct":91.77,"profit_total_abs":0.031232837493733862,"profit_total":0.30590187333333335,"profit_total_pct":30.59},{"exit_reason":"stop_loss","trades":6,"wins":0,"draws":0,"losses":6,"profit_mean":-0.10448878000000002,"profit_mean_pct":-10.45,"profit_sum":-0.6269326800000001,"profit_sum_pct":-62.69,"profit_total_abs":-0.0033602680000000026,"profit_total":-0.20897756000000003,"profit_total_pct":-20.9},{"exit_reason":"force_exit","trades":3,"wins":0,"draws":0,"losses":3,"profit_mean":-0.04894489333333333,"profit_mean_pct":-4.89,"profit_sum":-0.14683468,"profit_sum_pct":-14.68,"profit_total_abs":-0.001787070000000003,"profit_total":-0.04894489333333333,"profit_total_pct":-4.89}],"left_open_trades":[{"key":"TOTAL","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0}],"total_trades":179,"total_volume":0.17900000000000005,"avg_stake_amount":0.0010000000000000002,"profit_mean":0.0008041243575418989,"profit_median":0.0,"profit_total":2.6085499493733857,"profit_total_abs":0.026085499493733857,"backtest_start":"2018-01-10 07:15:00","backtest_start_ts":1515568500000,"backtest_end":"2018-01-30 04:45:00","backtest_end_ts":1517287500000,"backtest_days":19,"backtest_run_start_ts":"2020-10-01 18:00:00+00:00","backtest_run_end_ts":"2020-10-01 18:01:00+00:00","trades_per_day":9.42,"market_change":1.22,"pairlist":[],"stake_amount":0.001,"stake_currency":"BTC","stake_currency_decimals":8,"starting_balance":0.01,"dry_run_wallet":0.01,"final_balance":0.03608549949373386,"rejected_signals":0,"max_open_trades":3,"max_open_trades_setting":3,"timeframe":"5m","timeframe_detail":"","timerange":"","enable_protections":false,"strategy_name":"StrategyTestV2","stoploss":0.1,"trailing_stop":false,"trailing_stop_positive":null,"trailing_stop_positive_offset":0.0,"trailing_only_offset_is_reached":false,"use_custom_stoploss":false,"minimal_roi":{},"use_exit_signal":true,"exit_profit_only":false,"exit_profit_offset":false,"ignore_roi_if_entry_signal":false,"backtest_best_day":0.17955111999999998,"backtest_worst_day":-0.14683468,"backtest_best_day_abs":0.0071570099,"backtest_worst_day_abs":-0.0023093218,"winning_days":19,"draw_days":0,"losing_days":2,"daily_profit":[["2018-01-10",0.0025815306],["2018-01-11",0.0049356655],["2018-01-12",0.0006395218],["2018-01-13",0.0002574589],["2018-01-14",0.0010443828],["2018-01-15",0.0024030209],["2018-01-16",0.0071570099],["2018-01-17",0.001137038],["2018-01-18",0.0013712174],["2018-01-19",0.000584673],["2018-01-20",0.0006143386],["2018-01-21",0.0004749361],["2018-01-22",9.91669e-05],["2018-01-23",0.0015726664],["2018-01-24",0.0006610219],["2018-01-25",-0.0023093218],["2018-01-26",0.0003735204],["2018-01-27",0.0023975191],["2018-01-28",0.0007295947],["2018-01-29",0.0011476082],["2018-01-30",-0.00178707]],"wins":48,"losses":9,"draws":122,"holding_avg":"3:40:00","holding_avg_s":13200.0,"winner_holding_avg":"0:24:00","winner_holding_avg_s":1440.0,"loser_holding_avg":"1 day, 5:57:00","loser_holding_avg_s":107820.0,"max_drawdown":0.21142322000000008,"max_drawdown_account":0.08674033488183289,"max_drawdown_abs":0.0030822220000000025,"drawdown_start":"2018-01-25 01:30:00","drawdown_start_ts":1516843800000.0,"drawdown_end":"2018-01-25 03:50:00","drawdown_end_ts":1516852200000.0,"max_drawdown_low":0.02245167355388436,"max_drawdown_high":0.025533895553884363,"csum_min":0.01000434887218045,"csum_max":0.03608683949373386}},"strategy_comparison":[{"key":"StrategyTestV2","trades":179,"profit_mean":0.0008041243575418989,"profit_mean_pct":0.0804124357541899,"profit_sum":0.1439382599999999,"profit_sum_pct":14.39,"profit_total_abs":0.026085499493733857,"profit_total":2.6085499493733857,"profit_total_pct":260.85,"duration_avg":"3:40:00","wins":170,"draws":0,"losses":9,"max_drawdown_account":0.08674033488183289,"max_drawdown_abs":"0.00308222"},{"key":"TestStrategy","trades":179,"profit_mean":0.0008041243575418989,"profit_mean_pct":0.0804124357541899,"profit_sum":0.1439382599999999,"profit_sum_pct":14.39,"profit_total_abs":0.026085499493733857,"profit_total":2.6085499493733857,"profit_total_pct":260.85,"duration_avg":"3:40:00","wins":170,"draws":0,"losses":9,"max_drawdown_account":0.08674033488183289,"max_drawdown_abs":"0.00308222"}]} 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 + } +} diff --git a/tests/testdata/backtest-result_new.json b/tests/testdata/backtest_results/backtest-result_new.json similarity index 87% rename from tests/testdata/backtest-result_new.json rename to tests/testdata/backtest_results/backtest-result_new.json index 1d72cd479..03fdb455a 100644 --- a/tests/testdata/backtest-result_new.json +++ b/tests/testdata/backtest_results/backtest-result_new.json @@ -1 +1 @@ -{"strategy":{"StrategyTestV3":{"trades":[{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.37344398340249,"open_date":"2018-01-10 07:15:00+00:00","close_date":"2018-01-10 07:20:00+00:00","open_rate":9.64e-05,"close_rate":0.00010074887218045112,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":4.348872180451118e-06,"sell_reason":"roi","initial_stop_loss_abs":8.676e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.676e-05,"stop_loss_ratio":0.1,"min_rate":9.64e-05,"max_rate":0.00010074887218045112,"is_open":false,"buy_tag":null,"open_timestamp":1515568500000.0,"close_timestamp":1515568800000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":21.026072329688816,"open_date":"2018-01-10 07:15:00+00:00","close_date":"2018-01-10 07:30:00+00:00","open_rate":4.756e-05,"close_rate":4.9705563909774425e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":15,"profit_ratio":0.03990025,"profit_abs":2.1455639097744267e-06,"sell_reason":"roi","initial_stop_loss_abs":4.2804e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.2804e-05,"stop_loss_ratio":0.1,"min_rate":4.756e-05,"max_rate":4.9705563909774425e-05,"is_open":false,"buy_tag":"buy_tag","open_timestamp":1515568500000.0,"close_timestamp":1515569400000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":29.94908655286014,"open_date":"2018-01-10 07:25:00+00:00","close_date":"2018-01-10 07:35:00+00:00","open_rate":3.339e-05,"close_rate":3.489631578947368e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":10,"profit_ratio":0.03990025,"profit_abs":1.506315789473681e-06,"sell_reason":"roi","initial_stop_loss_abs":3.0050999999999997e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.0050999999999997e-05,"stop_loss_ratio":0.1,"min_rate":3.339e-05,"max_rate":3.489631578947368e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515569100000.0,"close_timestamp":1515569700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.313531353135314,"open_date":"2018-01-10 07:25:00+00:00","close_date":"2018-01-10 07:40:00+00:00","open_rate":9.696e-05,"close_rate":0.00010133413533834584,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":15,"profit_ratio":0.03990025,"profit_abs":4.3741353383458455e-06,"sell_reason":"roi","initial_stop_loss_abs":8.7264e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.7264e-05,"stop_loss_ratio":0.1,"min_rate":9.696e-05,"max_rate":0.00010133413533834584,"is_open":false,"buy_tag":null,"open_timestamp":1515569100000.0,"close_timestamp":1515570000000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010604453870625663,"open_date":"2018-01-10 07:35:00+00:00","close_date":"2018-01-10 08:35:00+00:00","open_rate":0.0943,"close_rate":0.09477268170426063,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.0,"profit_abs":0.0004726817042606385,"sell_reason":"roi","initial_stop_loss_abs":0.08487,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08487,"stop_loss_ratio":0.1,"min_rate":0.0943,"max_rate":0.09477268170426063,"is_open":false,"buy_tag":null,"open_timestamp":1515569700000.0,"close_timestamp":1515573300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03677001860930642,"open_date":"2018-01-10 07:40:00+00:00","close_date":"2018-01-10 08:10:00+00:00","open_rate":0.02719607,"close_rate":0.02760503345864661,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.00040896345864661204,"sell_reason":"roi","initial_stop_loss_abs":0.024476463,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.024476463,"stop_loss_ratio":0.1,"min_rate":0.02719607,"max_rate":0.02760503345864661,"is_open":false,"buy_tag":null,"open_timestamp":1515570000000.0,"close_timestamp":1515571800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.021575196463739,"open_date":"2018-01-10 08:15:00+00:00","close_date":"2018-01-10 09:55:00+00:00","open_rate":0.04634952,"close_rate":0.046581848421052625,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":100,"profit_ratio":0.0,"profit_abs":0.0002323284210526272,"sell_reason":"roi","initial_stop_loss_abs":0.041714568,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.041714568,"stop_loss_ratio":0.1,"min_rate":0.04634952,"max_rate":0.046581848421052625,"is_open":false,"buy_tag":null,"open_timestamp":1515572100000.0,"close_timestamp":1515578100000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":32.615786040443574,"open_date":"2018-01-10 14:45:00+00:00","close_date":"2018-01-10 15:50:00+00:00","open_rate":3.066e-05,"close_rate":3.081368421052631e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":65,"profit_ratio":-0.0,"profit_abs":1.5368421052630647e-07,"sell_reason":"roi","initial_stop_loss_abs":2.7594e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7594e-05,"stop_loss_ratio":0.1,"min_rate":3.066e-05,"max_rate":3.081368421052631e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515595500000.0,"close_timestamp":1515599400000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.05917194776300452,"open_date":"2018-01-10 16:35:00+00:00","close_date":"2018-01-10 17:15:00+00:00","open_rate":0.0168999,"close_rate":0.016984611278195488,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":8.471127819548868e-05,"sell_reason":"roi","initial_stop_loss_abs":0.01520991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.01520991,"stop_loss_ratio":0.1,"min_rate":0.0168999,"max_rate":0.016984611278195488,"is_open":false,"buy_tag":null,"open_timestamp":1515602100000.0,"close_timestamp":1515604500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010949822656672253,"open_date":"2018-01-10 16:40:00+00:00","close_date":"2018-01-10 17:20:00+00:00","open_rate":0.09132568,"close_rate":0.0917834528320802,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004577728320801916,"sell_reason":"roi","initial_stop_loss_abs":0.08219311200000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08219311200000001,"stop_loss_ratio":0.1,"min_rate":0.09132568,"max_rate":0.0917834528320802,"is_open":false,"buy_tag":null,"open_timestamp":1515602400000.0,"close_timestamp":1515604800000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011238476768326556,"open_date":"2018-01-10 18:50:00+00:00","close_date":"2018-01-10 19:45:00+00:00","open_rate":0.08898003,"close_rate":0.08942604518796991,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":0.00044601518796991146,"sell_reason":"roi","initial_stop_loss_abs":0.080082027,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.080082027,"stop_loss_ratio":0.1,"min_rate":0.08898003,"max_rate":0.08942604518796991,"is_open":false,"buy_tag":null,"open_timestamp":1515610200000.0,"close_timestamp":1515613500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011682232072680307,"open_date":"2018-01-10 22:15:00+00:00","close_date":"2018-01-10 23:00:00+00:00","open_rate":0.08560008,"close_rate":0.08602915308270676,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":0.0,"profit_abs":0.00042907308270676014,"sell_reason":"roi","initial_stop_loss_abs":0.077040072,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.077040072,"stop_loss_ratio":0.1,"min_rate":0.08560008,"max_rate":0.08602915308270676,"is_open":false,"buy_tag":null,"open_timestamp":1515622500000.0,"close_timestamp":1515625200000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.4014726015023105,"open_date":"2018-01-10 22:50:00+00:00","close_date":"2018-01-10 23:20:00+00:00","open_rate":0.00249083,"close_rate":0.0025282860902255634,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":3.745609022556351e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002241747,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002241747,"stop_loss_ratio":0.1,"min_rate":0.00249083,"max_rate":0.0025282860902255634,"is_open":false,"buy_tag":null,"open_timestamp":1515624600000.0,"close_timestamp":1515626400000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":33.090668431502316,"open_date":"2018-01-10 23:15:00+00:00","close_date":"2018-01-11 00:15:00+00:00","open_rate":3.022e-05,"close_rate":3.037147869674185e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.0,"profit_abs":1.5147869674185174e-07,"sell_reason":"roi","initial_stop_loss_abs":2.7198e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7198e-05,"stop_loss_ratio":0.1,"min_rate":3.022e-05,"max_rate":3.037147869674185e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515626100000.0,"close_timestamp":1515629700000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.41034058268362744,"open_date":"2018-01-10 23:40:00+00:00","close_date":"2018-01-11 00:05:00+00:00","open_rate":0.002437,"close_rate":0.0024980776942355883,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":6.107769423558838e-05,"sell_reason":"roi","initial_stop_loss_abs":0.0021933,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0021933,"stop_loss_ratio":0.1,"min_rate":0.002437,"max_rate":0.0024980776942355883,"is_open":false,"buy_tag":null,"open_timestamp":1515627600000.0,"close_timestamp":1515629100000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02095643931654345,"open_date":"2018-01-11 00:00:00+00:00","close_date":"2018-01-11 00:35:00+00:00","open_rate":0.04771803,"close_rate":0.04843559436090225,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0007175643609022495,"sell_reason":"roi","initial_stop_loss_abs":0.042946227000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.042946227000000003,"stop_loss_ratio":0.1,"min_rate":0.04771803,"max_rate":0.04843559436090225,"is_open":false,"buy_tag":null,"open_timestamp":1515628800000.0,"close_timestamp":1515630900000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":27.389756231169542,"open_date":"2018-01-11 03:40:00+00:00","close_date":"2018-01-11 04:25:00+00:00","open_rate":3.651e-05,"close_rate":3.2859000000000005e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.10448878,"profit_abs":-3.650999999999996e-06,"sell_reason":"stop_loss","initial_stop_loss_abs":3.2859000000000005e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.2859000000000005e-05,"stop_loss_ratio":0.1,"min_rate":3.2859000000000005e-05,"max_rate":3.651e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515642000000.0,"close_timestamp":1515644700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011332594070446804,"open_date":"2018-01-11 03:55:00+00:00","close_date":"2018-01-11 04:25:00+00:00","open_rate":0.08824105,"close_rate":0.08956798308270676,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.0013269330827067605,"sell_reason":"roi","initial_stop_loss_abs":0.079416945,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.079416945,"stop_loss_ratio":0.1,"min_rate":0.08824105,"max_rate":0.08956798308270676,"is_open":false,"buy_tag":null,"open_timestamp":1515642900000.0,"close_timestamp":1515644700000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.411522633744856,"open_date":"2018-01-11 04:00:00+00:00","close_date":"2018-01-11 04:50:00+00:00","open_rate":0.00243,"close_rate":0.002442180451127819,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":-0.0,"profit_abs":1.2180451127819219e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002187,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002187,"stop_loss_ratio":0.1,"min_rate":0.00243,"max_rate":0.002442180451127819,"is_open":false,"buy_tag":null,"open_timestamp":1515643200000.0,"close_timestamp":1515646200000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022001890402423376,"open_date":"2018-01-11 04:30:00+00:00","close_date":"2018-01-11 04:55:00+00:00","open_rate":0.04545064,"close_rate":0.046589753784461146,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":0.001139113784461146,"sell_reason":"roi","initial_stop_loss_abs":0.040905576,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.040905576,"stop_loss_ratio":0.1,"min_rate":0.04545064,"max_rate":0.046589753784461146,"is_open":false,"buy_tag":null,"open_timestamp":1515645000000.0,"close_timestamp":1515646500000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":29.655990510083036,"open_date":"2018-01-11 04:30:00+00:00","close_date":"2018-01-11 04:50:00+00:00","open_rate":3.372e-05,"close_rate":3.456511278195488e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":8.4511278195488e-07,"sell_reason":"roi","initial_stop_loss_abs":3.0348e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.0348e-05,"stop_loss_ratio":0.1,"min_rate":3.372e-05,"max_rate":3.456511278195488e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515645000000.0,"close_timestamp":1515646200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.037821482602118005,"open_date":"2018-01-11 04:55:00+00:00","close_date":"2018-01-11 05:15:00+00:00","open_rate":0.02644,"close_rate":0.02710265664160401,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":0.0006626566416040071,"sell_reason":"roi","initial_stop_loss_abs":0.023796,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.023796,"stop_loss_ratio":0.1,"min_rate":0.02644,"max_rate":0.02710265664160401,"is_open":false,"buy_tag":null,"open_timestamp":1515646500000.0,"close_timestamp":1515647700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011348161597821153,"open_date":"2018-01-11 11:20:00+00:00","close_date":"2018-01-11 12:00:00+00:00","open_rate":0.08812,"close_rate":0.08856170426065162,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004417042606516125,"sell_reason":"roi","initial_stop_loss_abs":0.079308,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.079308,"stop_loss_ratio":0.1,"min_rate":0.08812,"max_rate":0.08856170426065162,"is_open":false,"buy_tag":null,"open_timestamp":1515669600000.0,"close_timestamp":1515672000000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.037263696923919086,"open_date":"2018-01-11 11:35:00+00:00","close_date":"2018-01-11 12:15:00+00:00","open_rate":0.02683577,"close_rate":0.026970285137844607,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00013451513784460897,"sell_reason":"roi","initial_stop_loss_abs":0.024152193,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.024152193,"stop_loss_ratio":0.1,"min_rate":0.02683577,"max_rate":0.026970285137844607,"is_open":false,"buy_tag":null,"open_timestamp":1515670500000.0,"close_timestamp":1515672900000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":20.329335230737954,"open_date":"2018-01-11 14:00:00+00:00","close_date":"2018-01-11 14:25:00+00:00","open_rate":4.919e-05,"close_rate":5.04228320802005e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":1.232832080200495e-06,"sell_reason":"roi","initial_stop_loss_abs":4.4271000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4271000000000004e-05,"stop_loss_ratio":0.1,"min_rate":4.919e-05,"max_rate":5.04228320802005e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515679200000.0,"close_timestamp":1515680700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.01138317402960718,"open_date":"2018-01-11 19:25:00+00:00","close_date":"2018-01-11 20:35:00+00:00","open_rate":0.08784896,"close_rate":0.08828930566416039,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":70,"profit_ratio":-0.0,"profit_abs":0.0004403456641603881,"sell_reason":"roi","initial_stop_loss_abs":0.079064064,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.079064064,"stop_loss_ratio":0.1,"min_rate":0.08784896,"max_rate":0.08828930566416039,"is_open":false,"buy_tag":null,"open_timestamp":1515698700000.0,"close_timestamp":1515702900000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.58863858961802,"open_date":"2018-01-11 22:35:00+00:00","close_date":"2018-01-11 23:30:00+00:00","open_rate":5.105e-05,"close_rate":5.130588972431077e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.558897243107704e-07,"sell_reason":"roi","initial_stop_loss_abs":4.5945e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.5945e-05,"stop_loss_ratio":0.1,"min_rate":5.105e-05,"max_rate":5.130588972431077e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515710100000.0,"close_timestamp":1515713400000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":25.252525252525253,"open_date":"2018-01-11 22:55:00+00:00","close_date":"2018-01-11 23:25:00+00:00","open_rate":3.96e-05,"close_rate":4.019548872180451e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":5.954887218045116e-07,"sell_reason":"roi","initial_stop_loss_abs":3.5640000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.5640000000000004e-05,"stop_loss_ratio":0.1,"min_rate":3.96e-05,"max_rate":4.019548872180451e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515711300000.0,"close_timestamp":1515713100000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":34.66204506065858,"open_date":"2018-01-11 22:55:00+00:00","close_date":"2018-01-11 23:35:00+00:00","open_rate":2.885e-05,"close_rate":2.899461152882205e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.4461152882205115e-07,"sell_reason":"roi","initial_stop_loss_abs":2.5965e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.5965e-05,"stop_loss_ratio":0.1,"min_rate":2.885e-05,"max_rate":2.899461152882205e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515711300000.0,"close_timestamp":1515713700000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03780718336483932,"open_date":"2018-01-11 23:30:00+00:00","close_date":"2018-01-12 00:05:00+00:00","open_rate":0.02645,"close_rate":0.026847744360902256,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0003977443609022545,"sell_reason":"roi","initial_stop_loss_abs":0.023805000000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.023805000000000003,"stop_loss_ratio":0.1,"min_rate":0.02645,"max_rate":0.026847744360902256,"is_open":false,"buy_tag":null,"open_timestamp":1515713400000.0,"close_timestamp":1515715500000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.020833333333333332,"open_date":"2018-01-11 23:55:00+00:00","close_date":"2018-01-12 01:15:00+00:00","open_rate":0.048,"close_rate":0.04824060150375939,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.0,"profit_abs":0.00024060150375938838,"sell_reason":"roi","initial_stop_loss_abs":0.0432,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0432,"stop_loss_ratio":0.1,"min_rate":0.048,"max_rate":0.04824060150375939,"is_open":false,"buy_tag":null,"open_timestamp":1515714900000.0,"close_timestamp":1515719700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":21.31287297527707,"open_date":"2018-01-12 21:15:00+00:00","close_date":"2018-01-12 21:40:00+00:00","open_rate":4.692e-05,"close_rate":4.809593984962405e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":1.1759398496240516e-06,"sell_reason":"roi","initial_stop_loss_abs":4.2227999999999996e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.2227999999999996e-05,"stop_loss_ratio":0.1,"min_rate":4.692e-05,"max_rate":4.809593984962405e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515791700000.0,"close_timestamp":1515793200000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38915654211062944,"open_date":"2018-01-13 00:55:00+00:00","close_date":"2018-01-13 06:20:00+00:00","open_rate":0.00256966,"close_rate":0.0025825405012531327,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":325,"profit_ratio":-0.0,"profit_abs":1.2880501253132587e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002312694,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002312694,"stop_loss_ratio":0.1,"min_rate":0.00256966,"max_rate":0.0025825405012531327,"is_open":false,"buy_tag":null,"open_timestamp":1515804900000.0,"close_timestamp":1515824400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":15.96933886937081,"open_date":"2018-01-13 10:55:00+00:00","close_date":"2018-01-13 11:35:00+00:00","open_rate":6.262e-05,"close_rate":6.293388471177944e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":3.138847117794446e-07,"sell_reason":"roi","initial_stop_loss_abs":5.6358e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.6358e-05,"stop_loss_ratio":0.1,"min_rate":6.262e-05,"max_rate":6.293388471177944e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515840900000.0,"close_timestamp":1515843300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":21.141649048625794,"open_date":"2018-01-13 13:05:00+00:00","close_date":"2018-01-15 14:10:00+00:00","open_rate":4.73e-05,"close_rate":4.753709273182957e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":2945,"profit_ratio":0.0,"profit_abs":2.3709273182957117e-07,"sell_reason":"roi","initial_stop_loss_abs":4.257e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.257e-05,"stop_loss_ratio":0.1,"min_rate":4.73e-05,"max_rate":4.753709273182957e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515848700000.0,"close_timestamp":1516025400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":16.49348507339601,"open_date":"2018-01-13 13:30:00+00:00","close_date":"2018-01-13 14:45:00+00:00","open_rate":6.063e-05,"close_rate":6.0933909774436085e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":75,"profit_ratio":-0.0,"profit_abs":3.039097744360846e-07,"sell_reason":"roi","initial_stop_loss_abs":5.4567e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.4567e-05,"stop_loss_ratio":0.1,"min_rate":6.063e-05,"max_rate":6.0933909774436085e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515850200000.0,"close_timestamp":1515854700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":9.023641941887746,"open_date":"2018-01-13 13:40:00+00:00","close_date":"2018-01-13 23:30:00+00:00","open_rate":0.00011082,"close_rate":0.00011137548872180448,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":590,"profit_ratio":-0.0,"profit_abs":5.554887218044781e-07,"sell_reason":"roi","initial_stop_loss_abs":9.9738e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":9.9738e-05,"stop_loss_ratio":0.1,"min_rate":0.00011082,"max_rate":0.00011137548872180448,"is_open":false,"buy_tag":null,"open_timestamp":1515850800000.0,"close_timestamp":1515886200000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":16.863406408094438,"open_date":"2018-01-13 15:15:00+00:00","close_date":"2018-01-13 15:55:00+00:00","open_rate":5.93e-05,"close_rate":5.9597243107769415e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.9724310776941686e-07,"sell_reason":"roi","initial_stop_loss_abs":5.337e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.337e-05,"stop_loss_ratio":0.1,"min_rate":5.93e-05,"max_rate":5.9597243107769415e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515856500000.0,"close_timestamp":1515858900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.020618543947292404,"open_date":"2018-01-13 16:30:00+00:00","close_date":"2018-01-13 17:10:00+00:00","open_rate":0.04850003,"close_rate":0.04874313791979949,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00024310791979949287,"sell_reason":"roi","initial_stop_loss_abs":0.043650027,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.043650027,"stop_loss_ratio":0.1,"min_rate":0.04850003,"max_rate":0.04874313791979949,"is_open":false,"buy_tag":null,"open_timestamp":1515861000000.0,"close_timestamp":1515863400000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010178097365511457,"open_date":"2018-01-13 22:05:00+00:00","close_date":"2018-01-14 06:25:00+00:00","open_rate":0.09825019,"close_rate":0.09874267215538848,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":500,"profit_ratio":-0.0,"profit_abs":0.0004924821553884823,"sell_reason":"roi","initial_stop_loss_abs":0.088425171,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.088425171,"stop_loss_ratio":0.1,"min_rate":0.09825019,"max_rate":0.09874267215538848,"is_open":false,"buy_tag":null,"open_timestamp":1515881100000.0,"close_timestamp":1515911100000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":16.616816218012627,"open_date":"2018-01-14 00:20:00+00:00","close_date":"2018-01-14 22:55:00+00:00","open_rate":6.018e-05,"close_rate":6.048165413533834e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":1355,"profit_ratio":0.0,"profit_abs":3.0165413533833987e-07,"sell_reason":"roi","initial_stop_loss_abs":5.4162e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.4162e-05,"stop_loss_ratio":0.1,"min_rate":6.018e-05,"max_rate":6.048165413533834e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515889200000.0,"close_timestamp":1515970500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010246952581919518,"open_date":"2018-01-14 12:45:00+00:00","close_date":"2018-01-14 13:25:00+00:00","open_rate":0.09758999,"close_rate":0.0980791628822055,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004891728822054991,"sell_reason":"roi","initial_stop_loss_abs":0.087830991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.087830991,"stop_loss_ratio":0.1,"min_rate":0.09758999,"max_rate":0.0980791628822055,"is_open":false,"buy_tag":null,"open_timestamp":1515933900000.0,"close_timestamp":1515936300000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3215434083601286,"open_date":"2018-01-14 15:30:00+00:00","close_date":"2018-01-14 16:00:00+00:00","open_rate":0.00311,"close_rate":0.0031567669172932328,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.676691729323286e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002799,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002799,"stop_loss_ratio":0.1,"min_rate":0.00311,"max_rate":0.0031567669172932328,"is_open":false,"buy_tag":null,"open_timestamp":1515943800000.0,"close_timestamp":1515945600000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.32010140812609433,"open_date":"2018-01-14 20:45:00+00:00","close_date":"2018-01-14 22:15:00+00:00","open_rate":0.00312401,"close_rate":0.003139669197994987,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":90,"profit_ratio":-0.0,"profit_abs":1.5659197994987058e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002811609,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002811609,"stop_loss_ratio":0.1,"min_rate":0.00312401,"max_rate":0.003139669197994987,"is_open":false,"buy_tag":null,"open_timestamp":1515962700000.0,"close_timestamp":1515968100000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.057247866085791646,"open_date":"2018-01-14 23:35:00+00:00","close_date":"2018-01-15 00:30:00+00:00","open_rate":0.0174679,"close_rate":0.017555458395989976,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":0.0,"profit_abs":8.755839598997492e-05,"sell_reason":"roi","initial_stop_loss_abs":0.015721110000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.015721110000000003,"stop_loss_ratio":0.1,"min_rate":0.0174679,"max_rate":0.017555458395989976,"is_open":false,"buy_tag":null,"open_timestamp":1515972900000.0,"close_timestamp":1515976200000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.013611282991367997,"open_date":"2018-01-14 23:45:00+00:00","close_date":"2018-01-15 00:25:00+00:00","open_rate":0.07346846,"close_rate":0.07383672295739348,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00036826295739347814,"sell_reason":"roi","initial_stop_loss_abs":0.066121614,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.066121614,"stop_loss_ratio":0.1,"min_rate":0.07346846,"max_rate":0.07383672295739348,"is_open":false,"buy_tag":null,"open_timestamp":1515973500000.0,"close_timestamp":1515975900000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010204706410596568,"open_date":"2018-01-15 02:25:00+00:00","close_date":"2018-01-15 03:05:00+00:00","open_rate":0.097994,"close_rate":0.09848519799498744,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004911979949874384,"sell_reason":"roi","initial_stop_loss_abs":0.0881946,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0881946,"stop_loss_ratio":0.1,"min_rate":0.097994,"max_rate":0.09848519799498744,"is_open":false,"buy_tag":null,"open_timestamp":1515983100000.0,"close_timestamp":1515985500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010353038616834042,"open_date":"2018-01-15 07:20:00+00:00","close_date":"2018-01-15 08:00:00+00:00","open_rate":0.09659,"close_rate":0.09707416040100247,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004841604010024786,"sell_reason":"roi","initial_stop_loss_abs":0.086931,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.086931,"stop_loss_ratio":0.1,"min_rate":0.09659,"max_rate":0.09707416040100247,"is_open":false,"buy_tag":null,"open_timestamp":1516000800000.0,"close_timestamp":1516003200000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.013016921998599,"open_date":"2018-01-15 08:20:00+00:00","close_date":"2018-01-15 08:55:00+00:00","open_rate":9.987e-05,"close_rate":0.00010137180451127818,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":1.501804511278178e-06,"sell_reason":"roi","initial_stop_loss_abs":8.9883e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.9883e-05,"stop_loss_ratio":0.1,"min_rate":9.987e-05,"max_rate":0.00010137180451127818,"is_open":false,"buy_tag":null,"open_timestamp":1516004400000.0,"close_timestamp":1516006500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010537752023511832,"open_date":"2018-01-15 12:10:00+00:00","close_date":"2018-01-16 02:50:00+00:00","open_rate":0.0948969,"close_rate":0.09537257368421052,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":880,"profit_ratio":0.0,"profit_abs":0.0004756736842105175,"sell_reason":"roi","initial_stop_loss_abs":0.08540721000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08540721000000001,"stop_loss_ratio":0.1,"min_rate":0.0948969,"max_rate":0.09537257368421052,"is_open":false,"buy_tag":null,"open_timestamp":1516018200000.0,"close_timestamp":1516071000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014084507042253523,"open_date":"2018-01-15 14:10:00+00:00","close_date":"2018-01-15 17:40:00+00:00","open_rate":0.071,"close_rate":0.07135588972431077,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":210,"profit_ratio":-0.0,"profit_abs":0.00035588972431077615,"sell_reason":"roi","initial_stop_loss_abs":0.0639,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0639,"stop_loss_ratio":0.1,"min_rate":0.071,"max_rate":0.07135588972431077,"is_open":false,"buy_tag":null,"open_timestamp":1516025400000.0,"close_timestamp":1516038000000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.021736763017766978,"open_date":"2018-01-15 14:30:00+00:00","close_date":"2018-01-15 15:10:00+00:00","open_rate":0.04600501,"close_rate":0.046235611553884705,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00023060155388470588,"sell_reason":"roi","initial_stop_loss_abs":0.041404509,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.041404509,"stop_loss_ratio":0.1,"min_rate":0.04600501,"max_rate":0.046235611553884705,"is_open":false,"buy_tag":null,"open_timestamp":1516026600000.0,"close_timestamp":1516029000000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.595465140919686,"open_date":"2018-01-15 18:10:00+00:00","close_date":"2018-01-15 19:25:00+00:00","open_rate":9.438e-05,"close_rate":9.485308270676693e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":75,"profit_ratio":-0.0,"profit_abs":4.7308270676692514e-07,"sell_reason":"roi","initial_stop_loss_abs":8.4942e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.4942e-05,"stop_loss_ratio":0.1,"min_rate":9.438e-05,"max_rate":9.485308270676693e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516039800000.0,"close_timestamp":1516044300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.032894726021471705,"open_date":"2018-01-15 18:35:00+00:00","close_date":"2018-01-15 19:15:00+00:00","open_rate":0.03040001,"close_rate":0.030552391002506264,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0001523810025062626,"sell_reason":"roi","initial_stop_loss_abs":0.027360009,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.027360009,"stop_loss_ratio":0.1,"min_rate":0.03040001,"max_rate":0.030552391002506264,"is_open":false,"buy_tag":null,"open_timestamp":1516041300000.0,"close_timestamp":1516043700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.13208840157615,"open_date":"2018-01-15 20:25:00+00:00","close_date":"2018-01-16 08:25:00+00:00","open_rate":5.837e-05,"close_rate":5.2533e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":720,"profit_ratio":-0.10448878,"profit_abs":-5.8369999999999985e-06,"sell_reason":"stop_loss","initial_stop_loss_abs":5.2533e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.2533e-05,"stop_loss_ratio":0.1,"min_rate":5.2533e-05,"max_rate":5.837e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516047900000.0,"close_timestamp":1516091100000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.021722130506560085,"open_date":"2018-01-15 20:40:00+00:00","close_date":"2018-01-15 22:00:00+00:00","open_rate":0.046036,"close_rate":0.04626675689223057,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.0,"profit_abs":0.00023075689223057277,"sell_reason":"roi","initial_stop_loss_abs":0.0414324,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0414324,"stop_loss_ratio":0.1,"min_rate":0.046036,"max_rate":0.04626675689223057,"is_open":false,"buy_tag":null,"open_timestamp":1516048800000.0,"close_timestamp":1516053600000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.34861425832316545,"open_date":"2018-01-16 00:30:00+00:00","close_date":"2018-01-16 01:10:00+00:00","open_rate":0.0028685,"close_rate":0.0028828784461152877,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.4378446115287727e-05,"sell_reason":"roi","initial_stop_loss_abs":0.00258165,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.00258165,"stop_loss_ratio":0.1,"min_rate":0.0028685,"max_rate":0.0028828784461152877,"is_open":false,"buy_tag":null,"open_timestamp":1516062600000.0,"close_timestamp":1516065000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014854967241083492,"open_date":"2018-01-16 01:15:00+00:00","close_date":"2018-01-16 02:35:00+00:00","open_rate":0.06731755,"close_rate":0.0676549813283208,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":0.0,"profit_abs":0.00033743132832080025,"sell_reason":"roi","initial_stop_loss_abs":0.060585795000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060585795000000005,"stop_loss_ratio":0.1,"min_rate":0.06731755,"max_rate":0.0676549813283208,"is_open":false,"buy_tag":null,"open_timestamp":1516065300000.0,"close_timestamp":1516070100000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010848794492804754,"open_date":"2018-01-16 07:45:00+00:00","close_date":"2018-01-16 08:40:00+00:00","open_rate":0.09217614,"close_rate":0.09263817578947368,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":0.0,"profit_abs":0.0004620357894736804,"sell_reason":"roi","initial_stop_loss_abs":0.082958526,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.082958526,"stop_loss_ratio":0.1,"min_rate":0.09217614,"max_rate":0.09263817578947368,"is_open":false,"buy_tag":null,"open_timestamp":1516088700000.0,"close_timestamp":1516092000000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06060606060606061,"open_date":"2018-01-16 08:35:00+00:00","close_date":"2018-01-16 08:55:00+00:00","open_rate":0.0165,"close_rate":0.016913533834586467,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":0.00041353383458646656,"sell_reason":"roi","initial_stop_loss_abs":0.01485,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.01485,"stop_loss_ratio":0.1,"min_rate":0.0165,"max_rate":0.016913533834586467,"is_open":false,"buy_tag":null,"open_timestamp":1516091700000.0,"close_timestamp":1516092900000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":12.57387149503332,"open_date":"2018-01-16 08:35:00+00:00","close_date":"2018-01-16 08:40:00+00:00","open_rate":7.953e-05,"close_rate":8.311781954887218e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":3.587819548872171e-06,"sell_reason":"roi","initial_stop_loss_abs":7.157700000000001e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":7.157700000000001e-05,"stop_loss_ratio":0.1,"min_rate":7.953e-05,"max_rate":8.311781954887218e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516091700000.0,"close_timestamp":1516092000000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022122914915269236,"open_date":"2018-01-16 08:45:00+00:00","close_date":"2018-01-16 09:50:00+00:00","open_rate":0.045202,"close_rate":0.04542857644110275,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":65,"profit_ratio":-0.0,"profit_abs":0.00022657644110275071,"sell_reason":"roi","initial_stop_loss_abs":0.0406818,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0406818,"stop_loss_ratio":0.1,"min_rate":0.045202,"max_rate":0.04542857644110275,"is_open":false,"buy_tag":null,"open_timestamp":1516092300000.0,"close_timestamp":1516096200000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.054878048780488,"open_date":"2018-01-16 09:15:00+00:00","close_date":"2018-01-16 09:45:00+00:00","open_rate":5.248e-05,"close_rate":5.326917293233082e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":7.891729323308177e-07,"sell_reason":"roi","initial_stop_loss_abs":4.7232e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7232e-05,"stop_loss_ratio":0.1,"min_rate":5.248e-05,"max_rate":5.326917293233082e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516094100000.0,"close_timestamp":1516095900000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03457434486802627,"open_date":"2018-01-16 09:15:00+00:00","close_date":"2018-01-16 09:55:00+00:00","open_rate":0.02892318,"close_rate":0.02906815834586466,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.0001449783458646603,"sell_reason":"roi","initial_stop_loss_abs":0.026030862000000002,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.026030862000000002,"stop_loss_ratio":0.1,"min_rate":0.02892318,"max_rate":0.02906815834586466,"is_open":false,"buy_tag":null,"open_timestamp":1516094100000.0,"close_timestamp":1516096500000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.38735944164405,"open_date":"2018-01-16 09:50:00+00:00","close_date":"2018-01-16 10:10:00+00:00","open_rate":5.158e-05,"close_rate":5.287273182957392e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":1.2927318295739246e-06,"sell_reason":"roi","initial_stop_loss_abs":4.6422e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6422e-05,"stop_loss_ratio":0.1,"min_rate":5.158e-05,"max_rate":5.287273182957392e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516096200000.0,"close_timestamp":1516097400000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.035357778286929785,"open_date":"2018-01-16 10:05:00+00:00","close_date":"2018-01-16 10:35:00+00:00","open_rate":0.02828232,"close_rate":0.02870761804511278,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.00042529804511277913,"sell_reason":"roi","initial_stop_loss_abs":0.025454088,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025454088,"stop_loss_ratio":0.1,"min_rate":0.02828232,"max_rate":0.02870761804511278,"is_open":false,"buy_tag":null,"open_timestamp":1516097100000.0,"close_timestamp":1516098900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022948496230938982,"open_date":"2018-01-16 10:05:00+00:00","close_date":"2018-01-16 10:40:00+00:00","open_rate":0.04357584,"close_rate":0.044231115789473675,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0006552757894736777,"sell_reason":"roi","initial_stop_loss_abs":0.039218256,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.039218256,"stop_loss_ratio":0.1,"min_rate":0.04357584,"max_rate":0.044231115789473675,"is_open":false,"buy_tag":null,"open_timestamp":1516097100000.0,"close_timestamp":1516099200000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.64975755315181,"open_date":"2018-01-16 13:45:00+00:00","close_date":"2018-01-16 14:20:00+00:00","open_rate":5.362e-05,"close_rate":5.442631578947368e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":8.063157894736843e-07,"sell_reason":"roi","initial_stop_loss_abs":4.8258e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.8258e-05,"stop_loss_ratio":0.1,"min_rate":5.362e-05,"max_rate":5.442631578947368e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516110300000.0,"close_timestamp":1516112400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.86080724254998,"open_date":"2018-01-16 17:30:00+00:00","close_date":"2018-01-16 18:25:00+00:00","open_rate":5.302e-05,"close_rate":5.328576441102756e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.6576441102756397e-07,"sell_reason":"roi","initial_stop_loss_abs":4.7718e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7718e-05,"stop_loss_ratio":0.1,"min_rate":5.302e-05,"max_rate":5.328576441102756e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516123800000.0,"close_timestamp":1516127100000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010952903718828448,"open_date":"2018-01-16 18:15:00+00:00","close_date":"2018-01-16 18:45:00+00:00","open_rate":0.09129999,"close_rate":0.09267292218045112,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.0013729321804511196,"sell_reason":"roi","initial_stop_loss_abs":0.082169991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.082169991,"stop_loss_ratio":0.1,"min_rate":0.09129999,"max_rate":0.09267292218045112,"is_open":false,"buy_tag":null,"open_timestamp":1516126500000.0,"close_timestamp":1516128300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":26.26050420168067,"open_date":"2018-01-16 18:15:00+00:00","close_date":"2018-01-16 18:35:00+00:00","open_rate":3.808e-05,"close_rate":3.903438596491228e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":9.543859649122774e-07,"sell_reason":"roi","initial_stop_loss_abs":3.4272e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.4272e-05,"stop_loss_ratio":0.1,"min_rate":3.808e-05,"max_rate":3.903438596491228e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516126500000.0,"close_timestamp":1516127700000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.035574376772493324,"open_date":"2018-01-16 19:00:00+00:00","close_date":"2018-01-16 19:30:00+00:00","open_rate":0.02811012,"close_rate":0.028532828571428567,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.00042270857142856846,"sell_reason":"roi","initial_stop_loss_abs":0.025299108,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025299108,"stop_loss_ratio":0.1,"min_rate":0.02811012,"max_rate":0.028532828571428567,"is_open":false,"buy_tag":null,"open_timestamp":1516129200000.0,"close_timestamp":1516131000000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.387028357567759,"open_date":"2018-01-16 21:25:00+00:00","close_date":"2018-01-16 22:25:00+00:00","open_rate":0.00258379,"close_rate":0.002325411,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.10448878,"profit_abs":-0.000258379,"sell_reason":"stop_loss","initial_stop_loss_abs":0.002325411,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002325411,"stop_loss_ratio":0.1,"min_rate":0.002325411,"max_rate":0.00258379,"is_open":false,"buy_tag":null,"open_timestamp":1516137900000.0,"close_timestamp":1516141500000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":39.07776475185619,"open_date":"2018-01-16 21:25:00+00:00","close_date":"2018-01-16 22:45:00+00:00","open_rate":2.559e-05,"close_rate":2.3031e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.10448878,"profit_abs":-2.5590000000000004e-06,"sell_reason":"stop_loss","initial_stop_loss_abs":2.3031e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.3031e-05,"stop_loss_ratio":0.1,"min_rate":2.3031e-05,"max_rate":2.559e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516137900000.0,"close_timestamp":1516142700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":13.123359580052494,"open_date":"2018-01-16 21:35:00+00:00","close_date":"2018-01-16 22:25:00+00:00","open_rate":7.62e-05,"close_rate":6.858e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":-0.10448878,"profit_abs":-7.619999999999998e-06,"sell_reason":"stop_loss","initial_stop_loss_abs":6.858e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":6.858e-05,"stop_loss_ratio":0.1,"min_rate":6.858e-05,"max_rate":7.62e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516138500000.0,"close_timestamp":1516141500000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.4350777048780912,"open_date":"2018-01-16 22:30:00+00:00","close_date":"2018-01-16 22:35:00+00:00","open_rate":0.00229844,"close_rate":0.002402129022556391,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":0.00010368902255639091,"sell_reason":"roi","initial_stop_loss_abs":0.0020685960000000002,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0020685960000000002,"stop_loss_ratio":0.1,"min_rate":0.00229844,"max_rate":0.002402129022556391,"is_open":false,"buy_tag":null,"open_timestamp":1516141800000.0,"close_timestamp":1516142100000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06622516556291391,"open_date":"2018-01-16 22:30:00+00:00","close_date":"2018-01-16 22:40:00+00:00","open_rate":0.0151,"close_rate":0.015781203007518795,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":10,"profit_ratio":0.03990025,"profit_abs":0.0006812030075187946,"sell_reason":"roi","initial_stop_loss_abs":0.013590000000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.013590000000000001,"stop_loss_ratio":0.1,"min_rate":0.0151,"max_rate":0.015781203007518795,"is_open":false,"buy_tag":null,"open_timestamp":1516141800000.0,"close_timestamp":1516142400000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.42431134269081283,"open_date":"2018-01-16 22:40:00+00:00","close_date":"2018-01-16 22:45:00+00:00","open_rate":0.00235676,"close_rate":0.00246308,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":0.00010632000000000003,"sell_reason":"roi","initial_stop_loss_abs":0.002121084,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002121084,"stop_loss_ratio":0.1,"min_rate":0.00235676,"max_rate":0.00246308,"is_open":false,"buy_tag":null,"open_timestamp":1516142400000.0,"close_timestamp":1516142700000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.01585559988076589,"open_date":"2018-01-16 22:45:00+00:00","close_date":"2018-01-16 23:05:00+00:00","open_rate":0.0630692,"close_rate":0.06464988170426066,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":0.0015806817042606502,"sell_reason":"roi","initial_stop_loss_abs":0.056762280000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.056762280000000005,"stop_loss_ratio":0.1,"min_rate":0.0630692,"max_rate":0.06464988170426066,"is_open":false,"buy_tag":null,"open_timestamp":1516142700000.0,"close_timestamp":1516143900000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":45.45454545454545,"open_date":"2018-01-16 22:50:00+00:00","close_date":"2018-01-16 22:55:00+00:00","open_rate":2.2e-05,"close_rate":2.299248120300751e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":9.924812030075114e-07,"sell_reason":"roi","initial_stop_loss_abs":1.98e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":1.98e-05,"stop_loss_ratio":0.1,"min_rate":2.2e-05,"max_rate":2.299248120300751e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516143000000.0,"close_timestamp":1516143300000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":20.10454362685967,"open_date":"2018-01-17 03:30:00+00:00","close_date":"2018-01-17 04:00:00+00:00","open_rate":4.974e-05,"close_rate":5.048796992481203e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":7.479699248120277e-07,"sell_reason":"roi","initial_stop_loss_abs":4.4766000000000005e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4766000000000005e-05,"stop_loss_ratio":0.1,"min_rate":4.974e-05,"max_rate":5.048796992481203e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516159800000.0,"close_timestamp":1516161600000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":14.068655036578503,"open_date":"2018-01-17 03:55:00+00:00","close_date":"2018-01-17 04:15:00+00:00","open_rate":7.108e-05,"close_rate":7.28614536340852e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":1.7814536340851996e-06,"sell_reason":"roi","initial_stop_loss_abs":6.3972e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":6.3972e-05,"stop_loss_ratio":0.1,"min_rate":7.108e-05,"max_rate":7.28614536340852e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516161300000.0,"close_timestamp":1516162500000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.0231107002542177,"open_date":"2018-01-17 09:35:00+00:00","close_date":"2018-01-17 10:15:00+00:00","open_rate":0.04327,"close_rate":0.04348689223057644,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0002168922305764362,"sell_reason":"roi","initial_stop_loss_abs":0.038943000000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.038943000000000005,"stop_loss_ratio":0.1,"min_rate":0.04327,"max_rate":0.04348689223057644,"is_open":false,"buy_tag":null,"open_timestamp":1516181700000.0,"close_timestamp":1516184100000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":20.012007204322593,"open_date":"2018-01-17 10:20:00+00:00","close_date":"2018-01-17 17:00:00+00:00","open_rate":4.997e-05,"close_rate":5.022047619047618e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":400,"profit_ratio":-0.0,"profit_abs":2.504761904761831e-07,"sell_reason":"roi","initial_stop_loss_abs":4.4973e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4973e-05,"stop_loss_ratio":0.1,"min_rate":4.997e-05,"max_rate":5.022047619047618e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516184400000.0,"close_timestamp":1516208400000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014626687444363738,"open_date":"2018-01-17 10:30:00+00:00","close_date":"2018-01-17 11:25:00+00:00","open_rate":0.06836818,"close_rate":0.06871087764411027,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":0.00034269764411026804,"sell_reason":"roi","initial_stop_loss_abs":0.061531362,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.061531362,"stop_loss_ratio":0.1,"min_rate":0.06836818,"max_rate":0.06871087764411027,"is_open":false,"buy_tag":null,"open_timestamp":1516185000000.0,"close_timestamp":1516188300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":27.548209366391184,"open_date":"2018-01-17 10:30:00+00:00","close_date":"2018-01-17 11:10:00+00:00","open_rate":3.63e-05,"close_rate":3.648195488721804e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.8195488721804031e-07,"sell_reason":"roi","initial_stop_loss_abs":3.2670000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.2670000000000004e-05,"stop_loss_ratio":0.1,"min_rate":3.63e-05,"max_rate":3.648195488721804e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516185000000.0,"close_timestamp":1516187400000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03558718861209965,"open_date":"2018-01-17 12:30:00+00:00","close_date":"2018-01-17 22:05:00+00:00","open_rate":0.0281,"close_rate":0.02824085213032581,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":575,"profit_ratio":-0.0,"profit_abs":0.0001408521303258095,"sell_reason":"roi","initial_stop_loss_abs":0.02529,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.02529,"stop_loss_ratio":0.1,"min_rate":0.0281,"max_rate":0.02824085213032581,"is_open":false,"buy_tag":null,"open_timestamp":1516192200000.0,"close_timestamp":1516226700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011559355963546878,"open_date":"2018-01-17 12:35:00+00:00","close_date":"2018-01-17 16:55:00+00:00","open_rate":0.08651001,"close_rate":0.08694364413533832,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":260,"profit_ratio":-0.0,"profit_abs":0.00043363413533832607,"sell_reason":"roi","initial_stop_loss_abs":0.077859009,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.077859009,"stop_loss_ratio":0.1,"min_rate":0.08651001,"max_rate":0.08694364413533832,"is_open":false,"buy_tag":null,"open_timestamp":1516192500000.0,"close_timestamp":1516208100000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.752529735487308,"open_date":"2018-01-18 05:00:00+00:00","close_date":"2018-01-18 05:55:00+00:00","open_rate":5.633e-05,"close_rate":5.6612355889724306e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.8235588972430847e-07,"sell_reason":"roi","initial_stop_loss_abs":5.0697e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0697e-05,"stop_loss_ratio":0.1,"min_rate":5.633e-05,"max_rate":5.6612355889724306e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516251600000.0,"close_timestamp":1516254900000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.01430923457900944,"open_date":"2018-01-18 05:20:00+00:00","close_date":"2018-01-18 05:55:00+00:00","open_rate":0.06988494,"close_rate":0.07093584135338346,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0010509013533834544,"sell_reason":"roi","initial_stop_loss_abs":0.06289644600000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06289644600000001,"stop_loss_ratio":0.1,"min_rate":0.06988494,"max_rate":0.07093584135338346,"is_open":false,"buy_tag":null,"open_timestamp":1516252800000.0,"close_timestamp":1516254900000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.034265103697024,"open_date":"2018-01-18 07:35:00+00:00","close_date":"2018-01-18 08:15:00+00:00","open_rate":5.545e-05,"close_rate":5.572794486215538e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.779448621553787e-07,"sell_reason":"roi","initial_stop_loss_abs":4.9905e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.9905e-05,"stop_loss_ratio":0.1,"min_rate":5.545e-05,"max_rate":5.572794486215538e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516260900000.0,"close_timestamp":1516263300000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06121723118136401,"open_date":"2018-01-18 09:00:00+00:00","close_date":"2018-01-18 09:40:00+00:00","open_rate":0.01633527,"close_rate":0.016417151052631574,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":8.188105263157511e-05,"sell_reason":"roi","initial_stop_loss_abs":0.014701743,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014701743,"stop_loss_ratio":0.1,"min_rate":0.01633527,"max_rate":0.016417151052631574,"is_open":false,"buy_tag":null,"open_timestamp":1516266000000.0,"close_timestamp":1516268400000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3707356136045141,"open_date":"2018-01-18 16:40:00+00:00","close_date":"2018-01-18 17:20:00+00:00","open_rate":0.00269734,"close_rate":0.002710860501253133,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.3520501253133123e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002427606,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002427606,"stop_loss_ratio":0.1,"min_rate":0.00269734,"max_rate":0.002710860501253133,"is_open":false,"buy_tag":null,"open_timestamp":1516293600000.0,"close_timestamp":1516296000000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":22.346368715083802,"open_date":"2018-01-18 18:05:00+00:00","close_date":"2018-01-18 18:30:00+00:00","open_rate":4.475e-05,"close_rate":4.587155388471177e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":1.1215538847117757e-06,"sell_reason":"roi","initial_stop_loss_abs":4.0274999999999996e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.0274999999999996e-05,"stop_loss_ratio":0.1,"min_rate":4.475e-05,"max_rate":4.587155388471177e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516298700000.0,"close_timestamp":1516300200000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":35.842293906810035,"open_date":"2018-01-18 18:25:00+00:00","close_date":"2018-01-18 18:55:00+00:00","open_rate":2.79e-05,"close_rate":2.8319548872180444e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.1954887218044365e-07,"sell_reason":"roi","initial_stop_loss_abs":2.5110000000000002e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.5110000000000002e-05,"stop_loss_ratio":0.1,"min_rate":2.79e-05,"max_rate":2.8319548872180444e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516299900000.0,"close_timestamp":1516301700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022525942001105574,"open_date":"2018-01-18 20:10:00+00:00","close_date":"2018-01-18 20:50:00+00:00","open_rate":0.04439326,"close_rate":0.04461578260651629,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.00022252260651629135,"sell_reason":"roi","initial_stop_loss_abs":0.039953933999999997,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.039953933999999997,"stop_loss_ratio":0.1,"min_rate":0.04439326,"max_rate":0.04461578260651629,"is_open":false,"buy_tag":null,"open_timestamp":1516306200000.0,"close_timestamp":1516308600000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":22.271714922048996,"open_date":"2018-01-18 21:30:00+00:00","close_date":"2018-01-19 00:35:00+00:00","open_rate":4.49e-05,"close_rate":4.51250626566416e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":185,"profit_ratio":0.0,"profit_abs":2.2506265664159932e-07,"sell_reason":"roi","initial_stop_loss_abs":4.041e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.041e-05,"stop_loss_ratio":0.1,"min_rate":4.49e-05,"max_rate":4.51250626566416e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516311000000.0,"close_timestamp":1516322100000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03502626970227671,"open_date":"2018-01-18 21:55:00+00:00","close_date":"2018-01-19 05:05:00+00:00","open_rate":0.02855,"close_rate":0.028693107769423555,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":430,"profit_ratio":-0.0,"profit_abs":0.00014310776942355607,"sell_reason":"roi","initial_stop_loss_abs":0.025695,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025695,"stop_loss_ratio":0.1,"min_rate":0.02855,"max_rate":0.028693107769423555,"is_open":false,"buy_tag":null,"open_timestamp":1516312500000.0,"close_timestamp":1516338300000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.25327812284334,"open_date":"2018-01-18 22:10:00+00:00","close_date":"2018-01-18 22:50:00+00:00","open_rate":5.796e-05,"close_rate":5.8250526315789473e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":2.905263157894727e-07,"sell_reason":"roi","initial_stop_loss_abs":5.2164000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.2164000000000004e-05,"stop_loss_ratio":0.1,"min_rate":5.796e-05,"max_rate":5.8250526315789473e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516313400000.0,"close_timestamp":1516315800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02303975994413319,"open_date":"2018-01-18 23:50:00+00:00","close_date":"2018-01-19 00:30:00+00:00","open_rate":0.04340323,"close_rate":0.04362079005012531,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.0002175600501253122,"sell_reason":"roi","initial_stop_loss_abs":0.039062907,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.039062907,"stop_loss_ratio":0.1,"min_rate":0.04340323,"max_rate":0.04362079005012531,"is_open":false,"buy_tag":null,"open_timestamp":1516319400000.0,"close_timestamp":1516321800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02244943545282195,"open_date":"2018-01-19 16:45:00+00:00","close_date":"2018-01-19 17:35:00+00:00","open_rate":0.04454455,"close_rate":0.04476783095238095,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":0.0,"profit_abs":0.0002232809523809512,"sell_reason":"roi","initial_stop_loss_abs":0.040090095000000006,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.040090095000000006,"stop_loss_ratio":0.1,"min_rate":0.04454455,"max_rate":0.04476783095238095,"is_open":false,"buy_tag":null,"open_timestamp":1516380300000.0,"close_timestamp":1516383300000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.793594306049823,"open_date":"2018-01-19 17:15:00+00:00","close_date":"2018-01-19 19:55:00+00:00","open_rate":5.62e-05,"close_rate":5.648170426065162e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":160,"profit_ratio":-0.0,"profit_abs":2.817042606516199e-07,"sell_reason":"roi","initial_stop_loss_abs":5.058e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.058e-05,"stop_loss_ratio":0.1,"min_rate":5.62e-05,"max_rate":5.648170426065162e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516382100000.0,"close_timestamp":1516391700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":23.046784973496194,"open_date":"2018-01-19 17:20:00+00:00","close_date":"2018-01-19 20:15:00+00:00","open_rate":4.339e-05,"close_rate":4.360749373433584e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":175,"profit_ratio":-0.0,"profit_abs":2.174937343358337e-07,"sell_reason":"roi","initial_stop_loss_abs":3.9051e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.9051e-05,"stop_loss_ratio":0.1,"min_rate":4.339e-05,"max_rate":4.360749373433584e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516382400000.0,"close_timestamp":1516392900000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":9.910802775024777,"open_date":"2018-01-20 04:45:00+00:00","close_date":"2018-01-20 17:35:00+00:00","open_rate":0.0001009,"close_rate":0.00010140576441102755,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":770,"profit_ratio":0.0,"profit_abs":5.057644110275549e-07,"sell_reason":"roi","initial_stop_loss_abs":9.081e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":9.081e-05,"stop_loss_ratio":0.1,"min_rate":0.0001009,"max_rate":0.00010140576441102755,"is_open":false,"buy_tag":null,"open_timestamp":1516423500000.0,"close_timestamp":1516469700000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3696789338459548,"open_date":"2018-01-20 04:50:00+00:00","close_date":"2018-01-20 15:15:00+00:00","open_rate":0.00270505,"close_rate":0.002718609147869674,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":625,"profit_ratio":-0.0,"profit_abs":1.3559147869673764e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002434545,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002434545,"stop_loss_ratio":0.1,"min_rate":0.00270505,"max_rate":0.002718609147869674,"is_open":false,"buy_tag":null,"open_timestamp":1516423800000.0,"close_timestamp":1516461300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.033333311111125925,"open_date":"2018-01-20 04:50:00+00:00","close_date":"2018-01-20 07:00:00+00:00","open_rate":0.03000002,"close_rate":0.030150396040100245,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":130,"profit_ratio":-0.0,"profit_abs":0.00015037604010024672,"sell_reason":"roi","initial_stop_loss_abs":0.027000018,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.027000018,"stop_loss_ratio":0.1,"min_rate":0.03000002,"max_rate":0.030150396040100245,"is_open":false,"buy_tag":null,"open_timestamp":1516423800000.0,"close_timestamp":1516431600000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.315018315018317,"open_date":"2018-01-20 09:00:00+00:00","close_date":"2018-01-20 09:40:00+00:00","open_rate":5.46e-05,"close_rate":5.4873684210526304e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.736842105263053e-07,"sell_reason":"roi","initial_stop_loss_abs":4.914e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.914e-05,"stop_loss_ratio":0.1,"min_rate":5.46e-05,"max_rate":5.4873684210526304e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516438800000.0,"close_timestamp":1516441200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03244412634781012,"open_date":"2018-01-20 18:25:00+00:00","close_date":"2018-01-25 03:50:00+00:00","open_rate":0.03082222,"close_rate":0.027739998,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":6325,"profit_ratio":-0.10448878,"profit_abs":-0.0030822220000000025,"sell_reason":"stop_loss","initial_stop_loss_abs":0.027739998000000002,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.027739998000000002,"stop_loss_ratio":0.1,"min_rate":0.027739998,"max_rate":0.03082222,"is_open":false,"buy_tag":null,"open_timestamp":1516472700000.0,"close_timestamp":1516852200000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011148273260677065,"open_date":"2018-01-20 22:25:00+00:00","close_date":"2018-01-20 23:15:00+00:00","open_rate":0.08969999,"close_rate":0.09014961401002504,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":-0.0,"profit_abs":0.00044962401002504593,"sell_reason":"roi","initial_stop_loss_abs":0.080729991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.080729991,"stop_loss_ratio":0.1,"min_rate":0.08969999,"max_rate":0.09014961401002504,"is_open":false,"buy_tag":null,"open_timestamp":1516487100000.0,"close_timestamp":1516490100000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06125570520324337,"open_date":"2018-01-21 02:50:00+00:00","close_date":"2018-01-21 14:30:00+00:00","open_rate":0.01632501,"close_rate":0.01640683962406015,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":700,"profit_ratio":0.0,"profit_abs":8.182962406014932e-05,"sell_reason":"roi","initial_stop_loss_abs":0.014692509000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014692509000000001,"stop_loss_ratio":0.1,"min_rate":0.01632501,"max_rate":0.01640683962406015,"is_open":false,"buy_tag":null,"open_timestamp":1516503000000.0,"close_timestamp":1516545000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.01417675579120474,"open_date":"2018-01-21 10:20:00+00:00","close_date":"2018-01-21 11:00:00+00:00","open_rate":0.070538,"close_rate":0.07089157393483708,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00035357393483707866,"sell_reason":"roi","initial_stop_loss_abs":0.0634842,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0634842,"stop_loss_ratio":0.1,"min_rate":0.070538,"max_rate":0.07089157393483708,"is_open":false,"buy_tag":null,"open_timestamp":1516530000000.0,"close_timestamp":1516532400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.864365214110546,"open_date":"2018-01-21 15:50:00+00:00","close_date":"2018-01-21 18:45:00+00:00","open_rate":5.301e-05,"close_rate":5.327571428571427e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":175,"profit_ratio":-0.0,"profit_abs":2.657142857142672e-07,"sell_reason":"roi","initial_stop_loss_abs":4.7709e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7709e-05,"stop_loss_ratio":0.1,"min_rate":5.301e-05,"max_rate":5.327571428571427e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516549800000.0,"close_timestamp":1516560300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":25.284450063211125,"open_date":"2018-01-21 16:20:00+00:00","close_date":"2018-01-21 17:00:00+00:00","open_rate":3.955e-05,"close_rate":3.9748245614035085e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":1.9824561403508552e-07,"sell_reason":"roi","initial_stop_loss_abs":3.5595e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.5595e-05,"stop_loss_ratio":0.1,"min_rate":3.955e-05,"max_rate":3.9748245614035085e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516551600000.0,"close_timestamp":1516554000000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38683971296493297,"open_date":"2018-01-21 21:15:00+00:00","close_date":"2018-01-21 21:45:00+00:00","open_rate":0.00258505,"close_rate":0.002623922932330827,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":3.8872932330826816e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002326545,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002326545,"stop_loss_ratio":0.1,"min_rate":0.00258505,"max_rate":0.002623922932330827,"is_open":false,"buy_tag":null,"open_timestamp":1516569300000.0,"close_timestamp":1516571100000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":25.621316935690498,"open_date":"2018-01-21 21:15:00+00:00","close_date":"2018-01-21 21:55:00+00:00","open_rate":3.903e-05,"close_rate":3.922563909774435e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.9563909774435151e-07,"sell_reason":"roi","initial_stop_loss_abs":3.5127e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.5127e-05,"stop_loss_ratio":0.1,"min_rate":3.903e-05,"max_rate":3.922563909774435e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516569300000.0,"close_timestamp":1516571700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.098548510313215,"open_date":"2018-01-22 00:35:00+00:00","close_date":"2018-01-22 10:35:00+00:00","open_rate":5.236e-05,"close_rate":5.262245614035087e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":600,"profit_ratio":-0.0,"profit_abs":2.624561403508717e-07,"sell_reason":"roi","initial_stop_loss_abs":4.7124e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7124e-05,"stop_loss_ratio":0.1,"min_rate":5.236e-05,"max_rate":5.262245614035087e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516581300000.0,"close_timestamp":1516617300000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.076650420912717,"open_date":"2018-01-22 01:30:00+00:00","close_date":"2018-01-22 02:10:00+00:00","open_rate":9.028e-05,"close_rate":9.07325313283208e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":4.5253132832080657e-07,"sell_reason":"roi","initial_stop_loss_abs":8.1252e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.1252e-05,"stop_loss_ratio":0.1,"min_rate":9.028e-05,"max_rate":9.07325313283208e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516584600000.0,"close_timestamp":1516587000000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3721622627465575,"open_date":"2018-01-22 12:25:00+00:00","close_date":"2018-01-22 14:35:00+00:00","open_rate":0.002687,"close_rate":0.002700468671679198,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":130,"profit_ratio":-0.0,"profit_abs":1.3468671679197925e-05,"sell_reason":"roi","initial_stop_loss_abs":0.0024183000000000004,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0024183000000000004,"stop_loss_ratio":0.1,"min_rate":0.002687,"max_rate":0.002700468671679198,"is_open":false,"buy_tag":null,"open_timestamp":1516623900000.0,"close_timestamp":1516631700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":23.99232245681382,"open_date":"2018-01-22 13:15:00+00:00","close_date":"2018-01-22 13:55:00+00:00","open_rate":4.168e-05,"close_rate":4.188892230576441e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.0892230576441054e-07,"sell_reason":"roi","initial_stop_loss_abs":3.7512e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.7512e-05,"stop_loss_ratio":0.1,"min_rate":4.168e-05,"max_rate":4.188892230576441e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516626900000.0,"close_timestamp":1516629300000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.336583153837434,"open_date":"2018-01-22 14:00:00+00:00","close_date":"2018-01-22 14:30:00+00:00","open_rate":8.821e-05,"close_rate":8.953646616541353e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":1.326466165413529e-06,"sell_reason":"roi","initial_stop_loss_abs":7.9389e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":7.9389e-05,"stop_loss_ratio":0.1,"min_rate":8.821e-05,"max_rate":8.953646616541353e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516629600000.0,"close_timestamp":1516631400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.334880123743233,"open_date":"2018-01-22 15:55:00+00:00","close_date":"2018-01-22 16:40:00+00:00","open_rate":5.172e-05,"close_rate":5.1979248120300745e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":2.592481203007459e-07,"sell_reason":"roi","initial_stop_loss_abs":4.6548e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6548e-05,"stop_loss_ratio":0.1,"min_rate":5.172e-05,"max_rate":5.1979248120300745e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516636500000.0,"close_timestamp":1516639200000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":33.04692663582287,"open_date":"2018-01-22 16:05:00+00:00","close_date":"2018-01-22 16:25:00+00:00","open_rate":3.026e-05,"close_rate":3.101839598997494e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":7.5839598997494e-07,"sell_reason":"roi","initial_stop_loss_abs":2.7234e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7234e-05,"stop_loss_ratio":0.1,"min_rate":3.026e-05,"max_rate":3.101839598997494e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516637100000.0,"close_timestamp":1516638300000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014156285390713478,"open_date":"2018-01-22 19:50:00+00:00","close_date":"2018-01-23 00:10:00+00:00","open_rate":0.07064,"close_rate":0.07099408521303258,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":260,"profit_ratio":0.0,"profit_abs":0.00035408521303258167,"sell_reason":"roi","initial_stop_loss_abs":0.063576,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.063576,"stop_loss_ratio":0.1,"min_rate":0.07064,"max_rate":0.07099408521303258,"is_open":false,"buy_tag":null,"open_timestamp":1516650600000.0,"close_timestamp":1516666200000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06080938507725528,"open_date":"2018-01-22 21:25:00+00:00","close_date":"2018-01-22 22:05:00+00:00","open_rate":0.01644483,"close_rate":0.01652726022556391,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":8.243022556390922e-05,"sell_reason":"roi","initial_stop_loss_abs":0.014800347,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014800347,"stop_loss_ratio":0.1,"min_rate":0.01644483,"max_rate":0.01652726022556391,"is_open":false,"buy_tag":null,"open_timestamp":1516656300000.0,"close_timestamp":1516658700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":23.08935580697299,"open_date":"2018-01-23 00:05:00+00:00","close_date":"2018-01-23 00:35:00+00:00","open_rate":4.331e-05,"close_rate":4.3961278195488714e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":6.512781954887175e-07,"sell_reason":"roi","initial_stop_loss_abs":3.8979e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.8979e-05,"stop_loss_ratio":0.1,"min_rate":4.331e-05,"max_rate":4.3961278195488714e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516665900000.0,"close_timestamp":1516667700000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":31.250000000000004,"open_date":"2018-01-23 01:50:00+00:00","close_date":"2018-01-23 02:15:00+00:00","open_rate":3.2e-05,"close_rate":3.2802005012531326e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":8.020050125313278e-07,"sell_reason":"roi","initial_stop_loss_abs":2.88e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.88e-05,"stop_loss_ratio":0.1,"min_rate":3.2e-05,"max_rate":3.2802005012531326e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516672200000.0,"close_timestamp":1516673700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010907854156754155,"open_date":"2018-01-23 04:25:00+00:00","close_date":"2018-01-23 05:15:00+00:00","open_rate":0.09167706,"close_rate":0.09213659413533835,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":0.0,"profit_abs":0.0004595341353383492,"sell_reason":"roi","initial_stop_loss_abs":0.08250935400000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08250935400000001,"stop_loss_ratio":0.1,"min_rate":0.09167706,"max_rate":0.09213659413533835,"is_open":false,"buy_tag":null,"open_timestamp":1516681500000.0,"close_timestamp":1516684500000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014440474918339115,"open_date":"2018-01-23 07:35:00+00:00","close_date":"2018-01-23 09:00:00+00:00","open_rate":0.0692498,"close_rate":0.06959691679197995,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":85,"profit_ratio":0.0,"profit_abs":0.0003471167919799484,"sell_reason":"roi","initial_stop_loss_abs":0.06232482,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06232482,"stop_loss_ratio":0.1,"min_rate":0.0692498,"max_rate":0.06959691679197995,"is_open":false,"buy_tag":null,"open_timestamp":1516692900000.0,"close_timestamp":1516698000000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":31.426775612822127,"open_date":"2018-01-23 10:50:00+00:00","close_date":"2018-01-23 13:05:00+00:00","open_rate":3.182e-05,"close_rate":3.197949874686716e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":135,"profit_ratio":0.0,"profit_abs":1.594987468671663e-07,"sell_reason":"roi","initial_stop_loss_abs":2.8638e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.8638e-05,"stop_loss_ratio":0.1,"min_rate":3.182e-05,"max_rate":3.197949874686716e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516704600000.0,"close_timestamp":1516712700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024461839530332683,"open_date":"2018-01-23 11:05:00+00:00","close_date":"2018-01-23 16:05:00+00:00","open_rate":0.04088,"close_rate":0.04108491228070175,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":300,"profit_ratio":-0.0,"profit_abs":0.0002049122807017481,"sell_reason":"roi","initial_stop_loss_abs":0.036792,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036792,"stop_loss_ratio":0.1,"min_rate":0.04088,"max_rate":0.04108491228070175,"is_open":false,"buy_tag":null,"open_timestamp":1516705500000.0,"close_timestamp":1516723500000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.417475728155342,"open_date":"2018-01-23 14:55:00+00:00","close_date":"2018-01-23 15:35:00+00:00","open_rate":5.15e-05,"close_rate":5.175814536340851e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.5814536340851513e-07,"sell_reason":"roi","initial_stop_loss_abs":4.635e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.635e-05,"stop_loss_ratio":0.1,"min_rate":5.15e-05,"max_rate":5.175814536340851e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516719300000.0,"close_timestamp":1516721700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011023294646713328,"open_date":"2018-01-23 16:35:00+00:00","close_date":"2018-01-24 00:05:00+00:00","open_rate":0.09071698,"close_rate":0.09117170170426064,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":450,"profit_ratio":0.0,"profit_abs":0.00045472170426064107,"sell_reason":"roi","initial_stop_loss_abs":0.081645282,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.081645282,"stop_loss_ratio":0.1,"min_rate":0.09071698,"max_rate":0.09117170170426064,"is_open":false,"buy_tag":null,"open_timestamp":1516725300000.0,"close_timestamp":1516752300000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":31.969309462915604,"open_date":"2018-01-23 17:25:00+00:00","close_date":"2018-01-23 18:45:00+00:00","open_rate":3.128e-05,"close_rate":3.1436791979949865e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.0,"profit_abs":1.5679197994986587e-07,"sell_reason":"roi","initial_stop_loss_abs":2.8152e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.8152e-05,"stop_loss_ratio":0.1,"min_rate":3.128e-05,"max_rate":3.1436791979949865e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516728300000.0,"close_timestamp":1516733100000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.465724751439037,"open_date":"2018-01-23 20:15:00+00:00","close_date":"2018-01-23 22:00:00+00:00","open_rate":9.555e-05,"close_rate":9.602894736842104e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":105,"profit_ratio":-0.0,"profit_abs":4.789473684210343e-07,"sell_reason":"roi","initial_stop_loss_abs":8.5995e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.5995e-05,"stop_loss_ratio":0.1,"min_rate":9.555e-05,"max_rate":9.602894736842104e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516738500000.0,"close_timestamp":1516744800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02450979791426522,"open_date":"2018-01-23 22:30:00+00:00","close_date":"2018-01-23 23:10:00+00:00","open_rate":0.04080001,"close_rate":0.0410045213283208,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00020451132832080554,"sell_reason":"roi","initial_stop_loss_abs":0.036720009,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036720009,"stop_loss_ratio":0.1,"min_rate":0.04080001,"max_rate":0.0410045213283208,"is_open":false,"buy_tag":null,"open_timestamp":1516746600000.0,"close_timestamp":1516749000000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.368584156498162,"open_date":"2018-01-23 23:50:00+00:00","close_date":"2018-01-24 03:35:00+00:00","open_rate":5.163e-05,"close_rate":5.18887969924812e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":225,"profit_ratio":-0.0,"profit_abs":2.587969924812037e-07,"sell_reason":"roi","initial_stop_loss_abs":4.6467e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6467e-05,"stop_loss_ratio":0.1,"min_rate":5.163e-05,"max_rate":5.18887969924812e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516751400000.0,"close_timestamp":1516764900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024747691102289384,"open_date":"2018-01-24 00:20:00+00:00","close_date":"2018-01-24 01:50:00+00:00","open_rate":0.04040781,"close_rate":0.04061035541353383,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":90,"profit_ratio":0.0,"profit_abs":0.0002025454135338306,"sell_reason":"roi","initial_stop_loss_abs":0.036367029,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036367029,"stop_loss_ratio":0.1,"min_rate":0.04040781,"max_rate":0.04061035541353383,"is_open":false,"buy_tag":null,"open_timestamp":1516753200000.0,"close_timestamp":1516758600000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.485580670303975,"open_date":"2018-01-24 06:45:00+00:00","close_date":"2018-01-24 07:25:00+00:00","open_rate":5.132e-05,"close_rate":5.157724310776942e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.5724310776941724e-07,"sell_reason":"roi","initial_stop_loss_abs":4.6188000000000006e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6188000000000006e-05,"stop_loss_ratio":0.1,"min_rate":5.132e-05,"max_rate":5.157724310776942e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516776300000.0,"close_timestamp":1516778700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.23816852635629,"open_date":"2018-01-24 14:15:00+00:00","close_date":"2018-01-24 14:25:00+00:00","open_rate":5.198e-05,"close_rate":5.432496240601503e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":10,"profit_ratio":0.03990025,"profit_abs":2.344962406015033e-06,"sell_reason":"roi","initial_stop_loss_abs":4.6782e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6782e-05,"stop_loss_ratio":0.1,"min_rate":5.198e-05,"max_rate":5.432496240601503e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516803300000.0,"close_timestamp":1516803900000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":32.74394237066143,"open_date":"2018-01-24 14:50:00+00:00","close_date":"2018-01-24 16:35:00+00:00","open_rate":3.054e-05,"close_rate":3.069308270676692e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":105,"profit_ratio":-0.0,"profit_abs":1.5308270676691466e-07,"sell_reason":"roi","initial_stop_loss_abs":2.7486000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7486000000000004e-05,"stop_loss_ratio":0.1,"min_rate":3.054e-05,"max_rate":3.069308270676692e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516805400000.0,"close_timestamp":1516811700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.795638562020944,"open_date":"2018-01-24 15:10:00+00:00","close_date":"2018-01-24 16:15:00+00:00","open_rate":9.263e-05,"close_rate":9.309431077694236e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":65,"profit_ratio":0.0,"profit_abs":4.6431077694236234e-07,"sell_reason":"roi","initial_stop_loss_abs":8.3367e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.3367e-05,"stop_loss_ratio":0.1,"min_rate":9.263e-05,"max_rate":9.309431077694236e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516806600000.0,"close_timestamp":1516810500000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.13565469713457,"open_date":"2018-01-24 22:40:00+00:00","close_date":"2018-01-24 23:25:00+00:00","open_rate":5.514e-05,"close_rate":5.54163909774436e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":2.7639097744360576e-07,"sell_reason":"roi","initial_stop_loss_abs":4.9625999999999995e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.9625999999999995e-05,"stop_loss_ratio":0.1,"min_rate":5.514e-05,"max_rate":5.54163909774436e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516833600000.0,"close_timestamp":1516836300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":20.3210729526519,"open_date":"2018-01-25 00:50:00+00:00","close_date":"2018-01-25 01:30:00+00:00","open_rate":4.921e-05,"close_rate":4.9456666666666664e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":2.4666666666666543e-07,"sell_reason":"roi","initial_stop_loss_abs":4.4289e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4289e-05,"stop_loss_ratio":0.1,"min_rate":4.921e-05,"max_rate":4.9456666666666664e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516841400000.0,"close_timestamp":1516843800000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38461538461538464,"open_date":"2018-01-25 08:15:00+00:00","close_date":"2018-01-25 12:15:00+00:00","open_rate":0.0026,"close_rate":0.002613032581453634,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":240,"profit_ratio":0.0,"profit_abs":1.3032581453634e-05,"sell_reason":"roi","initial_stop_loss_abs":0.00234,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.00234,"stop_loss_ratio":0.1,"min_rate":0.0026,"max_rate":0.002613032581453634,"is_open":false,"buy_tag":null,"open_timestamp":1516868100000.0,"close_timestamp":1516882500000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03571593119825878,"open_date":"2018-01-25 10:25:00+00:00","close_date":"2018-01-25 16:15:00+00:00","open_rate":0.02799871,"close_rate":0.028139054411027563,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":350,"profit_ratio":-0.0,"profit_abs":0.00014034441102756326,"sell_reason":"roi","initial_stop_loss_abs":0.025198839,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025198839,"stop_loss_ratio":0.1,"min_rate":0.02799871,"max_rate":0.028139054411027563,"is_open":false,"buy_tag":null,"open_timestamp":1516875900000.0,"close_timestamp":1516896900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024516401717913302,"open_date":"2018-01-25 11:00:00+00:00","close_date":"2018-01-25 11:45:00+00:00","open_rate":0.04078902,"close_rate":0.0409934762406015,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":0.00020445624060149575,"sell_reason":"roi","initial_stop_loss_abs":0.036710118,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036710118,"stop_loss_ratio":0.1,"min_rate":0.04078902,"max_rate":0.0409934762406015,"is_open":false,"buy_tag":null,"open_timestamp":1516878000000.0,"close_timestamp":1516880700000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":34.602076124567475,"open_date":"2018-01-25 13:05:00+00:00","close_date":"2018-01-25 13:45:00+00:00","open_rate":2.89e-05,"close_rate":2.904486215538847e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.4486215538846723e-07,"sell_reason":"roi","initial_stop_loss_abs":2.601e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.601e-05,"stop_loss_ratio":0.1,"min_rate":2.89e-05,"max_rate":2.904486215538847e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516885500000.0,"close_timestamp":1516887900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02432912439481303,"open_date":"2018-01-25 13:20:00+00:00","close_date":"2018-01-25 14:05:00+00:00","open_rate":0.041103,"close_rate":0.04130903007518797,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":0.00020603007518796984,"sell_reason":"roi","initial_stop_loss_abs":0.0369927,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0369927,"stop_loss_ratio":0.1,"min_rate":0.041103,"max_rate":0.04130903007518797,"is_open":false,"buy_tag":null,"open_timestamp":1516886400000.0,"close_timestamp":1516889100000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":18.422991893883566,"open_date":"2018-01-25 15:45:00+00:00","close_date":"2018-01-25 16:15:00+00:00","open_rate":5.428e-05,"close_rate":5.509624060150376e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":8.162406015037611e-07,"sell_reason":"roi","initial_stop_loss_abs":4.8852000000000006e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.8852000000000006e-05,"stop_loss_ratio":0.1,"min_rate":5.428e-05,"max_rate":5.509624060150376e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516895100000.0,"close_timestamp":1516896900000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":18.47063169560399,"open_date":"2018-01-25 17:45:00+00:00","close_date":"2018-01-25 23:15:00+00:00","open_rate":5.414e-05,"close_rate":5.441137844611528e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":330,"profit_ratio":-0.0,"profit_abs":2.713784461152774e-07,"sell_reason":"roi","initial_stop_loss_abs":4.8726e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.8726e-05,"stop_loss_ratio":0.1,"min_rate":5.414e-05,"max_rate":5.441137844611528e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516902300000.0,"close_timestamp":1516922100000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024150056861308878,"open_date":"2018-01-25 21:15:00+00:00","close_date":"2018-01-25 21:55:00+00:00","open_rate":0.04140777,"close_rate":0.0416153277443609,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0002075577443608964,"sell_reason":"roi","initial_stop_loss_abs":0.037266993000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.037266993000000005,"stop_loss_ratio":0.1,"min_rate":0.04140777,"max_rate":0.0416153277443609,"is_open":false,"buy_tag":null,"open_timestamp":1516914900000.0,"close_timestamp":1516917300000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3932224183965176,"open_date":"2018-01-26 02:05:00+00:00","close_date":"2018-01-26 02:45:00+00:00","open_rate":0.00254309,"close_rate":0.002555837318295739,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":1.2747318295739177e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002288781,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002288781,"stop_loss_ratio":0.1,"min_rate":0.00254309,"max_rate":0.002555837318295739,"is_open":false,"buy_tag":null,"open_timestamp":1516932300000.0,"close_timestamp":1516934700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.834849295523455,"open_date":"2018-01-26 02:55:00+00:00","close_date":"2018-01-26 15:10:00+00:00","open_rate":5.607e-05,"close_rate":5.6351052631578935e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":735,"profit_ratio":-0.0,"profit_abs":2.810526315789381e-07,"sell_reason":"roi","initial_stop_loss_abs":5.0463e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0463e-05,"stop_loss_ratio":0.1,"min_rate":5.607e-05,"max_rate":5.6351052631578935e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516935300000.0,"close_timestamp":1516979400000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.39400171784748983,"open_date":"2018-01-26 06:10:00+00:00","close_date":"2018-01-26 09:25:00+00:00","open_rate":0.00253806,"close_rate":0.0025507821052631577,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":195,"profit_ratio":0.0,"profit_abs":1.2722105263157733e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002284254,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002284254,"stop_loss_ratio":0.1,"min_rate":0.00253806,"max_rate":0.0025507821052631577,"is_open":false,"buy_tag":null,"open_timestamp":1516947000000.0,"close_timestamp":1516958700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024096385542168672,"open_date":"2018-01-26 07:25:00+00:00","close_date":"2018-01-26 09:55:00+00:00","open_rate":0.0415,"close_rate":0.04170802005012531,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":150,"profit_ratio":-0.0,"profit_abs":0.00020802005012530989,"sell_reason":"roi","initial_stop_loss_abs":0.03735,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.03735,"stop_loss_ratio":0.1,"min_rate":0.0415,"max_rate":0.04170802005012531,"is_open":false,"buy_tag":null,"open_timestamp":1516951500000.0,"close_timestamp":1516960500000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":18.793459875963165,"open_date":"2018-01-26 09:55:00+00:00","close_date":"2018-01-26 10:25:00+00:00","open_rate":5.321e-05,"close_rate":5.401015037593984e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":8.00150375939842e-07,"sell_reason":"roi","initial_stop_loss_abs":4.7889e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7889e-05,"stop_loss_ratio":0.1,"min_rate":5.321e-05,"max_rate":5.401015037593984e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516960500000.0,"close_timestamp":1516962300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.036074437437185386,"open_date":"2018-01-26 16:05:00+00:00","close_date":"2018-01-26 16:45:00+00:00","open_rate":0.02772046,"close_rate":0.02785940967418546,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00013894967418546025,"sell_reason":"roi","initial_stop_loss_abs":0.024948414,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.024948414,"stop_loss_ratio":0.1,"min_rate":0.02772046,"max_rate":0.02785940967418546,"is_open":false,"buy_tag":null,"open_timestamp":1516982700000.0,"close_timestamp":1516985100000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010569326272036914,"open_date":"2018-01-26 23:35:00+00:00","close_date":"2018-01-27 00:15:00+00:00","open_rate":0.09461341,"close_rate":0.09508766268170424,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.00047425268170424306,"sell_reason":"roi","initial_stop_loss_abs":0.085152069,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.085152069,"stop_loss_ratio":0.1,"min_rate":0.09461341,"max_rate":0.09508766268170424,"is_open":false,"buy_tag":null,"open_timestamp":1517009700000.0,"close_timestamp":1517012100000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":17.809439002671414,"open_date":"2018-01-27 00:35:00+00:00","close_date":"2018-01-27 01:30:00+00:00","open_rate":5.615e-05,"close_rate":5.643145363408521e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.814536340852038e-07,"sell_reason":"roi","initial_stop_loss_abs":5.0535e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0535e-05,"stop_loss_ratio":0.1,"min_rate":5.615e-05,"max_rate":5.643145363408521e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517013300000.0,"close_timestamp":1517016600000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.998560115190784,"open_date":"2018-01-27 00:45:00+00:00","close_date":"2018-01-30 04:45:00+00:00","open_rate":5.556e-05,"close_rate":5.144e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":4560,"profit_ratio":-0.07877175,"profit_abs":-4.120000000000001e-06,"sell_reason":"force_sell","initial_stop_loss_abs":5.0004000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0004000000000004e-05,"stop_loss_ratio":0.1,"min_rate":5.144e-05,"max_rate":5.556e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517013900000.0,"close_timestamp":1517287500000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014492751522789634,"open_date":"2018-01-27 02:30:00+00:00","close_date":"2018-01-27 11:25:00+00:00","open_rate":0.06900001,"close_rate":0.06934587471177944,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":535,"profit_ratio":-0.0,"profit_abs":0.0003458647117794422,"sell_reason":"roi","initial_stop_loss_abs":0.062100009000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.062100009000000005,"stop_loss_ratio":0.1,"min_rate":0.06900001,"max_rate":0.06934587471177944,"is_open":false,"buy_tag":null,"open_timestamp":1517020200000.0,"close_timestamp":1517052300000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010582027378879437,"open_date":"2018-01-27 06:25:00+00:00","close_date":"2018-01-27 07:05:00+00:00","open_rate":0.09449985,"close_rate":0.0949735334586466,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004736834586466093,"sell_reason":"roi","initial_stop_loss_abs":0.085049865,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.085049865,"stop_loss_ratio":0.1,"min_rate":0.09449985,"max_rate":0.0949735334586466,"is_open":false,"buy_tag":null,"open_timestamp":1517034300000.0,"close_timestamp":1517036700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02434885085598385,"open_date":"2018-01-27 09:40:00+00:00","close_date":"2018-01-30 04:40:00+00:00","open_rate":0.0410697,"close_rate":0.03928809,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":4020,"profit_ratio":-0.04815133,"profit_abs":-0.001781610000000003,"sell_reason":"force_sell","initial_stop_loss_abs":0.03696273,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.03696273,"stop_loss_ratio":0.1,"min_rate":0.03928809,"max_rate":0.0410697,"is_open":false,"buy_tag":null,"open_timestamp":1517046000000.0,"close_timestamp":1517287200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03508771929824561,"open_date":"2018-01-27 11:45:00+00:00","close_date":"2018-01-27 12:30:00+00:00","open_rate":0.0285,"close_rate":0.02864285714285714,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":0.00014285714285713902,"sell_reason":"roi","initial_stop_loss_abs":0.025650000000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025650000000000003,"stop_loss_ratio":0.1,"min_rate":0.0285,"max_rate":0.02864285714285714,"is_open":false,"buy_tag":null,"open_timestamp":1517053500000.0,"close_timestamp":1517056200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.034887307020861215,"open_date":"2018-01-27 12:35:00+00:00","close_date":"2018-01-27 15:25:00+00:00","open_rate":0.02866372,"close_rate":0.02880739779448621,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":170,"profit_ratio":-0.0,"profit_abs":0.00014367779448621124,"sell_reason":"roi","initial_stop_loss_abs":0.025797348,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025797348,"stop_loss_ratio":0.1,"min_rate":0.02866372,"max_rate":0.02880739779448621,"is_open":false,"buy_tag":null,"open_timestamp":1517056500000.0,"close_timestamp":1517066700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010484268355332824,"open_date":"2018-01-27 15:50:00+00:00","close_date":"2018-01-27 16:50:00+00:00","open_rate":0.095381,"close_rate":0.09585910025062656,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.0,"profit_abs":0.00047810025062657024,"sell_reason":"roi","initial_stop_loss_abs":0.0858429,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0858429,"stop_loss_ratio":0.1,"min_rate":0.095381,"max_rate":0.09585910025062656,"is_open":false,"buy_tag":null,"open_timestamp":1517068200000.0,"close_timestamp":1517071800000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014794886650455417,"open_date":"2018-01-27 17:05:00+00:00","close_date":"2018-01-27 17:45:00+00:00","open_rate":0.06759092,"close_rate":0.06792972160401002,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00033880160401002224,"sell_reason":"roi","initial_stop_loss_abs":0.060831828,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060831828,"stop_loss_ratio":0.1,"min_rate":0.06759092,"max_rate":0.06792972160401002,"is_open":false,"buy_tag":null,"open_timestamp":1517072700000.0,"close_timestamp":1517075100000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38684569885609726,"open_date":"2018-01-27 23:40:00+00:00","close_date":"2018-01-28 01:05:00+00:00","open_rate":0.00258501,"close_rate":0.002597967443609022,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":85,"profit_ratio":-0.0,"profit_abs":1.2957443609021985e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002326509,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002326509,"stop_loss_ratio":0.1,"min_rate":0.00258501,"max_rate":0.002597967443609022,"is_open":false,"buy_tag":null,"open_timestamp":1517096400000.0,"close_timestamp":1517101500000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014928710926711672,"open_date":"2018-01-28 02:25:00+00:00","close_date":"2018-01-28 08:10:00+00:00","open_rate":0.06698502,"close_rate":0.0673207845112782,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":345,"profit_ratio":-0.0,"profit_abs":0.00033576451127818874,"sell_reason":"roi","initial_stop_loss_abs":0.060286518000000004,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060286518000000004,"stop_loss_ratio":0.1,"min_rate":0.06698502,"max_rate":0.0673207845112782,"is_open":false,"buy_tag":null,"open_timestamp":1517106300000.0,"close_timestamp":1517127000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014767187899175548,"open_date":"2018-01-28 10:25:00+00:00","close_date":"2018-01-28 16:30:00+00:00","open_rate":0.0677177,"close_rate":0.06805713709273183,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":365,"profit_ratio":-0.0,"profit_abs":0.0003394370927318202,"sell_reason":"roi","initial_stop_loss_abs":0.06094593000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06094593000000001,"stop_loss_ratio":0.1,"min_rate":0.0677177,"max_rate":0.06805713709273183,"is_open":false,"buy_tag":null,"open_timestamp":1517135100000.0,"close_timestamp":1517157000000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":19.175455417066157,"open_date":"2018-01-28 20:35:00+00:00","close_date":"2018-01-28 21:35:00+00:00","open_rate":5.215e-05,"close_rate":5.2411403508771925e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":0.0,"profit_abs":2.6140350877192417e-07,"sell_reason":"roi","initial_stop_loss_abs":4.6935000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6935000000000004e-05,"stop_loss_ratio":0.1,"min_rate":5.215e-05,"max_rate":5.2411403508771925e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517171700000.0,"close_timestamp":1517175300000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.36521808998243305,"open_date":"2018-01-28 22:00:00+00:00","close_date":"2018-01-28 22:30:00+00:00","open_rate":0.00273809,"close_rate":0.002779264285714285,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.117428571428529e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002464281,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002464281,"stop_loss_ratio":0.1,"min_rate":0.00273809,"max_rate":0.002779264285714285,"is_open":false,"buy_tag":null,"open_timestamp":1517176800000.0,"close_timestamp":1517178600000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3641236272539253,"open_date":"2018-01-29 00:00:00+00:00","close_date":"2018-01-29 00:30:00+00:00","open_rate":0.00274632,"close_rate":0.002787618045112782,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.129804511278194e-05,"sell_reason":"roi","initial_stop_loss_abs":0.002471688,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002471688,"stop_loss_ratio":0.1,"min_rate":0.00274632,"max_rate":0.002787618045112782,"is_open":false,"buy_tag":null,"open_timestamp":1517184000000.0,"close_timestamp":1517185800000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.061634117689115045,"open_date":"2018-01-29 02:15:00+00:00","close_date":"2018-01-29 03:00:00+00:00","open_rate":0.01622478,"close_rate":0.016306107218045113,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":0.0,"profit_abs":8.132721804511231e-05,"sell_reason":"roi","initial_stop_loss_abs":0.014602302000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014602302000000001,"stop_loss_ratio":0.1,"min_rate":0.01622478,"max_rate":0.016306107218045113,"is_open":false,"buy_tag":null,"open_timestamp":1517192100000.0,"close_timestamp":1517194800000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014492753623188404,"open_date":"2018-01-29 03:05:00+00:00","close_date":"2018-01-29 03:45:00+00:00","open_rate":0.069,"close_rate":0.06934586466165413,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00034586466165412166,"sell_reason":"roi","initial_stop_loss_abs":0.06210000000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06210000000000001,"stop_loss_ratio":0.1,"min_rate":0.069,"max_rate":0.06934586466165413,"is_open":false,"buy_tag":null,"open_timestamp":1517195100000.0,"close_timestamp":1517197500000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.42204454597373,"open_date":"2018-01-29 05:20:00+00:00","close_date":"2018-01-29 06:55:00+00:00","open_rate":8.755e-05,"close_rate":8.798884711779448e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":95,"profit_ratio":-0.0,"profit_abs":4.3884711779447504e-07,"sell_reason":"roi","initial_stop_loss_abs":7.879500000000001e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":7.879500000000001e-05,"stop_loss_ratio":0.1,"min_rate":8.755e-05,"max_rate":8.798884711779448e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517203200000.0,"close_timestamp":1517208900000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014650376815016871,"open_date":"2018-01-29 07:00:00+00:00","close_date":"2018-01-29 19:25:00+00:00","open_rate":0.06825763,"close_rate":0.06859977350877192,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":745,"profit_ratio":-0.0,"profit_abs":0.00034214350877191657,"sell_reason":"roi","initial_stop_loss_abs":0.061431867,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.061431867,"stop_loss_ratio":0.1,"min_rate":0.06825763,"max_rate":0.06859977350877192,"is_open":false,"buy_tag":null,"open_timestamp":1517209200000.0,"close_timestamp":1517253900000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014894490408841846,"open_date":"2018-01-29 19:45:00+00:00","close_date":"2018-01-29 20:25:00+00:00","open_rate":0.06713892,"close_rate":0.06747545593984962,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0003365359398496137,"sell_reason":"roi","initial_stop_loss_abs":0.060425028000000006,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060425028000000006,"stop_loss_ratio":0.1,"min_rate":0.06713892,"max_rate":0.06747545593984962,"is_open":false,"buy_tag":null,"open_timestamp":1517255100000.0,"close_timestamp":1517257500000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.193194537721066,"open_date":"2018-01-29 23:30:00+00:00","close_date":"2018-01-30 04:45:00+00:00","open_rate":8.934e-05,"close_rate":8.8e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":315,"profit_ratio":-0.0199116,"profit_abs":-1.3399999999999973e-06,"sell_reason":"force_sell","initial_stop_loss_abs":8.0406e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.0406e-05,"stop_loss_ratio":0.1,"min_rate":8.8e-05,"max_rate":8.934e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517268600000.0,"close_timestamp":1517287500000.0}],"locks":[],"best_pair":{"key":"LTC/BTC","trades":8,"profit_mean":0.00748129625,"profit_mean_pct":0.748129625,"profit_sum":0.05985037,"profit_sum_pct":5.99,"profit_total_abs":0.0015944746365914707,"profit_total":0.15944746365914708,"profit_total_pct":15.94,"duration_avg":"1:59:00","wins":8,"draws":0,"losses":0},"worst_pair":{"key":"XMR/BTC","trades":16,"profit_mean":-0.0027899012500000007,"profit_mean_pct":-0.2789901250000001,"profit_sum":-0.04463842000000001,"profit_sum_pct":-4.46,"profit_total_abs":0.0006671885263157366,"profit_total":0.06671885263157366,"profit_total_pct":6.67,"duration_avg":"8:41:00","wins":15,"draws":0,"losses":1},"results_per_pair":[{"key":"ETH/BTC","trades":21,"profit_mean":0.0009500057142857142,"profit_mean_pct":0.09500057142857142,"profit_sum":0.01995012,"profit_sum_pct":2.0,"profit_total_abs":0.011505731278195264,"profit_total":1.1505731278195264,"profit_total_pct":115.06,"duration_avg":"2:17:00","wins":21,"draws":0,"losses":0},{"key":"DASH/BTC","trades":16,"profit_mean":0.0018703237499999997,"profit_mean_pct":0.18703237499999997,"profit_sum":0.029925179999999996,"profit_sum_pct":2.99,"profit_total_abs":0.007475052681704161,"profit_total":0.7475052681704161,"profit_total_pct":74.75,"duration_avg":"3:03:00","wins":16,"draws":0,"losses":0},{"key":"ZEC/BTC","trades":21,"profit_mean":-0.00039290904761904774,"profit_mean_pct":-0.03929090476190478,"profit_sum":-0.008251090000000003,"profit_sum_pct":-0.83,"profit_total_abs":0.004452605639097655,"profit_total":0.4452605639097655,"profit_total_pct":44.53,"duration_avg":"4:17:00","wins":20,"draws":0,"losses":1},{"key":"LTC/BTC","trades":8,"profit_mean":0.00748129625,"profit_mean_pct":0.748129625,"profit_sum":0.05985037,"profit_sum_pct":5.99,"profit_total_abs":0.0015944746365914707,"profit_total":0.15944746365914708,"profit_total_pct":15.94,"duration_avg":"1:59:00","wins":8,"draws":0,"losses":0},{"key":"XMR/BTC","trades":16,"profit_mean":-0.0027899012500000007,"profit_mean_pct":-0.2789901250000001,"profit_sum":-0.04463842000000001,"profit_sum_pct":-4.46,"profit_total_abs":0.0006671885263157366,"profit_total":0.06671885263157366,"profit_total_pct":6.67,"duration_avg":"8:41:00","wins":15,"draws":0,"losses":1},{"key":"ETC/BTC","trades":20,"profit_mean":0.0022568569999999997,"profit_mean_pct":0.22568569999999996,"profit_sum":0.04513713999999999,"profit_sum_pct":4.51,"profit_total_abs":0.00036538235338345404,"profit_total":0.0365382353383454,"profit_total_pct":3.65,"duration_avg":"1:45:00","wins":19,"draws":0,"losses":1},{"key":"TRX/BTC","trades":15,"profit_mean":0.0023467073333333323,"profit_mean_pct":0.23467073333333321,"profit_sum":0.035200609999999986,"profit_sum_pct":3.52,"profit_total_abs":1.1329523809523682e-05,"profit_total":0.0011329523809523682,"profit_total_pct":0.11,"duration_avg":"2:28:00","wins":13,"draws":0,"losses":2},{"key":"XLM/BTC","trades":21,"profit_mean":0.0026243899999999994,"profit_mean_pct":0.2624389999999999,"profit_sum":0.05511218999999999,"profit_sum_pct":5.51,"profit_total_abs":7.340779448621465e-06,"profit_total":0.0007340779448621465,"profit_total_pct":0.07,"duration_avg":"3:21:00","wins":20,"draws":0,"losses":1},{"key":"ADA/BTC","trades":29,"profit_mean":-0.0011598141379310352,"profit_mean_pct":-0.11598141379310352,"profit_sum":-0.03363461000000002,"profit_sum_pct":-3.36,"profit_total_abs":4.916634085212862e-06,"profit_total":0.0004916634085212862,"profit_total_pct":0.05,"duration_avg":"5:35:00","wins":27,"draws":0,"losses":2},{"key":"NXT/BTC","trades":12,"profit_mean":-0.0012261025000000006,"profit_mean_pct":-0.12261025000000006,"profit_sum":-0.014713230000000008,"profit_sum_pct":-1.47,"profit_total_abs":1.4774411027568458e-06,"profit_total":0.00014774411027568458,"profit_total_pct":0.01,"duration_avg":"0:57:00","wins":11,"draws":0,"losses":1},{"key":"TOTAL","trades":179,"profit_mean":0.0008041243575418989,"profit_mean_pct":0.0804124357541899,"profit_sum":0.1439382599999999,"profit_sum_pct":14.39,"profit_total_abs":0.026085499493733857,"profit_total":2.6085499493733857,"profit_total_pct":260.85,"duration_avg":"3:40:00","wins":170,"draws":0,"losses":9}],"results_per_enter_tag":[{"key":"TOTAL","trades":179,"profit_mean":0.0008041243575418989,"profit_mean_pct":0.0804124357541899,"profit_sum":0.1439382599999999,"profit_sum_pct":14.39,"profit_total_abs":0.026085499493733857,"profit_total":2.6085499493733857,"profit_total_pct":260.85,"duration_avg":"3:40:00","wins":170,"draws":0,"losses":9}],"sell_reason_summary":[{"sell_reason":"roi","trades":170,"wins":170,"draws":0,"losses":0,"profit_mean":0.005398268352941177,"profit_mean_pct":0.54,"profit_sum":0.91770562,"profit_sum_pct":91.77,"profit_total_abs":0.031232837493733862,"profit_total":0.30590187333333335,"profit_total_pct":30.59},{"sell_reason":"stop_loss","trades":6,"wins":0,"draws":0,"losses":6,"profit_mean":-0.10448878000000002,"profit_mean_pct":-10.45,"profit_sum":-0.6269326800000001,"profit_sum_pct":-62.69,"profit_total_abs":-0.0033602680000000026,"profit_total":-0.20897756000000003,"profit_total_pct":-20.9},{"sell_reason":"force_sell","trades":3,"wins":0,"draws":0,"losses":3,"profit_mean":-0.04894489333333333,"profit_mean_pct":-4.89,"profit_sum":-0.14683468,"profit_sum_pct":-14.68,"profit_total_abs":-0.001787070000000003,"profit_total":-0.04894489333333333,"profit_total_pct":-4.89}],"left_open_trades":[{"key":"TOTAL","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0}],"total_trades":179,"total_volume":0.17900000000000005,"avg_stake_amount":0.0010000000000000002,"profit_mean":0.0008041243575418989,"profit_median":0.0,"profit_total":2.6085499493733857,"profit_total_abs":0.026085499493733857,"backtest_start":"2018-01-10 07:15:00","backtest_start_ts":1515568500000,"backtest_end":"2018-01-30 04:45:00","backtest_end_ts":1517287500000,"backtest_days":19,"backtest_run_start_ts":"2020-10-01 18:00:00+00:00","backtest_run_end_ts":"2020-10-01 18:01:00+00:00","trades_per_day":9.42,"market_change":1.22,"pairlist":[],"stake_amount":0.001,"stake_currency":"BTC","stake_currency_decimals":8,"starting_balance":0.01,"dry_run_wallet":0.01,"final_balance":0.03608549949373386,"rejected_signals":0,"max_open_trades":3,"max_open_trades_setting":3,"timeframe":"5m","timeframe_detail":"","timerange":"","enable_protections":false,"strategy_name":"StrategyTestV2","stoploss":0.1,"trailing_stop":false,"trailing_stop_positive":null,"trailing_stop_positive_offset":0.0,"trailing_only_offset_is_reached":false,"use_custom_stoploss":false,"minimal_roi":{},"use_sell_signal":true,"sell_profit_only":false,"sell_profit_offset":false,"ignore_roi_if_buy_signal":false,"backtest_best_day":0.17955111999999998,"backtest_worst_day":-0.14683468,"backtest_best_day_abs":0.0071570099,"backtest_worst_day_abs":-0.0023093218,"winning_days":19,"draw_days":0,"losing_days":2,"daily_profit":[["2018-01-10",0.0025815306],["2018-01-11",0.0049356655],["2018-01-12",0.0006395218],["2018-01-13",0.0002574589],["2018-01-14",0.0010443828],["2018-01-15",0.0024030209],["2018-01-16",0.0071570099],["2018-01-17",0.001137038],["2018-01-18",0.0013712174],["2018-01-19",0.000584673],["2018-01-20",0.0006143386],["2018-01-21",0.0004749361],["2018-01-22",9.91669e-05],["2018-01-23",0.0015726664],["2018-01-24",0.0006610219],["2018-01-25",-0.0023093218],["2018-01-26",0.0003735204],["2018-01-27",0.0023975191],["2018-01-28",0.0007295947],["2018-01-29",0.0011476082],["2018-01-30",-0.00178707]],"wins":48,"losses":9,"draws":122,"holding_avg":"3:40:00","holding_avg_s":13200.0,"winner_holding_avg":"0:24:00","winner_holding_avg_s":1440.0,"loser_holding_avg":"1 day, 5:57:00","loser_holding_avg_s":107820.0,"max_drawdown":0.21142322000000008,"max_drawdown_account":0.08674033488183289,"max_drawdown_abs":0.0030822220000000025,"drawdown_start":"2018-01-25 01:30:00","drawdown_start_ts":1516843800000.0,"drawdown_end":"2018-01-25 03:50:00","drawdown_end_ts":1516852200000.0,"max_drawdown_low":0.02245167355388436,"max_drawdown_high":0.025533895553884363,"csum_min":0.01000434887218045,"csum_max":0.03608683949373386}},"strategy_comparison":[{"key":"StrategyTestV2","trades":179,"profit_mean":0.0008041243575418989,"profit_mean_pct":0.0804124357541899,"profit_sum":0.1439382599999999,"profit_sum_pct":14.39,"profit_total_abs":0.026085499493733857,"profit_total":2.6085499493733857,"profit_total_pct":260.85,"duration_avg":"3:40:00","wins":170,"draws":0,"losses":9,"max_drawdown_account":0.08674033488183289,"max_drawdown_abs":"0.00308222"}]} +{"strategy":{"StrategyTestV3":{"trades":[{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.37344398340249,"open_date":"2018-01-10 07:15:00+00:00","close_date":"2018-01-10 07:20:00+00:00","open_rate":9.64e-05,"close_rate":0.00010074887218045112,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":4.348872180451118e-06,"exit_reason":"roi","initial_stop_loss_abs":8.676e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.676e-05,"stop_loss_ratio":0.1,"min_rate":9.64e-05,"max_rate":0.00010074887218045112,"is_open":false,"buy_tag":null,"open_timestamp":1515568500000.0,"close_timestamp":1515568800000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":21.026072329688816,"open_date":"2018-01-10 07:15:00+00:00","close_date":"2018-01-10 07:30:00+00:00","open_rate":4.756e-05,"close_rate":4.9705563909774425e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":15,"profit_ratio":0.03990025,"profit_abs":2.1455639097744267e-06,"exit_reason":"roi","initial_stop_loss_abs":4.2804e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.2804e-05,"stop_loss_ratio":0.1,"min_rate":4.756e-05,"max_rate":4.9705563909774425e-05,"is_open":false,"buy_tag":"buy_tag","open_timestamp":1515568500000.0,"close_timestamp":1515569400000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":29.94908655286014,"open_date":"2018-01-10 07:25:00+00:00","close_date":"2018-01-10 07:35:00+00:00","open_rate":3.339e-05,"close_rate":3.489631578947368e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":10,"profit_ratio":0.03990025,"profit_abs":1.506315789473681e-06,"exit_reason":"roi","initial_stop_loss_abs":3.0050999999999997e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.0050999999999997e-05,"stop_loss_ratio":0.1,"min_rate":3.339e-05,"max_rate":3.489631578947368e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515569100000.0,"close_timestamp":1515569700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.313531353135314,"open_date":"2018-01-10 07:25:00+00:00","close_date":"2018-01-10 07:40:00+00:00","open_rate":9.696e-05,"close_rate":0.00010133413533834584,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":15,"profit_ratio":0.03990025,"profit_abs":4.3741353383458455e-06,"exit_reason":"roi","initial_stop_loss_abs":8.7264e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.7264e-05,"stop_loss_ratio":0.1,"min_rate":9.696e-05,"max_rate":0.00010133413533834584,"is_open":false,"buy_tag":null,"open_timestamp":1515569100000.0,"close_timestamp":1515570000000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010604453870625663,"open_date":"2018-01-10 07:35:00+00:00","close_date":"2018-01-10 08:35:00+00:00","open_rate":0.0943,"close_rate":0.09477268170426063,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.0,"profit_abs":0.0004726817042606385,"exit_reason":"roi","initial_stop_loss_abs":0.08487,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08487,"stop_loss_ratio":0.1,"min_rate":0.0943,"max_rate":0.09477268170426063,"is_open":false,"buy_tag":null,"open_timestamp":1515569700000.0,"close_timestamp":1515573300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03677001860930642,"open_date":"2018-01-10 07:40:00+00:00","close_date":"2018-01-10 08:10:00+00:00","open_rate":0.02719607,"close_rate":0.02760503345864661,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.00040896345864661204,"exit_reason":"roi","initial_stop_loss_abs":0.024476463,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.024476463,"stop_loss_ratio":0.1,"min_rate":0.02719607,"max_rate":0.02760503345864661,"is_open":false,"buy_tag":null,"open_timestamp":1515570000000.0,"close_timestamp":1515571800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.021575196463739,"open_date":"2018-01-10 08:15:00+00:00","close_date":"2018-01-10 09:55:00+00:00","open_rate":0.04634952,"close_rate":0.046581848421052625,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":100,"profit_ratio":0.0,"profit_abs":0.0002323284210526272,"exit_reason":"roi","initial_stop_loss_abs":0.041714568,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.041714568,"stop_loss_ratio":0.1,"min_rate":0.04634952,"max_rate":0.046581848421052625,"is_open":false,"buy_tag":null,"open_timestamp":1515572100000.0,"close_timestamp":1515578100000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":32.615786040443574,"open_date":"2018-01-10 14:45:00+00:00","close_date":"2018-01-10 15:50:00+00:00","open_rate":3.066e-05,"close_rate":3.081368421052631e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":65,"profit_ratio":-0.0,"profit_abs":1.5368421052630647e-07,"exit_reason":"roi","initial_stop_loss_abs":2.7594e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7594e-05,"stop_loss_ratio":0.1,"min_rate":3.066e-05,"max_rate":3.081368421052631e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515595500000.0,"close_timestamp":1515599400000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.05917194776300452,"open_date":"2018-01-10 16:35:00+00:00","close_date":"2018-01-10 17:15:00+00:00","open_rate":0.0168999,"close_rate":0.016984611278195488,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":8.471127819548868e-05,"exit_reason":"roi","initial_stop_loss_abs":0.01520991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.01520991,"stop_loss_ratio":0.1,"min_rate":0.0168999,"max_rate":0.016984611278195488,"is_open":false,"buy_tag":null,"open_timestamp":1515602100000.0,"close_timestamp":1515604500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010949822656672253,"open_date":"2018-01-10 16:40:00+00:00","close_date":"2018-01-10 17:20:00+00:00","open_rate":0.09132568,"close_rate":0.0917834528320802,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004577728320801916,"exit_reason":"roi","initial_stop_loss_abs":0.08219311200000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08219311200000001,"stop_loss_ratio":0.1,"min_rate":0.09132568,"max_rate":0.0917834528320802,"is_open":false,"buy_tag":null,"open_timestamp":1515602400000.0,"close_timestamp":1515604800000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011238476768326556,"open_date":"2018-01-10 18:50:00+00:00","close_date":"2018-01-10 19:45:00+00:00","open_rate":0.08898003,"close_rate":0.08942604518796991,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":0.00044601518796991146,"exit_reason":"roi","initial_stop_loss_abs":0.080082027,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.080082027,"stop_loss_ratio":0.1,"min_rate":0.08898003,"max_rate":0.08942604518796991,"is_open":false,"buy_tag":null,"open_timestamp":1515610200000.0,"close_timestamp":1515613500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011682232072680307,"open_date":"2018-01-10 22:15:00+00:00","close_date":"2018-01-10 23:00:00+00:00","open_rate":0.08560008,"close_rate":0.08602915308270676,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":0.0,"profit_abs":0.00042907308270676014,"exit_reason":"roi","initial_stop_loss_abs":0.077040072,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.077040072,"stop_loss_ratio":0.1,"min_rate":0.08560008,"max_rate":0.08602915308270676,"is_open":false,"buy_tag":null,"open_timestamp":1515622500000.0,"close_timestamp":1515625200000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.4014726015023105,"open_date":"2018-01-10 22:50:00+00:00","close_date":"2018-01-10 23:20:00+00:00","open_rate":0.00249083,"close_rate":0.0025282860902255634,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":3.745609022556351e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002241747,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002241747,"stop_loss_ratio":0.1,"min_rate":0.00249083,"max_rate":0.0025282860902255634,"is_open":false,"buy_tag":null,"open_timestamp":1515624600000.0,"close_timestamp":1515626400000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":33.090668431502316,"open_date":"2018-01-10 23:15:00+00:00","close_date":"2018-01-11 00:15:00+00:00","open_rate":3.022e-05,"close_rate":3.037147869674185e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.0,"profit_abs":1.5147869674185174e-07,"exit_reason":"roi","initial_stop_loss_abs":2.7198e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7198e-05,"stop_loss_ratio":0.1,"min_rate":3.022e-05,"max_rate":3.037147869674185e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515626100000.0,"close_timestamp":1515629700000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.41034058268362744,"open_date":"2018-01-10 23:40:00+00:00","close_date":"2018-01-11 00:05:00+00:00","open_rate":0.002437,"close_rate":0.0024980776942355883,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":6.107769423558838e-05,"exit_reason":"roi","initial_stop_loss_abs":0.0021933,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0021933,"stop_loss_ratio":0.1,"min_rate":0.002437,"max_rate":0.0024980776942355883,"is_open":false,"buy_tag":null,"open_timestamp":1515627600000.0,"close_timestamp":1515629100000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02095643931654345,"open_date":"2018-01-11 00:00:00+00:00","close_date":"2018-01-11 00:35:00+00:00","open_rate":0.04771803,"close_rate":0.04843559436090225,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0007175643609022495,"exit_reason":"roi","initial_stop_loss_abs":0.042946227000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.042946227000000003,"stop_loss_ratio":0.1,"min_rate":0.04771803,"max_rate":0.04843559436090225,"is_open":false,"buy_tag":null,"open_timestamp":1515628800000.0,"close_timestamp":1515630900000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":27.389756231169542,"open_date":"2018-01-11 03:40:00+00:00","close_date":"2018-01-11 04:25:00+00:00","open_rate":3.651e-05,"close_rate":3.2859000000000005e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.10448878,"profit_abs":-3.650999999999996e-06,"exit_reason":"stop_loss","initial_stop_loss_abs":3.2859000000000005e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.2859000000000005e-05,"stop_loss_ratio":0.1,"min_rate":3.2859000000000005e-05,"max_rate":3.651e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515642000000.0,"close_timestamp":1515644700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011332594070446804,"open_date":"2018-01-11 03:55:00+00:00","close_date":"2018-01-11 04:25:00+00:00","open_rate":0.08824105,"close_rate":0.08956798308270676,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.0013269330827067605,"exit_reason":"roi","initial_stop_loss_abs":0.079416945,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.079416945,"stop_loss_ratio":0.1,"min_rate":0.08824105,"max_rate":0.08956798308270676,"is_open":false,"buy_tag":null,"open_timestamp":1515642900000.0,"close_timestamp":1515644700000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.411522633744856,"open_date":"2018-01-11 04:00:00+00:00","close_date":"2018-01-11 04:50:00+00:00","open_rate":0.00243,"close_rate":0.002442180451127819,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":-0.0,"profit_abs":1.2180451127819219e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002187,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002187,"stop_loss_ratio":0.1,"min_rate":0.00243,"max_rate":0.002442180451127819,"is_open":false,"buy_tag":null,"open_timestamp":1515643200000.0,"close_timestamp":1515646200000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022001890402423376,"open_date":"2018-01-11 04:30:00+00:00","close_date":"2018-01-11 04:55:00+00:00","open_rate":0.04545064,"close_rate":0.046589753784461146,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":0.001139113784461146,"exit_reason":"roi","initial_stop_loss_abs":0.040905576,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.040905576,"stop_loss_ratio":0.1,"min_rate":0.04545064,"max_rate":0.046589753784461146,"is_open":false,"buy_tag":null,"open_timestamp":1515645000000.0,"close_timestamp":1515646500000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":29.655990510083036,"open_date":"2018-01-11 04:30:00+00:00","close_date":"2018-01-11 04:50:00+00:00","open_rate":3.372e-05,"close_rate":3.456511278195488e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":8.4511278195488e-07,"exit_reason":"roi","initial_stop_loss_abs":3.0348e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.0348e-05,"stop_loss_ratio":0.1,"min_rate":3.372e-05,"max_rate":3.456511278195488e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515645000000.0,"close_timestamp":1515646200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.037821482602118005,"open_date":"2018-01-11 04:55:00+00:00","close_date":"2018-01-11 05:15:00+00:00","open_rate":0.02644,"close_rate":0.02710265664160401,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":0.0006626566416040071,"exit_reason":"roi","initial_stop_loss_abs":0.023796,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.023796,"stop_loss_ratio":0.1,"min_rate":0.02644,"max_rate":0.02710265664160401,"is_open":false,"buy_tag":null,"open_timestamp":1515646500000.0,"close_timestamp":1515647700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011348161597821153,"open_date":"2018-01-11 11:20:00+00:00","close_date":"2018-01-11 12:00:00+00:00","open_rate":0.08812,"close_rate":0.08856170426065162,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004417042606516125,"exit_reason":"roi","initial_stop_loss_abs":0.079308,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.079308,"stop_loss_ratio":0.1,"min_rate":0.08812,"max_rate":0.08856170426065162,"is_open":false,"buy_tag":null,"open_timestamp":1515669600000.0,"close_timestamp":1515672000000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.037263696923919086,"open_date":"2018-01-11 11:35:00+00:00","close_date":"2018-01-11 12:15:00+00:00","open_rate":0.02683577,"close_rate":0.026970285137844607,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00013451513784460897,"exit_reason":"roi","initial_stop_loss_abs":0.024152193,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.024152193,"stop_loss_ratio":0.1,"min_rate":0.02683577,"max_rate":0.026970285137844607,"is_open":false,"buy_tag":null,"open_timestamp":1515670500000.0,"close_timestamp":1515672900000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":20.329335230737954,"open_date":"2018-01-11 14:00:00+00:00","close_date":"2018-01-11 14:25:00+00:00","open_rate":4.919e-05,"close_rate":5.04228320802005e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":1.232832080200495e-06,"exit_reason":"roi","initial_stop_loss_abs":4.4271000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4271000000000004e-05,"stop_loss_ratio":0.1,"min_rate":4.919e-05,"max_rate":5.04228320802005e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515679200000.0,"close_timestamp":1515680700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.01138317402960718,"open_date":"2018-01-11 19:25:00+00:00","close_date":"2018-01-11 20:35:00+00:00","open_rate":0.08784896,"close_rate":0.08828930566416039,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":70,"profit_ratio":-0.0,"profit_abs":0.0004403456641603881,"exit_reason":"roi","initial_stop_loss_abs":0.079064064,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.079064064,"stop_loss_ratio":0.1,"min_rate":0.08784896,"max_rate":0.08828930566416039,"is_open":false,"buy_tag":null,"open_timestamp":1515698700000.0,"close_timestamp":1515702900000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.58863858961802,"open_date":"2018-01-11 22:35:00+00:00","close_date":"2018-01-11 23:30:00+00:00","open_rate":5.105e-05,"close_rate":5.130588972431077e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.558897243107704e-07,"exit_reason":"roi","initial_stop_loss_abs":4.5945e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.5945e-05,"stop_loss_ratio":0.1,"min_rate":5.105e-05,"max_rate":5.130588972431077e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515710100000.0,"close_timestamp":1515713400000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":25.252525252525253,"open_date":"2018-01-11 22:55:00+00:00","close_date":"2018-01-11 23:25:00+00:00","open_rate":3.96e-05,"close_rate":4.019548872180451e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":5.954887218045116e-07,"exit_reason":"roi","initial_stop_loss_abs":3.5640000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.5640000000000004e-05,"stop_loss_ratio":0.1,"min_rate":3.96e-05,"max_rate":4.019548872180451e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515711300000.0,"close_timestamp":1515713100000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":34.66204506065858,"open_date":"2018-01-11 22:55:00+00:00","close_date":"2018-01-11 23:35:00+00:00","open_rate":2.885e-05,"close_rate":2.899461152882205e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.4461152882205115e-07,"exit_reason":"roi","initial_stop_loss_abs":2.5965e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.5965e-05,"stop_loss_ratio":0.1,"min_rate":2.885e-05,"max_rate":2.899461152882205e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515711300000.0,"close_timestamp":1515713700000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03780718336483932,"open_date":"2018-01-11 23:30:00+00:00","close_date":"2018-01-12 00:05:00+00:00","open_rate":0.02645,"close_rate":0.026847744360902256,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0003977443609022545,"exit_reason":"roi","initial_stop_loss_abs":0.023805000000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.023805000000000003,"stop_loss_ratio":0.1,"min_rate":0.02645,"max_rate":0.026847744360902256,"is_open":false,"buy_tag":null,"open_timestamp":1515713400000.0,"close_timestamp":1515715500000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.020833333333333332,"open_date":"2018-01-11 23:55:00+00:00","close_date":"2018-01-12 01:15:00+00:00","open_rate":0.048,"close_rate":0.04824060150375939,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.0,"profit_abs":0.00024060150375938838,"exit_reason":"roi","initial_stop_loss_abs":0.0432,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0432,"stop_loss_ratio":0.1,"min_rate":0.048,"max_rate":0.04824060150375939,"is_open":false,"buy_tag":null,"open_timestamp":1515714900000.0,"close_timestamp":1515719700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":21.31287297527707,"open_date":"2018-01-12 21:15:00+00:00","close_date":"2018-01-12 21:40:00+00:00","open_rate":4.692e-05,"close_rate":4.809593984962405e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":1.1759398496240516e-06,"exit_reason":"roi","initial_stop_loss_abs":4.2227999999999996e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.2227999999999996e-05,"stop_loss_ratio":0.1,"min_rate":4.692e-05,"max_rate":4.809593984962405e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515791700000.0,"close_timestamp":1515793200000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38915654211062944,"open_date":"2018-01-13 00:55:00+00:00","close_date":"2018-01-13 06:20:00+00:00","open_rate":0.00256966,"close_rate":0.0025825405012531327,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":325,"profit_ratio":-0.0,"profit_abs":1.2880501253132587e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002312694,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002312694,"stop_loss_ratio":0.1,"min_rate":0.00256966,"max_rate":0.0025825405012531327,"is_open":false,"buy_tag":null,"open_timestamp":1515804900000.0,"close_timestamp":1515824400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":15.96933886937081,"open_date":"2018-01-13 10:55:00+00:00","close_date":"2018-01-13 11:35:00+00:00","open_rate":6.262e-05,"close_rate":6.293388471177944e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":3.138847117794446e-07,"exit_reason":"roi","initial_stop_loss_abs":5.6358e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.6358e-05,"stop_loss_ratio":0.1,"min_rate":6.262e-05,"max_rate":6.293388471177944e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515840900000.0,"close_timestamp":1515843300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":21.141649048625794,"open_date":"2018-01-13 13:05:00+00:00","close_date":"2018-01-15 14:10:00+00:00","open_rate":4.73e-05,"close_rate":4.753709273182957e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":2945,"profit_ratio":0.0,"profit_abs":2.3709273182957117e-07,"exit_reason":"roi","initial_stop_loss_abs":4.257e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.257e-05,"stop_loss_ratio":0.1,"min_rate":4.73e-05,"max_rate":4.753709273182957e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515848700000.0,"close_timestamp":1516025400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":16.49348507339601,"open_date":"2018-01-13 13:30:00+00:00","close_date":"2018-01-13 14:45:00+00:00","open_rate":6.063e-05,"close_rate":6.0933909774436085e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":75,"profit_ratio":-0.0,"profit_abs":3.039097744360846e-07,"exit_reason":"roi","initial_stop_loss_abs":5.4567e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.4567e-05,"stop_loss_ratio":0.1,"min_rate":6.063e-05,"max_rate":6.0933909774436085e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515850200000.0,"close_timestamp":1515854700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":9.023641941887746,"open_date":"2018-01-13 13:40:00+00:00","close_date":"2018-01-13 23:30:00+00:00","open_rate":0.00011082,"close_rate":0.00011137548872180448,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":590,"profit_ratio":-0.0,"profit_abs":5.554887218044781e-07,"exit_reason":"roi","initial_stop_loss_abs":9.9738e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":9.9738e-05,"stop_loss_ratio":0.1,"min_rate":0.00011082,"max_rate":0.00011137548872180448,"is_open":false,"buy_tag":null,"open_timestamp":1515850800000.0,"close_timestamp":1515886200000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":16.863406408094438,"open_date":"2018-01-13 15:15:00+00:00","close_date":"2018-01-13 15:55:00+00:00","open_rate":5.93e-05,"close_rate":5.9597243107769415e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.9724310776941686e-07,"exit_reason":"roi","initial_stop_loss_abs":5.337e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.337e-05,"stop_loss_ratio":0.1,"min_rate":5.93e-05,"max_rate":5.9597243107769415e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515856500000.0,"close_timestamp":1515858900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.020618543947292404,"open_date":"2018-01-13 16:30:00+00:00","close_date":"2018-01-13 17:10:00+00:00","open_rate":0.04850003,"close_rate":0.04874313791979949,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00024310791979949287,"exit_reason":"roi","initial_stop_loss_abs":0.043650027,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.043650027,"stop_loss_ratio":0.1,"min_rate":0.04850003,"max_rate":0.04874313791979949,"is_open":false,"buy_tag":null,"open_timestamp":1515861000000.0,"close_timestamp":1515863400000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010178097365511457,"open_date":"2018-01-13 22:05:00+00:00","close_date":"2018-01-14 06:25:00+00:00","open_rate":0.09825019,"close_rate":0.09874267215538848,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":500,"profit_ratio":-0.0,"profit_abs":0.0004924821553884823,"exit_reason":"roi","initial_stop_loss_abs":0.088425171,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.088425171,"stop_loss_ratio":0.1,"min_rate":0.09825019,"max_rate":0.09874267215538848,"is_open":false,"buy_tag":null,"open_timestamp":1515881100000.0,"close_timestamp":1515911100000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":16.616816218012627,"open_date":"2018-01-14 00:20:00+00:00","close_date":"2018-01-14 22:55:00+00:00","open_rate":6.018e-05,"close_rate":6.048165413533834e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":1355,"profit_ratio":0.0,"profit_abs":3.0165413533833987e-07,"exit_reason":"roi","initial_stop_loss_abs":5.4162e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.4162e-05,"stop_loss_ratio":0.1,"min_rate":6.018e-05,"max_rate":6.048165413533834e-05,"is_open":false,"buy_tag":null,"open_timestamp":1515889200000.0,"close_timestamp":1515970500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010246952581919518,"open_date":"2018-01-14 12:45:00+00:00","close_date":"2018-01-14 13:25:00+00:00","open_rate":0.09758999,"close_rate":0.0980791628822055,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004891728822054991,"exit_reason":"roi","initial_stop_loss_abs":0.087830991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.087830991,"stop_loss_ratio":0.1,"min_rate":0.09758999,"max_rate":0.0980791628822055,"is_open":false,"buy_tag":null,"open_timestamp":1515933900000.0,"close_timestamp":1515936300000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3215434083601286,"open_date":"2018-01-14 15:30:00+00:00","close_date":"2018-01-14 16:00:00+00:00","open_rate":0.00311,"close_rate":0.0031567669172932328,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.676691729323286e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002799,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002799,"stop_loss_ratio":0.1,"min_rate":0.00311,"max_rate":0.0031567669172932328,"is_open":false,"buy_tag":null,"open_timestamp":1515943800000.0,"close_timestamp":1515945600000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.32010140812609433,"open_date":"2018-01-14 20:45:00+00:00","close_date":"2018-01-14 22:15:00+00:00","open_rate":0.00312401,"close_rate":0.003139669197994987,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":90,"profit_ratio":-0.0,"profit_abs":1.5659197994987058e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002811609,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002811609,"stop_loss_ratio":0.1,"min_rate":0.00312401,"max_rate":0.003139669197994987,"is_open":false,"buy_tag":null,"open_timestamp":1515962700000.0,"close_timestamp":1515968100000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.057247866085791646,"open_date":"2018-01-14 23:35:00+00:00","close_date":"2018-01-15 00:30:00+00:00","open_rate":0.0174679,"close_rate":0.017555458395989976,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":0.0,"profit_abs":8.755839598997492e-05,"exit_reason":"roi","initial_stop_loss_abs":0.015721110000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.015721110000000003,"stop_loss_ratio":0.1,"min_rate":0.0174679,"max_rate":0.017555458395989976,"is_open":false,"buy_tag":null,"open_timestamp":1515972900000.0,"close_timestamp":1515976200000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.013611282991367997,"open_date":"2018-01-14 23:45:00+00:00","close_date":"2018-01-15 00:25:00+00:00","open_rate":0.07346846,"close_rate":0.07383672295739348,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00036826295739347814,"exit_reason":"roi","initial_stop_loss_abs":0.066121614,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.066121614,"stop_loss_ratio":0.1,"min_rate":0.07346846,"max_rate":0.07383672295739348,"is_open":false,"buy_tag":null,"open_timestamp":1515973500000.0,"close_timestamp":1515975900000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010204706410596568,"open_date":"2018-01-15 02:25:00+00:00","close_date":"2018-01-15 03:05:00+00:00","open_rate":0.097994,"close_rate":0.09848519799498744,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004911979949874384,"exit_reason":"roi","initial_stop_loss_abs":0.0881946,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0881946,"stop_loss_ratio":0.1,"min_rate":0.097994,"max_rate":0.09848519799498744,"is_open":false,"buy_tag":null,"open_timestamp":1515983100000.0,"close_timestamp":1515985500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010353038616834042,"open_date":"2018-01-15 07:20:00+00:00","close_date":"2018-01-15 08:00:00+00:00","open_rate":0.09659,"close_rate":0.09707416040100247,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004841604010024786,"exit_reason":"roi","initial_stop_loss_abs":0.086931,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.086931,"stop_loss_ratio":0.1,"min_rate":0.09659,"max_rate":0.09707416040100247,"is_open":false,"buy_tag":null,"open_timestamp":1516000800000.0,"close_timestamp":1516003200000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.013016921998599,"open_date":"2018-01-15 08:20:00+00:00","close_date":"2018-01-15 08:55:00+00:00","open_rate":9.987e-05,"close_rate":0.00010137180451127818,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":1.501804511278178e-06,"exit_reason":"roi","initial_stop_loss_abs":8.9883e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.9883e-05,"stop_loss_ratio":0.1,"min_rate":9.987e-05,"max_rate":0.00010137180451127818,"is_open":false,"buy_tag":null,"open_timestamp":1516004400000.0,"close_timestamp":1516006500000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010537752023511832,"open_date":"2018-01-15 12:10:00+00:00","close_date":"2018-01-16 02:50:00+00:00","open_rate":0.0948969,"close_rate":0.09537257368421052,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":880,"profit_ratio":0.0,"profit_abs":0.0004756736842105175,"exit_reason":"roi","initial_stop_loss_abs":0.08540721000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08540721000000001,"stop_loss_ratio":0.1,"min_rate":0.0948969,"max_rate":0.09537257368421052,"is_open":false,"buy_tag":null,"open_timestamp":1516018200000.0,"close_timestamp":1516071000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014084507042253523,"open_date":"2018-01-15 14:10:00+00:00","close_date":"2018-01-15 17:40:00+00:00","open_rate":0.071,"close_rate":0.07135588972431077,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":210,"profit_ratio":-0.0,"profit_abs":0.00035588972431077615,"exit_reason":"roi","initial_stop_loss_abs":0.0639,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0639,"stop_loss_ratio":0.1,"min_rate":0.071,"max_rate":0.07135588972431077,"is_open":false,"buy_tag":null,"open_timestamp":1516025400000.0,"close_timestamp":1516038000000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.021736763017766978,"open_date":"2018-01-15 14:30:00+00:00","close_date":"2018-01-15 15:10:00+00:00","open_rate":0.04600501,"close_rate":0.046235611553884705,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00023060155388470588,"exit_reason":"roi","initial_stop_loss_abs":0.041404509,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.041404509,"stop_loss_ratio":0.1,"min_rate":0.04600501,"max_rate":0.046235611553884705,"is_open":false,"buy_tag":null,"open_timestamp":1516026600000.0,"close_timestamp":1516029000000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.595465140919686,"open_date":"2018-01-15 18:10:00+00:00","close_date":"2018-01-15 19:25:00+00:00","open_rate":9.438e-05,"close_rate":9.485308270676693e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":75,"profit_ratio":-0.0,"profit_abs":4.7308270676692514e-07,"exit_reason":"roi","initial_stop_loss_abs":8.4942e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.4942e-05,"stop_loss_ratio":0.1,"min_rate":9.438e-05,"max_rate":9.485308270676693e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516039800000.0,"close_timestamp":1516044300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.032894726021471705,"open_date":"2018-01-15 18:35:00+00:00","close_date":"2018-01-15 19:15:00+00:00","open_rate":0.03040001,"close_rate":0.030552391002506264,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0001523810025062626,"exit_reason":"roi","initial_stop_loss_abs":0.027360009,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.027360009,"stop_loss_ratio":0.1,"min_rate":0.03040001,"max_rate":0.030552391002506264,"is_open":false,"buy_tag":null,"open_timestamp":1516041300000.0,"close_timestamp":1516043700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.13208840157615,"open_date":"2018-01-15 20:25:00+00:00","close_date":"2018-01-16 08:25:00+00:00","open_rate":5.837e-05,"close_rate":5.2533e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":720,"profit_ratio":-0.10448878,"profit_abs":-5.8369999999999985e-06,"exit_reason":"stop_loss","initial_stop_loss_abs":5.2533e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.2533e-05,"stop_loss_ratio":0.1,"min_rate":5.2533e-05,"max_rate":5.837e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516047900000.0,"close_timestamp":1516091100000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.021722130506560085,"open_date":"2018-01-15 20:40:00+00:00","close_date":"2018-01-15 22:00:00+00:00","open_rate":0.046036,"close_rate":0.04626675689223057,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.0,"profit_abs":0.00023075689223057277,"exit_reason":"roi","initial_stop_loss_abs":0.0414324,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0414324,"stop_loss_ratio":0.1,"min_rate":0.046036,"max_rate":0.04626675689223057,"is_open":false,"buy_tag":null,"open_timestamp":1516048800000.0,"close_timestamp":1516053600000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.34861425832316545,"open_date":"2018-01-16 00:30:00+00:00","close_date":"2018-01-16 01:10:00+00:00","open_rate":0.0028685,"close_rate":0.0028828784461152877,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.4378446115287727e-05,"exit_reason":"roi","initial_stop_loss_abs":0.00258165,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.00258165,"stop_loss_ratio":0.1,"min_rate":0.0028685,"max_rate":0.0028828784461152877,"is_open":false,"buy_tag":null,"open_timestamp":1516062600000.0,"close_timestamp":1516065000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014854967241083492,"open_date":"2018-01-16 01:15:00+00:00","close_date":"2018-01-16 02:35:00+00:00","open_rate":0.06731755,"close_rate":0.0676549813283208,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":0.0,"profit_abs":0.00033743132832080025,"exit_reason":"roi","initial_stop_loss_abs":0.060585795000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060585795000000005,"stop_loss_ratio":0.1,"min_rate":0.06731755,"max_rate":0.0676549813283208,"is_open":false,"buy_tag":null,"open_timestamp":1516065300000.0,"close_timestamp":1516070100000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010848794492804754,"open_date":"2018-01-16 07:45:00+00:00","close_date":"2018-01-16 08:40:00+00:00","open_rate":0.09217614,"close_rate":0.09263817578947368,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":0.0,"profit_abs":0.0004620357894736804,"exit_reason":"roi","initial_stop_loss_abs":0.082958526,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.082958526,"stop_loss_ratio":0.1,"min_rate":0.09217614,"max_rate":0.09263817578947368,"is_open":false,"buy_tag":null,"open_timestamp":1516088700000.0,"close_timestamp":1516092000000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06060606060606061,"open_date":"2018-01-16 08:35:00+00:00","close_date":"2018-01-16 08:55:00+00:00","open_rate":0.0165,"close_rate":0.016913533834586467,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":0.00041353383458646656,"exit_reason":"roi","initial_stop_loss_abs":0.01485,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.01485,"stop_loss_ratio":0.1,"min_rate":0.0165,"max_rate":0.016913533834586467,"is_open":false,"buy_tag":null,"open_timestamp":1516091700000.0,"close_timestamp":1516092900000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":12.57387149503332,"open_date":"2018-01-16 08:35:00+00:00","close_date":"2018-01-16 08:40:00+00:00","open_rate":7.953e-05,"close_rate":8.311781954887218e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":3.587819548872171e-06,"exit_reason":"roi","initial_stop_loss_abs":7.157700000000001e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":7.157700000000001e-05,"stop_loss_ratio":0.1,"min_rate":7.953e-05,"max_rate":8.311781954887218e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516091700000.0,"close_timestamp":1516092000000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022122914915269236,"open_date":"2018-01-16 08:45:00+00:00","close_date":"2018-01-16 09:50:00+00:00","open_rate":0.045202,"close_rate":0.04542857644110275,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":65,"profit_ratio":-0.0,"profit_abs":0.00022657644110275071,"exit_reason":"roi","initial_stop_loss_abs":0.0406818,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0406818,"stop_loss_ratio":0.1,"min_rate":0.045202,"max_rate":0.04542857644110275,"is_open":false,"buy_tag":null,"open_timestamp":1516092300000.0,"close_timestamp":1516096200000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.054878048780488,"open_date":"2018-01-16 09:15:00+00:00","close_date":"2018-01-16 09:45:00+00:00","open_rate":5.248e-05,"close_rate":5.326917293233082e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":7.891729323308177e-07,"exit_reason":"roi","initial_stop_loss_abs":4.7232e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7232e-05,"stop_loss_ratio":0.1,"min_rate":5.248e-05,"max_rate":5.326917293233082e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516094100000.0,"close_timestamp":1516095900000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03457434486802627,"open_date":"2018-01-16 09:15:00+00:00","close_date":"2018-01-16 09:55:00+00:00","open_rate":0.02892318,"close_rate":0.02906815834586466,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.0001449783458646603,"exit_reason":"roi","initial_stop_loss_abs":0.026030862000000002,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.026030862000000002,"stop_loss_ratio":0.1,"min_rate":0.02892318,"max_rate":0.02906815834586466,"is_open":false,"buy_tag":null,"open_timestamp":1516094100000.0,"close_timestamp":1516096500000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.38735944164405,"open_date":"2018-01-16 09:50:00+00:00","close_date":"2018-01-16 10:10:00+00:00","open_rate":5.158e-05,"close_rate":5.287273182957392e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":1.2927318295739246e-06,"exit_reason":"roi","initial_stop_loss_abs":4.6422e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6422e-05,"stop_loss_ratio":0.1,"min_rate":5.158e-05,"max_rate":5.287273182957392e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516096200000.0,"close_timestamp":1516097400000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.035357778286929785,"open_date":"2018-01-16 10:05:00+00:00","close_date":"2018-01-16 10:35:00+00:00","open_rate":0.02828232,"close_rate":0.02870761804511278,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.00042529804511277913,"exit_reason":"roi","initial_stop_loss_abs":0.025454088,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025454088,"stop_loss_ratio":0.1,"min_rate":0.02828232,"max_rate":0.02870761804511278,"is_open":false,"buy_tag":null,"open_timestamp":1516097100000.0,"close_timestamp":1516098900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022948496230938982,"open_date":"2018-01-16 10:05:00+00:00","close_date":"2018-01-16 10:40:00+00:00","open_rate":0.04357584,"close_rate":0.044231115789473675,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0006552757894736777,"exit_reason":"roi","initial_stop_loss_abs":0.039218256,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.039218256,"stop_loss_ratio":0.1,"min_rate":0.04357584,"max_rate":0.044231115789473675,"is_open":false,"buy_tag":null,"open_timestamp":1516097100000.0,"close_timestamp":1516099200000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.64975755315181,"open_date":"2018-01-16 13:45:00+00:00","close_date":"2018-01-16 14:20:00+00:00","open_rate":5.362e-05,"close_rate":5.442631578947368e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":8.063157894736843e-07,"exit_reason":"roi","initial_stop_loss_abs":4.8258e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.8258e-05,"stop_loss_ratio":0.1,"min_rate":5.362e-05,"max_rate":5.442631578947368e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516110300000.0,"close_timestamp":1516112400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.86080724254998,"open_date":"2018-01-16 17:30:00+00:00","close_date":"2018-01-16 18:25:00+00:00","open_rate":5.302e-05,"close_rate":5.328576441102756e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.6576441102756397e-07,"exit_reason":"roi","initial_stop_loss_abs":4.7718e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7718e-05,"stop_loss_ratio":0.1,"min_rate":5.302e-05,"max_rate":5.328576441102756e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516123800000.0,"close_timestamp":1516127100000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010952903718828448,"open_date":"2018-01-16 18:15:00+00:00","close_date":"2018-01-16 18:45:00+00:00","open_rate":0.09129999,"close_rate":0.09267292218045112,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.0013729321804511196,"exit_reason":"roi","initial_stop_loss_abs":0.082169991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.082169991,"stop_loss_ratio":0.1,"min_rate":0.09129999,"max_rate":0.09267292218045112,"is_open":false,"buy_tag":null,"open_timestamp":1516126500000.0,"close_timestamp":1516128300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":26.26050420168067,"open_date":"2018-01-16 18:15:00+00:00","close_date":"2018-01-16 18:35:00+00:00","open_rate":3.808e-05,"close_rate":3.903438596491228e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":9.543859649122774e-07,"exit_reason":"roi","initial_stop_loss_abs":3.4272e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.4272e-05,"stop_loss_ratio":0.1,"min_rate":3.808e-05,"max_rate":3.903438596491228e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516126500000.0,"close_timestamp":1516127700000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.035574376772493324,"open_date":"2018-01-16 19:00:00+00:00","close_date":"2018-01-16 19:30:00+00:00","open_rate":0.02811012,"close_rate":0.028532828571428567,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":0.00042270857142856846,"exit_reason":"roi","initial_stop_loss_abs":0.025299108,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025299108,"stop_loss_ratio":0.1,"min_rate":0.02811012,"max_rate":0.028532828571428567,"is_open":false,"buy_tag":null,"open_timestamp":1516129200000.0,"close_timestamp":1516131000000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.387028357567759,"open_date":"2018-01-16 21:25:00+00:00","close_date":"2018-01-16 22:25:00+00:00","open_rate":0.00258379,"close_rate":0.002325411,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.10448878,"profit_abs":-0.000258379,"exit_reason":"stop_loss","initial_stop_loss_abs":0.002325411,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002325411,"stop_loss_ratio":0.1,"min_rate":0.002325411,"max_rate":0.00258379,"is_open":false,"buy_tag":null,"open_timestamp":1516137900000.0,"close_timestamp":1516141500000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":39.07776475185619,"open_date":"2018-01-16 21:25:00+00:00","close_date":"2018-01-16 22:45:00+00:00","open_rate":2.559e-05,"close_rate":2.3031e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.10448878,"profit_abs":-2.5590000000000004e-06,"exit_reason":"stop_loss","initial_stop_loss_abs":2.3031e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.3031e-05,"stop_loss_ratio":0.1,"min_rate":2.3031e-05,"max_rate":2.559e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516137900000.0,"close_timestamp":1516142700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":13.123359580052494,"open_date":"2018-01-16 21:35:00+00:00","close_date":"2018-01-16 22:25:00+00:00","open_rate":7.62e-05,"close_rate":6.858e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":-0.10448878,"profit_abs":-7.619999999999998e-06,"exit_reason":"stop_loss","initial_stop_loss_abs":6.858e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":6.858e-05,"stop_loss_ratio":0.1,"min_rate":6.858e-05,"max_rate":7.62e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516138500000.0,"close_timestamp":1516141500000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.4350777048780912,"open_date":"2018-01-16 22:30:00+00:00","close_date":"2018-01-16 22:35:00+00:00","open_rate":0.00229844,"close_rate":0.002402129022556391,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":0.00010368902255639091,"exit_reason":"roi","initial_stop_loss_abs":0.0020685960000000002,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0020685960000000002,"stop_loss_ratio":0.1,"min_rate":0.00229844,"max_rate":0.002402129022556391,"is_open":false,"buy_tag":null,"open_timestamp":1516141800000.0,"close_timestamp":1516142100000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06622516556291391,"open_date":"2018-01-16 22:30:00+00:00","close_date":"2018-01-16 22:40:00+00:00","open_rate":0.0151,"close_rate":0.015781203007518795,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":10,"profit_ratio":0.03990025,"profit_abs":0.0006812030075187946,"exit_reason":"roi","initial_stop_loss_abs":0.013590000000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.013590000000000001,"stop_loss_ratio":0.1,"min_rate":0.0151,"max_rate":0.015781203007518795,"is_open":false,"buy_tag":null,"open_timestamp":1516141800000.0,"close_timestamp":1516142400000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.42431134269081283,"open_date":"2018-01-16 22:40:00+00:00","close_date":"2018-01-16 22:45:00+00:00","open_rate":0.00235676,"close_rate":0.00246308,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":0.00010632000000000003,"exit_reason":"roi","initial_stop_loss_abs":0.002121084,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002121084,"stop_loss_ratio":0.1,"min_rate":0.00235676,"max_rate":0.00246308,"is_open":false,"buy_tag":null,"open_timestamp":1516142400000.0,"close_timestamp":1516142700000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.01585559988076589,"open_date":"2018-01-16 22:45:00+00:00","close_date":"2018-01-16 23:05:00+00:00","open_rate":0.0630692,"close_rate":0.06464988170426066,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":0.0015806817042606502,"exit_reason":"roi","initial_stop_loss_abs":0.056762280000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.056762280000000005,"stop_loss_ratio":0.1,"min_rate":0.0630692,"max_rate":0.06464988170426066,"is_open":false,"buy_tag":null,"open_timestamp":1516142700000.0,"close_timestamp":1516143900000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":45.45454545454545,"open_date":"2018-01-16 22:50:00+00:00","close_date":"2018-01-16 22:55:00+00:00","open_rate":2.2e-05,"close_rate":2.299248120300751e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":5,"profit_ratio":0.03990025,"profit_abs":9.924812030075114e-07,"exit_reason":"roi","initial_stop_loss_abs":1.98e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":1.98e-05,"stop_loss_ratio":0.1,"min_rate":2.2e-05,"max_rate":2.299248120300751e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516143000000.0,"close_timestamp":1516143300000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":20.10454362685967,"open_date":"2018-01-17 03:30:00+00:00","close_date":"2018-01-17 04:00:00+00:00","open_rate":4.974e-05,"close_rate":5.048796992481203e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":7.479699248120277e-07,"exit_reason":"roi","initial_stop_loss_abs":4.4766000000000005e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4766000000000005e-05,"stop_loss_ratio":0.1,"min_rate":4.974e-05,"max_rate":5.048796992481203e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516159800000.0,"close_timestamp":1516161600000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":14.068655036578503,"open_date":"2018-01-17 03:55:00+00:00","close_date":"2018-01-17 04:15:00+00:00","open_rate":7.108e-05,"close_rate":7.28614536340852e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":1.7814536340851996e-06,"exit_reason":"roi","initial_stop_loss_abs":6.3972e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":6.3972e-05,"stop_loss_ratio":0.1,"min_rate":7.108e-05,"max_rate":7.28614536340852e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516161300000.0,"close_timestamp":1516162500000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.0231107002542177,"open_date":"2018-01-17 09:35:00+00:00","close_date":"2018-01-17 10:15:00+00:00","open_rate":0.04327,"close_rate":0.04348689223057644,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0002168922305764362,"exit_reason":"roi","initial_stop_loss_abs":0.038943000000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.038943000000000005,"stop_loss_ratio":0.1,"min_rate":0.04327,"max_rate":0.04348689223057644,"is_open":false,"buy_tag":null,"open_timestamp":1516181700000.0,"close_timestamp":1516184100000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":20.012007204322593,"open_date":"2018-01-17 10:20:00+00:00","close_date":"2018-01-17 17:00:00+00:00","open_rate":4.997e-05,"close_rate":5.022047619047618e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":400,"profit_ratio":-0.0,"profit_abs":2.504761904761831e-07,"exit_reason":"roi","initial_stop_loss_abs":4.4973e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4973e-05,"stop_loss_ratio":0.1,"min_rate":4.997e-05,"max_rate":5.022047619047618e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516184400000.0,"close_timestamp":1516208400000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014626687444363738,"open_date":"2018-01-17 10:30:00+00:00","close_date":"2018-01-17 11:25:00+00:00","open_rate":0.06836818,"close_rate":0.06871087764411027,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":0.00034269764411026804,"exit_reason":"roi","initial_stop_loss_abs":0.061531362,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.061531362,"stop_loss_ratio":0.1,"min_rate":0.06836818,"max_rate":0.06871087764411027,"is_open":false,"buy_tag":null,"open_timestamp":1516185000000.0,"close_timestamp":1516188300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":27.548209366391184,"open_date":"2018-01-17 10:30:00+00:00","close_date":"2018-01-17 11:10:00+00:00","open_rate":3.63e-05,"close_rate":3.648195488721804e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.8195488721804031e-07,"exit_reason":"roi","initial_stop_loss_abs":3.2670000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.2670000000000004e-05,"stop_loss_ratio":0.1,"min_rate":3.63e-05,"max_rate":3.648195488721804e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516185000000.0,"close_timestamp":1516187400000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03558718861209965,"open_date":"2018-01-17 12:30:00+00:00","close_date":"2018-01-17 22:05:00+00:00","open_rate":0.0281,"close_rate":0.02824085213032581,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":575,"profit_ratio":-0.0,"profit_abs":0.0001408521303258095,"exit_reason":"roi","initial_stop_loss_abs":0.02529,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.02529,"stop_loss_ratio":0.1,"min_rate":0.0281,"max_rate":0.02824085213032581,"is_open":false,"buy_tag":null,"open_timestamp":1516192200000.0,"close_timestamp":1516226700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011559355963546878,"open_date":"2018-01-17 12:35:00+00:00","close_date":"2018-01-17 16:55:00+00:00","open_rate":0.08651001,"close_rate":0.08694364413533832,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":260,"profit_ratio":-0.0,"profit_abs":0.00043363413533832607,"exit_reason":"roi","initial_stop_loss_abs":0.077859009,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.077859009,"stop_loss_ratio":0.1,"min_rate":0.08651001,"max_rate":0.08694364413533832,"is_open":false,"buy_tag":null,"open_timestamp":1516192500000.0,"close_timestamp":1516208100000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.752529735487308,"open_date":"2018-01-18 05:00:00+00:00","close_date":"2018-01-18 05:55:00+00:00","open_rate":5.633e-05,"close_rate":5.6612355889724306e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.8235588972430847e-07,"exit_reason":"roi","initial_stop_loss_abs":5.0697e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0697e-05,"stop_loss_ratio":0.1,"min_rate":5.633e-05,"max_rate":5.6612355889724306e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516251600000.0,"close_timestamp":1516254900000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.01430923457900944,"open_date":"2018-01-18 05:20:00+00:00","close_date":"2018-01-18 05:55:00+00:00","open_rate":0.06988494,"close_rate":0.07093584135338346,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":35,"profit_ratio":0.00997506,"profit_abs":0.0010509013533834544,"exit_reason":"roi","initial_stop_loss_abs":0.06289644600000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06289644600000001,"stop_loss_ratio":0.1,"min_rate":0.06988494,"max_rate":0.07093584135338346,"is_open":false,"buy_tag":null,"open_timestamp":1516252800000.0,"close_timestamp":1516254900000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.034265103697024,"open_date":"2018-01-18 07:35:00+00:00","close_date":"2018-01-18 08:15:00+00:00","open_rate":5.545e-05,"close_rate":5.572794486215538e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.779448621553787e-07,"exit_reason":"roi","initial_stop_loss_abs":4.9905e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.9905e-05,"stop_loss_ratio":0.1,"min_rate":5.545e-05,"max_rate":5.572794486215538e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516260900000.0,"close_timestamp":1516263300000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06121723118136401,"open_date":"2018-01-18 09:00:00+00:00","close_date":"2018-01-18 09:40:00+00:00","open_rate":0.01633527,"close_rate":0.016417151052631574,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":8.188105263157511e-05,"exit_reason":"roi","initial_stop_loss_abs":0.014701743,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014701743,"stop_loss_ratio":0.1,"min_rate":0.01633527,"max_rate":0.016417151052631574,"is_open":false,"buy_tag":null,"open_timestamp":1516266000000.0,"close_timestamp":1516268400000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3707356136045141,"open_date":"2018-01-18 16:40:00+00:00","close_date":"2018-01-18 17:20:00+00:00","open_rate":0.00269734,"close_rate":0.002710860501253133,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.3520501253133123e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002427606,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002427606,"stop_loss_ratio":0.1,"min_rate":0.00269734,"max_rate":0.002710860501253133,"is_open":false,"buy_tag":null,"open_timestamp":1516293600000.0,"close_timestamp":1516296000000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":22.346368715083802,"open_date":"2018-01-18 18:05:00+00:00","close_date":"2018-01-18 18:30:00+00:00","open_rate":4.475e-05,"close_rate":4.587155388471177e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":1.1215538847117757e-06,"exit_reason":"roi","initial_stop_loss_abs":4.0274999999999996e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.0274999999999996e-05,"stop_loss_ratio":0.1,"min_rate":4.475e-05,"max_rate":4.587155388471177e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516298700000.0,"close_timestamp":1516300200000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":35.842293906810035,"open_date":"2018-01-18 18:25:00+00:00","close_date":"2018-01-18 18:55:00+00:00","open_rate":2.79e-05,"close_rate":2.8319548872180444e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.1954887218044365e-07,"exit_reason":"roi","initial_stop_loss_abs":2.5110000000000002e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.5110000000000002e-05,"stop_loss_ratio":0.1,"min_rate":2.79e-05,"max_rate":2.8319548872180444e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516299900000.0,"close_timestamp":1516301700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.022525942001105574,"open_date":"2018-01-18 20:10:00+00:00","close_date":"2018-01-18 20:50:00+00:00","open_rate":0.04439326,"close_rate":0.04461578260651629,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.00022252260651629135,"exit_reason":"roi","initial_stop_loss_abs":0.039953933999999997,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.039953933999999997,"stop_loss_ratio":0.1,"min_rate":0.04439326,"max_rate":0.04461578260651629,"is_open":false,"buy_tag":null,"open_timestamp":1516306200000.0,"close_timestamp":1516308600000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":22.271714922048996,"open_date":"2018-01-18 21:30:00+00:00","close_date":"2018-01-19 00:35:00+00:00","open_rate":4.49e-05,"close_rate":4.51250626566416e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":185,"profit_ratio":0.0,"profit_abs":2.2506265664159932e-07,"exit_reason":"roi","initial_stop_loss_abs":4.041e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.041e-05,"stop_loss_ratio":0.1,"min_rate":4.49e-05,"max_rate":4.51250626566416e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516311000000.0,"close_timestamp":1516322100000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03502626970227671,"open_date":"2018-01-18 21:55:00+00:00","close_date":"2018-01-19 05:05:00+00:00","open_rate":0.02855,"close_rate":0.028693107769423555,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":430,"profit_ratio":-0.0,"profit_abs":0.00014310776942355607,"exit_reason":"roi","initial_stop_loss_abs":0.025695,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025695,"stop_loss_ratio":0.1,"min_rate":0.02855,"max_rate":0.028693107769423555,"is_open":false,"buy_tag":null,"open_timestamp":1516312500000.0,"close_timestamp":1516338300000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.25327812284334,"open_date":"2018-01-18 22:10:00+00:00","close_date":"2018-01-18 22:50:00+00:00","open_rate":5.796e-05,"close_rate":5.8250526315789473e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":2.905263157894727e-07,"exit_reason":"roi","initial_stop_loss_abs":5.2164000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.2164000000000004e-05,"stop_loss_ratio":0.1,"min_rate":5.796e-05,"max_rate":5.8250526315789473e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516313400000.0,"close_timestamp":1516315800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02303975994413319,"open_date":"2018-01-18 23:50:00+00:00","close_date":"2018-01-19 00:30:00+00:00","open_rate":0.04340323,"close_rate":0.04362079005012531,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.0002175600501253122,"exit_reason":"roi","initial_stop_loss_abs":0.039062907,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.039062907,"stop_loss_ratio":0.1,"min_rate":0.04340323,"max_rate":0.04362079005012531,"is_open":false,"buy_tag":null,"open_timestamp":1516319400000.0,"close_timestamp":1516321800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02244943545282195,"open_date":"2018-01-19 16:45:00+00:00","close_date":"2018-01-19 17:35:00+00:00","open_rate":0.04454455,"close_rate":0.04476783095238095,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":0.0,"profit_abs":0.0002232809523809512,"exit_reason":"roi","initial_stop_loss_abs":0.040090095000000006,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.040090095000000006,"stop_loss_ratio":0.1,"min_rate":0.04454455,"max_rate":0.04476783095238095,"is_open":false,"buy_tag":null,"open_timestamp":1516380300000.0,"close_timestamp":1516383300000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.793594306049823,"open_date":"2018-01-19 17:15:00+00:00","close_date":"2018-01-19 19:55:00+00:00","open_rate":5.62e-05,"close_rate":5.648170426065162e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":160,"profit_ratio":-0.0,"profit_abs":2.817042606516199e-07,"exit_reason":"roi","initial_stop_loss_abs":5.058e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.058e-05,"stop_loss_ratio":0.1,"min_rate":5.62e-05,"max_rate":5.648170426065162e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516382100000.0,"close_timestamp":1516391700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":23.046784973496194,"open_date":"2018-01-19 17:20:00+00:00","close_date":"2018-01-19 20:15:00+00:00","open_rate":4.339e-05,"close_rate":4.360749373433584e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":175,"profit_ratio":-0.0,"profit_abs":2.174937343358337e-07,"exit_reason":"roi","initial_stop_loss_abs":3.9051e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.9051e-05,"stop_loss_ratio":0.1,"min_rate":4.339e-05,"max_rate":4.360749373433584e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516382400000.0,"close_timestamp":1516392900000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":9.910802775024777,"open_date":"2018-01-20 04:45:00+00:00","close_date":"2018-01-20 17:35:00+00:00","open_rate":0.0001009,"close_rate":0.00010140576441102755,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":770,"profit_ratio":0.0,"profit_abs":5.057644110275549e-07,"exit_reason":"roi","initial_stop_loss_abs":9.081e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":9.081e-05,"stop_loss_ratio":0.1,"min_rate":0.0001009,"max_rate":0.00010140576441102755,"is_open":false,"buy_tag":null,"open_timestamp":1516423500000.0,"close_timestamp":1516469700000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3696789338459548,"open_date":"2018-01-20 04:50:00+00:00","close_date":"2018-01-20 15:15:00+00:00","open_rate":0.00270505,"close_rate":0.002718609147869674,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":625,"profit_ratio":-0.0,"profit_abs":1.3559147869673764e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002434545,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002434545,"stop_loss_ratio":0.1,"min_rate":0.00270505,"max_rate":0.002718609147869674,"is_open":false,"buy_tag":null,"open_timestamp":1516423800000.0,"close_timestamp":1516461300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.033333311111125925,"open_date":"2018-01-20 04:50:00+00:00","close_date":"2018-01-20 07:00:00+00:00","open_rate":0.03000002,"close_rate":0.030150396040100245,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":130,"profit_ratio":-0.0,"profit_abs":0.00015037604010024672,"exit_reason":"roi","initial_stop_loss_abs":0.027000018,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.027000018,"stop_loss_ratio":0.1,"min_rate":0.03000002,"max_rate":0.030150396040100245,"is_open":false,"buy_tag":null,"open_timestamp":1516423800000.0,"close_timestamp":1516431600000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.315018315018317,"open_date":"2018-01-20 09:00:00+00:00","close_date":"2018-01-20 09:40:00+00:00","open_rate":5.46e-05,"close_rate":5.4873684210526304e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.736842105263053e-07,"exit_reason":"roi","initial_stop_loss_abs":4.914e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.914e-05,"stop_loss_ratio":0.1,"min_rate":5.46e-05,"max_rate":5.4873684210526304e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516438800000.0,"close_timestamp":1516441200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03244412634781012,"open_date":"2018-01-20 18:25:00+00:00","close_date":"2018-01-25 03:50:00+00:00","open_rate":0.03082222,"close_rate":0.027739998,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":6325,"profit_ratio":-0.10448878,"profit_abs":-0.0030822220000000025,"exit_reason":"stop_loss","initial_stop_loss_abs":0.027739998000000002,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.027739998000000002,"stop_loss_ratio":0.1,"min_rate":0.027739998,"max_rate":0.03082222,"is_open":false,"buy_tag":null,"open_timestamp":1516472700000.0,"close_timestamp":1516852200000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011148273260677065,"open_date":"2018-01-20 22:25:00+00:00","close_date":"2018-01-20 23:15:00+00:00","open_rate":0.08969999,"close_rate":0.09014961401002504,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":-0.0,"profit_abs":0.00044962401002504593,"exit_reason":"roi","initial_stop_loss_abs":0.080729991,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.080729991,"stop_loss_ratio":0.1,"min_rate":0.08969999,"max_rate":0.09014961401002504,"is_open":false,"buy_tag":null,"open_timestamp":1516487100000.0,"close_timestamp":1516490100000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06125570520324337,"open_date":"2018-01-21 02:50:00+00:00","close_date":"2018-01-21 14:30:00+00:00","open_rate":0.01632501,"close_rate":0.01640683962406015,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":700,"profit_ratio":0.0,"profit_abs":8.182962406014932e-05,"exit_reason":"roi","initial_stop_loss_abs":0.014692509000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014692509000000001,"stop_loss_ratio":0.1,"min_rate":0.01632501,"max_rate":0.01640683962406015,"is_open":false,"buy_tag":null,"open_timestamp":1516503000000.0,"close_timestamp":1516545000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.01417675579120474,"open_date":"2018-01-21 10:20:00+00:00","close_date":"2018-01-21 11:00:00+00:00","open_rate":0.070538,"close_rate":0.07089157393483708,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00035357393483707866,"exit_reason":"roi","initial_stop_loss_abs":0.0634842,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0634842,"stop_loss_ratio":0.1,"min_rate":0.070538,"max_rate":0.07089157393483708,"is_open":false,"buy_tag":null,"open_timestamp":1516530000000.0,"close_timestamp":1516532400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.864365214110546,"open_date":"2018-01-21 15:50:00+00:00","close_date":"2018-01-21 18:45:00+00:00","open_rate":5.301e-05,"close_rate":5.327571428571427e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":175,"profit_ratio":-0.0,"profit_abs":2.657142857142672e-07,"exit_reason":"roi","initial_stop_loss_abs":4.7709e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7709e-05,"stop_loss_ratio":0.1,"min_rate":5.301e-05,"max_rate":5.327571428571427e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516549800000.0,"close_timestamp":1516560300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":25.284450063211125,"open_date":"2018-01-21 16:20:00+00:00","close_date":"2018-01-21 17:00:00+00:00","open_rate":3.955e-05,"close_rate":3.9748245614035085e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":1.9824561403508552e-07,"exit_reason":"roi","initial_stop_loss_abs":3.5595e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.5595e-05,"stop_loss_ratio":0.1,"min_rate":3.955e-05,"max_rate":3.9748245614035085e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516551600000.0,"close_timestamp":1516554000000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38683971296493297,"open_date":"2018-01-21 21:15:00+00:00","close_date":"2018-01-21 21:45:00+00:00","open_rate":0.00258505,"close_rate":0.002623922932330827,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":3.8872932330826816e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002326545,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002326545,"stop_loss_ratio":0.1,"min_rate":0.00258505,"max_rate":0.002623922932330827,"is_open":false,"buy_tag":null,"open_timestamp":1516569300000.0,"close_timestamp":1516571100000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":25.621316935690498,"open_date":"2018-01-21 21:15:00+00:00","close_date":"2018-01-21 21:55:00+00:00","open_rate":3.903e-05,"close_rate":3.922563909774435e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.9563909774435151e-07,"exit_reason":"roi","initial_stop_loss_abs":3.5127e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.5127e-05,"stop_loss_ratio":0.1,"min_rate":3.903e-05,"max_rate":3.922563909774435e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516569300000.0,"close_timestamp":1516571700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.098548510313215,"open_date":"2018-01-22 00:35:00+00:00","close_date":"2018-01-22 10:35:00+00:00","open_rate":5.236e-05,"close_rate":5.262245614035087e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":600,"profit_ratio":-0.0,"profit_abs":2.624561403508717e-07,"exit_reason":"roi","initial_stop_loss_abs":4.7124e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7124e-05,"stop_loss_ratio":0.1,"min_rate":5.236e-05,"max_rate":5.262245614035087e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516581300000.0,"close_timestamp":1516617300000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.076650420912717,"open_date":"2018-01-22 01:30:00+00:00","close_date":"2018-01-22 02:10:00+00:00","open_rate":9.028e-05,"close_rate":9.07325313283208e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":4.5253132832080657e-07,"exit_reason":"roi","initial_stop_loss_abs":8.1252e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.1252e-05,"stop_loss_ratio":0.1,"min_rate":9.028e-05,"max_rate":9.07325313283208e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516584600000.0,"close_timestamp":1516587000000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3721622627465575,"open_date":"2018-01-22 12:25:00+00:00","close_date":"2018-01-22 14:35:00+00:00","open_rate":0.002687,"close_rate":0.002700468671679198,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":130,"profit_ratio":-0.0,"profit_abs":1.3468671679197925e-05,"exit_reason":"roi","initial_stop_loss_abs":0.0024183000000000004,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0024183000000000004,"stop_loss_ratio":0.1,"min_rate":0.002687,"max_rate":0.002700468671679198,"is_open":false,"buy_tag":null,"open_timestamp":1516623900000.0,"close_timestamp":1516631700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":23.99232245681382,"open_date":"2018-01-22 13:15:00+00:00","close_date":"2018-01-22 13:55:00+00:00","open_rate":4.168e-05,"close_rate":4.188892230576441e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.0892230576441054e-07,"exit_reason":"roi","initial_stop_loss_abs":3.7512e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.7512e-05,"stop_loss_ratio":0.1,"min_rate":4.168e-05,"max_rate":4.188892230576441e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516626900000.0,"close_timestamp":1516629300000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.336583153837434,"open_date":"2018-01-22 14:00:00+00:00","close_date":"2018-01-22 14:30:00+00:00","open_rate":8.821e-05,"close_rate":8.953646616541353e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":1.326466165413529e-06,"exit_reason":"roi","initial_stop_loss_abs":7.9389e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":7.9389e-05,"stop_loss_ratio":0.1,"min_rate":8.821e-05,"max_rate":8.953646616541353e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516629600000.0,"close_timestamp":1516631400000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.334880123743233,"open_date":"2018-01-22 15:55:00+00:00","close_date":"2018-01-22 16:40:00+00:00","open_rate":5.172e-05,"close_rate":5.1979248120300745e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":2.592481203007459e-07,"exit_reason":"roi","initial_stop_loss_abs":4.6548e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6548e-05,"stop_loss_ratio":0.1,"min_rate":5.172e-05,"max_rate":5.1979248120300745e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516636500000.0,"close_timestamp":1516639200000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":33.04692663582287,"open_date":"2018-01-22 16:05:00+00:00","close_date":"2018-01-22 16:25:00+00:00","open_rate":3.026e-05,"close_rate":3.101839598997494e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":20,"profit_ratio":0.01995012,"profit_abs":7.5839598997494e-07,"exit_reason":"roi","initial_stop_loss_abs":2.7234e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7234e-05,"stop_loss_ratio":0.1,"min_rate":3.026e-05,"max_rate":3.101839598997494e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516637100000.0,"close_timestamp":1516638300000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014156285390713478,"open_date":"2018-01-22 19:50:00+00:00","close_date":"2018-01-23 00:10:00+00:00","open_rate":0.07064,"close_rate":0.07099408521303258,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":260,"profit_ratio":0.0,"profit_abs":0.00035408521303258167,"exit_reason":"roi","initial_stop_loss_abs":0.063576,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.063576,"stop_loss_ratio":0.1,"min_rate":0.07064,"max_rate":0.07099408521303258,"is_open":false,"buy_tag":null,"open_timestamp":1516650600000.0,"close_timestamp":1516666200000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.06080938507725528,"open_date":"2018-01-22 21:25:00+00:00","close_date":"2018-01-22 22:05:00+00:00","open_rate":0.01644483,"close_rate":0.01652726022556391,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":8.243022556390922e-05,"exit_reason":"roi","initial_stop_loss_abs":0.014800347,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014800347,"stop_loss_ratio":0.1,"min_rate":0.01644483,"max_rate":0.01652726022556391,"is_open":false,"buy_tag":null,"open_timestamp":1516656300000.0,"close_timestamp":1516658700000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":23.08935580697299,"open_date":"2018-01-23 00:05:00+00:00","close_date":"2018-01-23 00:35:00+00:00","open_rate":4.331e-05,"close_rate":4.3961278195488714e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":6.512781954887175e-07,"exit_reason":"roi","initial_stop_loss_abs":3.8979e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":3.8979e-05,"stop_loss_ratio":0.1,"min_rate":4.331e-05,"max_rate":4.3961278195488714e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516665900000.0,"close_timestamp":1516667700000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":31.250000000000004,"open_date":"2018-01-23 01:50:00+00:00","close_date":"2018-01-23 02:15:00+00:00","open_rate":3.2e-05,"close_rate":3.2802005012531326e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":25,"profit_ratio":0.01995012,"profit_abs":8.020050125313278e-07,"exit_reason":"roi","initial_stop_loss_abs":2.88e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.88e-05,"stop_loss_ratio":0.1,"min_rate":3.2e-05,"max_rate":3.2802005012531326e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516672200000.0,"close_timestamp":1516673700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010907854156754155,"open_date":"2018-01-23 04:25:00+00:00","close_date":"2018-01-23 05:15:00+00:00","open_rate":0.09167706,"close_rate":0.09213659413533835,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":50,"profit_ratio":0.0,"profit_abs":0.0004595341353383492,"exit_reason":"roi","initial_stop_loss_abs":0.08250935400000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.08250935400000001,"stop_loss_ratio":0.1,"min_rate":0.09167706,"max_rate":0.09213659413533835,"is_open":false,"buy_tag":null,"open_timestamp":1516681500000.0,"close_timestamp":1516684500000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014440474918339115,"open_date":"2018-01-23 07:35:00+00:00","close_date":"2018-01-23 09:00:00+00:00","open_rate":0.0692498,"close_rate":0.06959691679197995,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":85,"profit_ratio":0.0,"profit_abs":0.0003471167919799484,"exit_reason":"roi","initial_stop_loss_abs":0.06232482,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06232482,"stop_loss_ratio":0.1,"min_rate":0.0692498,"max_rate":0.06959691679197995,"is_open":false,"buy_tag":null,"open_timestamp":1516692900000.0,"close_timestamp":1516698000000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":31.426775612822127,"open_date":"2018-01-23 10:50:00+00:00","close_date":"2018-01-23 13:05:00+00:00","open_rate":3.182e-05,"close_rate":3.197949874686716e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":135,"profit_ratio":0.0,"profit_abs":1.594987468671663e-07,"exit_reason":"roi","initial_stop_loss_abs":2.8638e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.8638e-05,"stop_loss_ratio":0.1,"min_rate":3.182e-05,"max_rate":3.197949874686716e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516704600000.0,"close_timestamp":1516712700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024461839530332683,"open_date":"2018-01-23 11:05:00+00:00","close_date":"2018-01-23 16:05:00+00:00","open_rate":0.04088,"close_rate":0.04108491228070175,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":300,"profit_ratio":-0.0,"profit_abs":0.0002049122807017481,"exit_reason":"roi","initial_stop_loss_abs":0.036792,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036792,"stop_loss_ratio":0.1,"min_rate":0.04088,"max_rate":0.04108491228070175,"is_open":false,"buy_tag":null,"open_timestamp":1516705500000.0,"close_timestamp":1516723500000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.417475728155342,"open_date":"2018-01-23 14:55:00+00:00","close_date":"2018-01-23 15:35:00+00:00","open_rate":5.15e-05,"close_rate":5.175814536340851e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.5814536340851513e-07,"exit_reason":"roi","initial_stop_loss_abs":4.635e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.635e-05,"stop_loss_ratio":0.1,"min_rate":5.15e-05,"max_rate":5.175814536340851e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516719300000.0,"close_timestamp":1516721700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.011023294646713328,"open_date":"2018-01-23 16:35:00+00:00","close_date":"2018-01-24 00:05:00+00:00","open_rate":0.09071698,"close_rate":0.09117170170426064,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":450,"profit_ratio":0.0,"profit_abs":0.00045472170426064107,"exit_reason":"roi","initial_stop_loss_abs":0.081645282,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.081645282,"stop_loss_ratio":0.1,"min_rate":0.09071698,"max_rate":0.09117170170426064,"is_open":false,"buy_tag":null,"open_timestamp":1516725300000.0,"close_timestamp":1516752300000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":31.969309462915604,"open_date":"2018-01-23 17:25:00+00:00","close_date":"2018-01-23 18:45:00+00:00","open_rate":3.128e-05,"close_rate":3.1436791979949865e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":80,"profit_ratio":-0.0,"profit_abs":1.5679197994986587e-07,"exit_reason":"roi","initial_stop_loss_abs":2.8152e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.8152e-05,"stop_loss_ratio":0.1,"min_rate":3.128e-05,"max_rate":3.1436791979949865e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516728300000.0,"close_timestamp":1516733100000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.465724751439037,"open_date":"2018-01-23 20:15:00+00:00","close_date":"2018-01-23 22:00:00+00:00","open_rate":9.555e-05,"close_rate":9.602894736842104e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":105,"profit_ratio":-0.0,"profit_abs":4.789473684210343e-07,"exit_reason":"roi","initial_stop_loss_abs":8.5995e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.5995e-05,"stop_loss_ratio":0.1,"min_rate":9.555e-05,"max_rate":9.602894736842104e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516738500000.0,"close_timestamp":1516744800000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02450979791426522,"open_date":"2018-01-23 22:30:00+00:00","close_date":"2018-01-23 23:10:00+00:00","open_rate":0.04080001,"close_rate":0.0410045213283208,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00020451132832080554,"exit_reason":"roi","initial_stop_loss_abs":0.036720009,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036720009,"stop_loss_ratio":0.1,"min_rate":0.04080001,"max_rate":0.0410045213283208,"is_open":false,"buy_tag":null,"open_timestamp":1516746600000.0,"close_timestamp":1516749000000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.368584156498162,"open_date":"2018-01-23 23:50:00+00:00","close_date":"2018-01-24 03:35:00+00:00","open_rate":5.163e-05,"close_rate":5.18887969924812e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":225,"profit_ratio":-0.0,"profit_abs":2.587969924812037e-07,"exit_reason":"roi","initial_stop_loss_abs":4.6467e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6467e-05,"stop_loss_ratio":0.1,"min_rate":5.163e-05,"max_rate":5.18887969924812e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516751400000.0,"close_timestamp":1516764900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024747691102289384,"open_date":"2018-01-24 00:20:00+00:00","close_date":"2018-01-24 01:50:00+00:00","open_rate":0.04040781,"close_rate":0.04061035541353383,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":90,"profit_ratio":0.0,"profit_abs":0.0002025454135338306,"exit_reason":"roi","initial_stop_loss_abs":0.036367029,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036367029,"stop_loss_ratio":0.1,"min_rate":0.04040781,"max_rate":0.04061035541353383,"is_open":false,"buy_tag":null,"open_timestamp":1516753200000.0,"close_timestamp":1516758600000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.485580670303975,"open_date":"2018-01-24 06:45:00+00:00","close_date":"2018-01-24 07:25:00+00:00","open_rate":5.132e-05,"close_rate":5.157724310776942e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":2.5724310776941724e-07,"exit_reason":"roi","initial_stop_loss_abs":4.6188000000000006e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6188000000000006e-05,"stop_loss_ratio":0.1,"min_rate":5.132e-05,"max_rate":5.157724310776942e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516776300000.0,"close_timestamp":1516778700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":19.23816852635629,"open_date":"2018-01-24 14:15:00+00:00","close_date":"2018-01-24 14:25:00+00:00","open_rate":5.198e-05,"close_rate":5.432496240601503e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":10,"profit_ratio":0.03990025,"profit_abs":2.344962406015033e-06,"exit_reason":"roi","initial_stop_loss_abs":4.6782e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6782e-05,"stop_loss_ratio":0.1,"min_rate":5.198e-05,"max_rate":5.432496240601503e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516803300000.0,"close_timestamp":1516803900000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":32.74394237066143,"open_date":"2018-01-24 14:50:00+00:00","close_date":"2018-01-24 16:35:00+00:00","open_rate":3.054e-05,"close_rate":3.069308270676692e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":105,"profit_ratio":-0.0,"profit_abs":1.5308270676691466e-07,"exit_reason":"roi","initial_stop_loss_abs":2.7486000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.7486000000000004e-05,"stop_loss_ratio":0.1,"min_rate":3.054e-05,"max_rate":3.069308270676692e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516805400000.0,"close_timestamp":1516811700000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":10.795638562020944,"open_date":"2018-01-24 15:10:00+00:00","close_date":"2018-01-24 16:15:00+00:00","open_rate":9.263e-05,"close_rate":9.309431077694236e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":65,"profit_ratio":0.0,"profit_abs":4.6431077694236234e-07,"exit_reason":"roi","initial_stop_loss_abs":8.3367e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.3367e-05,"stop_loss_ratio":0.1,"min_rate":9.263e-05,"max_rate":9.309431077694236e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516806600000.0,"close_timestamp":1516810500000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":18.13565469713457,"open_date":"2018-01-24 22:40:00+00:00","close_date":"2018-01-24 23:25:00+00:00","open_rate":5.514e-05,"close_rate":5.54163909774436e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":2.7639097744360576e-07,"exit_reason":"roi","initial_stop_loss_abs":4.9625999999999995e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.9625999999999995e-05,"stop_loss_ratio":0.1,"min_rate":5.514e-05,"max_rate":5.54163909774436e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516833600000.0,"close_timestamp":1516836300000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":20.3210729526519,"open_date":"2018-01-25 00:50:00+00:00","close_date":"2018-01-25 01:30:00+00:00","open_rate":4.921e-05,"close_rate":4.9456666666666664e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":2.4666666666666543e-07,"exit_reason":"roi","initial_stop_loss_abs":4.4289e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.4289e-05,"stop_loss_ratio":0.1,"min_rate":4.921e-05,"max_rate":4.9456666666666664e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516841400000.0,"close_timestamp":1516843800000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38461538461538464,"open_date":"2018-01-25 08:15:00+00:00","close_date":"2018-01-25 12:15:00+00:00","open_rate":0.0026,"close_rate":0.002613032581453634,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":240,"profit_ratio":0.0,"profit_abs":1.3032581453634e-05,"exit_reason":"roi","initial_stop_loss_abs":0.00234,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.00234,"stop_loss_ratio":0.1,"min_rate":0.0026,"max_rate":0.002613032581453634,"is_open":false,"buy_tag":null,"open_timestamp":1516868100000.0,"close_timestamp":1516882500000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03571593119825878,"open_date":"2018-01-25 10:25:00+00:00","close_date":"2018-01-25 16:15:00+00:00","open_rate":0.02799871,"close_rate":0.028139054411027563,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":350,"profit_ratio":-0.0,"profit_abs":0.00014034441102756326,"exit_reason":"roi","initial_stop_loss_abs":0.025198839,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025198839,"stop_loss_ratio":0.1,"min_rate":0.02799871,"max_rate":0.028139054411027563,"is_open":false,"buy_tag":null,"open_timestamp":1516875900000.0,"close_timestamp":1516896900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024516401717913302,"open_date":"2018-01-25 11:00:00+00:00","close_date":"2018-01-25 11:45:00+00:00","open_rate":0.04078902,"close_rate":0.0409934762406015,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":0.00020445624060149575,"exit_reason":"roi","initial_stop_loss_abs":0.036710118,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.036710118,"stop_loss_ratio":0.1,"min_rate":0.04078902,"max_rate":0.0409934762406015,"is_open":false,"buy_tag":null,"open_timestamp":1516878000000.0,"close_timestamp":1516880700000.0},{"pair":"NXT/BTC","stake_amount":0.001,"amount":34.602076124567475,"open_date":"2018-01-25 13:05:00+00:00","close_date":"2018-01-25 13:45:00+00:00","open_rate":2.89e-05,"close_rate":2.904486215538847e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":1.4486215538846723e-07,"exit_reason":"roi","initial_stop_loss_abs":2.601e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":2.601e-05,"stop_loss_ratio":0.1,"min_rate":2.89e-05,"max_rate":2.904486215538847e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516885500000.0,"close_timestamp":1516887900000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02432912439481303,"open_date":"2018-01-25 13:20:00+00:00","close_date":"2018-01-25 14:05:00+00:00","open_rate":0.041103,"close_rate":0.04130903007518797,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":0.00020603007518796984,"exit_reason":"roi","initial_stop_loss_abs":0.0369927,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0369927,"stop_loss_ratio":0.1,"min_rate":0.041103,"max_rate":0.04130903007518797,"is_open":false,"buy_tag":null,"open_timestamp":1516886400000.0,"close_timestamp":1516889100000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":18.422991893883566,"open_date":"2018-01-25 15:45:00+00:00","close_date":"2018-01-25 16:15:00+00:00","open_rate":5.428e-05,"close_rate":5.509624060150376e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":8.162406015037611e-07,"exit_reason":"roi","initial_stop_loss_abs":4.8852000000000006e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.8852000000000006e-05,"stop_loss_ratio":0.1,"min_rate":5.428e-05,"max_rate":5.509624060150376e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516895100000.0,"close_timestamp":1516896900000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":18.47063169560399,"open_date":"2018-01-25 17:45:00+00:00","close_date":"2018-01-25 23:15:00+00:00","open_rate":5.414e-05,"close_rate":5.441137844611528e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":330,"profit_ratio":-0.0,"profit_abs":2.713784461152774e-07,"exit_reason":"roi","initial_stop_loss_abs":4.8726e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.8726e-05,"stop_loss_ratio":0.1,"min_rate":5.414e-05,"max_rate":5.441137844611528e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516902300000.0,"close_timestamp":1516922100000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024150056861308878,"open_date":"2018-01-25 21:15:00+00:00","close_date":"2018-01-25 21:55:00+00:00","open_rate":0.04140777,"close_rate":0.0416153277443609,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0002075577443608964,"exit_reason":"roi","initial_stop_loss_abs":0.037266993000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.037266993000000005,"stop_loss_ratio":0.1,"min_rate":0.04140777,"max_rate":0.0416153277443609,"is_open":false,"buy_tag":null,"open_timestamp":1516914900000.0,"close_timestamp":1516917300000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3932224183965176,"open_date":"2018-01-26 02:05:00+00:00","close_date":"2018-01-26 02:45:00+00:00","open_rate":0.00254309,"close_rate":0.002555837318295739,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":1.2747318295739177e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002288781,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002288781,"stop_loss_ratio":0.1,"min_rate":0.00254309,"max_rate":0.002555837318295739,"is_open":false,"buy_tag":null,"open_timestamp":1516932300000.0,"close_timestamp":1516934700000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.834849295523455,"open_date":"2018-01-26 02:55:00+00:00","close_date":"2018-01-26 15:10:00+00:00","open_rate":5.607e-05,"close_rate":5.6351052631578935e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":735,"profit_ratio":-0.0,"profit_abs":2.810526315789381e-07,"exit_reason":"roi","initial_stop_loss_abs":5.0463e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0463e-05,"stop_loss_ratio":0.1,"min_rate":5.607e-05,"max_rate":5.6351052631578935e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516935300000.0,"close_timestamp":1516979400000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.39400171784748983,"open_date":"2018-01-26 06:10:00+00:00","close_date":"2018-01-26 09:25:00+00:00","open_rate":0.00253806,"close_rate":0.0025507821052631577,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":195,"profit_ratio":0.0,"profit_abs":1.2722105263157733e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002284254,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002284254,"stop_loss_ratio":0.1,"min_rate":0.00253806,"max_rate":0.0025507821052631577,"is_open":false,"buy_tag":null,"open_timestamp":1516947000000.0,"close_timestamp":1516958700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.024096385542168672,"open_date":"2018-01-26 07:25:00+00:00","close_date":"2018-01-26 09:55:00+00:00","open_rate":0.0415,"close_rate":0.04170802005012531,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":150,"profit_ratio":-0.0,"profit_abs":0.00020802005012530989,"exit_reason":"roi","initial_stop_loss_abs":0.03735,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.03735,"stop_loss_ratio":0.1,"min_rate":0.0415,"max_rate":0.04170802005012531,"is_open":false,"buy_tag":null,"open_timestamp":1516951500000.0,"close_timestamp":1516960500000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":18.793459875963165,"open_date":"2018-01-26 09:55:00+00:00","close_date":"2018-01-26 10:25:00+00:00","open_rate":5.321e-05,"close_rate":5.401015037593984e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":8.00150375939842e-07,"exit_reason":"roi","initial_stop_loss_abs":4.7889e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.7889e-05,"stop_loss_ratio":0.1,"min_rate":5.321e-05,"max_rate":5.401015037593984e-05,"is_open":false,"buy_tag":null,"open_timestamp":1516960500000.0,"close_timestamp":1516962300000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.036074437437185386,"open_date":"2018-01-26 16:05:00+00:00","close_date":"2018-01-26 16:45:00+00:00","open_rate":0.02772046,"close_rate":0.02785940967418546,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00013894967418546025,"exit_reason":"roi","initial_stop_loss_abs":0.024948414,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.024948414,"stop_loss_ratio":0.1,"min_rate":0.02772046,"max_rate":0.02785940967418546,"is_open":false,"buy_tag":null,"open_timestamp":1516982700000.0,"close_timestamp":1516985100000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010569326272036914,"open_date":"2018-01-26 23:35:00+00:00","close_date":"2018-01-27 00:15:00+00:00","open_rate":0.09461341,"close_rate":0.09508766268170424,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":0.0,"profit_abs":0.00047425268170424306,"exit_reason":"roi","initial_stop_loss_abs":0.085152069,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.085152069,"stop_loss_ratio":0.1,"min_rate":0.09461341,"max_rate":0.09508766268170424,"is_open":false,"buy_tag":null,"open_timestamp":1517009700000.0,"close_timestamp":1517012100000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":17.809439002671414,"open_date":"2018-01-27 00:35:00+00:00","close_date":"2018-01-27 01:30:00+00:00","open_rate":5.615e-05,"close_rate":5.643145363408521e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":55,"profit_ratio":-0.0,"profit_abs":2.814536340852038e-07,"exit_reason":"roi","initial_stop_loss_abs":5.0535e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0535e-05,"stop_loss_ratio":0.1,"min_rate":5.615e-05,"max_rate":5.643145363408521e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517013300000.0,"close_timestamp":1517016600000.0},{"pair":"ADA/BTC","stake_amount":0.001,"amount":17.998560115190784,"open_date":"2018-01-27 00:45:00+00:00","close_date":"2018-01-30 04:45:00+00:00","open_rate":5.556e-05,"close_rate":5.144e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":4560,"profit_ratio":-0.07877175,"profit_abs":-4.120000000000001e-06,"exit_reason":"force_exit","initial_stop_loss_abs":5.0004000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":5.0004000000000004e-05,"stop_loss_ratio":0.1,"min_rate":5.144e-05,"max_rate":5.556e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517013900000.0,"close_timestamp":1517287500000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014492751522789634,"open_date":"2018-01-27 02:30:00+00:00","close_date":"2018-01-27 11:25:00+00:00","open_rate":0.06900001,"close_rate":0.06934587471177944,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":535,"profit_ratio":-0.0,"profit_abs":0.0003458647117794422,"exit_reason":"roi","initial_stop_loss_abs":0.062100009000000005,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.062100009000000005,"stop_loss_ratio":0.1,"min_rate":0.06900001,"max_rate":0.06934587471177944,"is_open":false,"buy_tag":null,"open_timestamp":1517020200000.0,"close_timestamp":1517052300000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010582027378879437,"open_date":"2018-01-27 06:25:00+00:00","close_date":"2018-01-27 07:05:00+00:00","open_rate":0.09449985,"close_rate":0.0949735334586466,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0004736834586466093,"exit_reason":"roi","initial_stop_loss_abs":0.085049865,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.085049865,"stop_loss_ratio":0.1,"min_rate":0.09449985,"max_rate":0.0949735334586466,"is_open":false,"buy_tag":null,"open_timestamp":1517034300000.0,"close_timestamp":1517036700000.0},{"pair":"ZEC/BTC","stake_amount":0.001,"amount":0.02434885085598385,"open_date":"2018-01-27 09:40:00+00:00","close_date":"2018-01-30 04:40:00+00:00","open_rate":0.0410697,"close_rate":0.03928809,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":4020,"profit_ratio":-0.04815133,"profit_abs":-0.001781610000000003,"exit_reason":"force_exit","initial_stop_loss_abs":0.03696273,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.03696273,"stop_loss_ratio":0.1,"min_rate":0.03928809,"max_rate":0.0410697,"is_open":false,"buy_tag":null,"open_timestamp":1517046000000.0,"close_timestamp":1517287200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.03508771929824561,"open_date":"2018-01-27 11:45:00+00:00","close_date":"2018-01-27 12:30:00+00:00","open_rate":0.0285,"close_rate":0.02864285714285714,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":-0.0,"profit_abs":0.00014285714285713902,"exit_reason":"roi","initial_stop_loss_abs":0.025650000000000003,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025650000000000003,"stop_loss_ratio":0.1,"min_rate":0.0285,"max_rate":0.02864285714285714,"is_open":false,"buy_tag":null,"open_timestamp":1517053500000.0,"close_timestamp":1517056200000.0},{"pair":"XMR/BTC","stake_amount":0.001,"amount":0.034887307020861215,"open_date":"2018-01-27 12:35:00+00:00","close_date":"2018-01-27 15:25:00+00:00","open_rate":0.02866372,"close_rate":0.02880739779448621,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":170,"profit_ratio":-0.0,"profit_abs":0.00014367779448621124,"exit_reason":"roi","initial_stop_loss_abs":0.025797348,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.025797348,"stop_loss_ratio":0.1,"min_rate":0.02866372,"max_rate":0.02880739779448621,"is_open":false,"buy_tag":null,"open_timestamp":1517056500000.0,"close_timestamp":1517066700000.0},{"pair":"ETH/BTC","stake_amount":0.001,"amount":0.010484268355332824,"open_date":"2018-01-27 15:50:00+00:00","close_date":"2018-01-27 16:50:00+00:00","open_rate":0.095381,"close_rate":0.09585910025062656,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":-0.0,"profit_abs":0.00047810025062657024,"exit_reason":"roi","initial_stop_loss_abs":0.0858429,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.0858429,"stop_loss_ratio":0.1,"min_rate":0.095381,"max_rate":0.09585910025062656,"is_open":false,"buy_tag":null,"open_timestamp":1517068200000.0,"close_timestamp":1517071800000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014794886650455417,"open_date":"2018-01-27 17:05:00+00:00","close_date":"2018-01-27 17:45:00+00:00","open_rate":0.06759092,"close_rate":0.06792972160401002,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00033880160401002224,"exit_reason":"roi","initial_stop_loss_abs":0.060831828,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060831828,"stop_loss_ratio":0.1,"min_rate":0.06759092,"max_rate":0.06792972160401002,"is_open":false,"buy_tag":null,"open_timestamp":1517072700000.0,"close_timestamp":1517075100000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.38684569885609726,"open_date":"2018-01-27 23:40:00+00:00","close_date":"2018-01-28 01:05:00+00:00","open_rate":0.00258501,"close_rate":0.002597967443609022,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":85,"profit_ratio":-0.0,"profit_abs":1.2957443609021985e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002326509,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002326509,"stop_loss_ratio":0.1,"min_rate":0.00258501,"max_rate":0.002597967443609022,"is_open":false,"buy_tag":null,"open_timestamp":1517096400000.0,"close_timestamp":1517101500000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014928710926711672,"open_date":"2018-01-28 02:25:00+00:00","close_date":"2018-01-28 08:10:00+00:00","open_rate":0.06698502,"close_rate":0.0673207845112782,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":345,"profit_ratio":-0.0,"profit_abs":0.00033576451127818874,"exit_reason":"roi","initial_stop_loss_abs":0.060286518000000004,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060286518000000004,"stop_loss_ratio":0.1,"min_rate":0.06698502,"max_rate":0.0673207845112782,"is_open":false,"buy_tag":null,"open_timestamp":1517106300000.0,"close_timestamp":1517127000000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014767187899175548,"open_date":"2018-01-28 10:25:00+00:00","close_date":"2018-01-28 16:30:00+00:00","open_rate":0.0677177,"close_rate":0.06805713709273183,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":365,"profit_ratio":-0.0,"profit_abs":0.0003394370927318202,"exit_reason":"roi","initial_stop_loss_abs":0.06094593000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06094593000000001,"stop_loss_ratio":0.1,"min_rate":0.0677177,"max_rate":0.06805713709273183,"is_open":false,"buy_tag":null,"open_timestamp":1517135100000.0,"close_timestamp":1517157000000.0},{"pair":"XLM/BTC","stake_amount":0.001,"amount":19.175455417066157,"open_date":"2018-01-28 20:35:00+00:00","close_date":"2018-01-28 21:35:00+00:00","open_rate":5.215e-05,"close_rate":5.2411403508771925e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":60,"profit_ratio":0.0,"profit_abs":2.6140350877192417e-07,"exit_reason":"roi","initial_stop_loss_abs":4.6935000000000004e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":4.6935000000000004e-05,"stop_loss_ratio":0.1,"min_rate":5.215e-05,"max_rate":5.2411403508771925e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517171700000.0,"close_timestamp":1517175300000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.36521808998243305,"open_date":"2018-01-28 22:00:00+00:00","close_date":"2018-01-28 22:30:00+00:00","open_rate":0.00273809,"close_rate":0.002779264285714285,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.117428571428529e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002464281,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002464281,"stop_loss_ratio":0.1,"min_rate":0.00273809,"max_rate":0.002779264285714285,"is_open":false,"buy_tag":null,"open_timestamp":1517176800000.0,"close_timestamp":1517178600000.0},{"pair":"ETC/BTC","stake_amount":0.001,"amount":0.3641236272539253,"open_date":"2018-01-29 00:00:00+00:00","close_date":"2018-01-29 00:30:00+00:00","open_rate":0.00274632,"close_rate":0.002787618045112782,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":30,"profit_ratio":0.00997506,"profit_abs":4.129804511278194e-05,"exit_reason":"roi","initial_stop_loss_abs":0.002471688,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.002471688,"stop_loss_ratio":0.1,"min_rate":0.00274632,"max_rate":0.002787618045112782,"is_open":false,"buy_tag":null,"open_timestamp":1517184000000.0,"close_timestamp":1517185800000.0},{"pair":"LTC/BTC","stake_amount":0.001,"amount":0.061634117689115045,"open_date":"2018-01-29 02:15:00+00:00","close_date":"2018-01-29 03:00:00+00:00","open_rate":0.01622478,"close_rate":0.016306107218045113,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":45,"profit_ratio":0.0,"profit_abs":8.132721804511231e-05,"exit_reason":"roi","initial_stop_loss_abs":0.014602302000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.014602302000000001,"stop_loss_ratio":0.1,"min_rate":0.01622478,"max_rate":0.016306107218045113,"is_open":false,"buy_tag":null,"open_timestamp":1517192100000.0,"close_timestamp":1517194800000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014492753623188404,"open_date":"2018-01-29 03:05:00+00:00","close_date":"2018-01-29 03:45:00+00:00","open_rate":0.069,"close_rate":0.06934586466165413,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.00034586466165412166,"exit_reason":"roi","initial_stop_loss_abs":0.06210000000000001,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.06210000000000001,"stop_loss_ratio":0.1,"min_rate":0.069,"max_rate":0.06934586466165413,"is_open":false,"buy_tag":null,"open_timestamp":1517195100000.0,"close_timestamp":1517197500000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.42204454597373,"open_date":"2018-01-29 05:20:00+00:00","close_date":"2018-01-29 06:55:00+00:00","open_rate":8.755e-05,"close_rate":8.798884711779448e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":95,"profit_ratio":-0.0,"profit_abs":4.3884711779447504e-07,"exit_reason":"roi","initial_stop_loss_abs":7.879500000000001e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":7.879500000000001e-05,"stop_loss_ratio":0.1,"min_rate":8.755e-05,"max_rate":8.798884711779448e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517203200000.0,"close_timestamp":1517208900000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014650376815016871,"open_date":"2018-01-29 07:00:00+00:00","close_date":"2018-01-29 19:25:00+00:00","open_rate":0.06825763,"close_rate":0.06859977350877192,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":745,"profit_ratio":-0.0,"profit_abs":0.00034214350877191657,"exit_reason":"roi","initial_stop_loss_abs":0.061431867,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.061431867,"stop_loss_ratio":0.1,"min_rate":0.06825763,"max_rate":0.06859977350877192,"is_open":false,"buy_tag":null,"open_timestamp":1517209200000.0,"close_timestamp":1517253900000.0},{"pair":"DASH/BTC","stake_amount":0.001,"amount":0.014894490408841846,"open_date":"2018-01-29 19:45:00+00:00","close_date":"2018-01-29 20:25:00+00:00","open_rate":0.06713892,"close_rate":0.06747545593984962,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":40,"profit_ratio":-0.0,"profit_abs":0.0003365359398496137,"exit_reason":"roi","initial_stop_loss_abs":0.060425028000000006,"initial_stop_loss_ratio":0.1,"stop_loss_abs":0.060425028000000006,"stop_loss_ratio":0.1,"min_rate":0.06713892,"max_rate":0.06747545593984962,"is_open":false,"buy_tag":null,"open_timestamp":1517255100000.0,"close_timestamp":1517257500000.0},{"pair":"TRX/BTC","stake_amount":0.001,"amount":11.193194537721066,"open_date":"2018-01-29 23:30:00+00:00","close_date":"2018-01-30 04:45:00+00:00","open_rate":8.934e-05,"close_rate":8.8e-05,"fee_open":0.0025,"fee_close":0.0025,"trade_duration":315,"profit_ratio":-0.0199116,"profit_abs":-1.3399999999999973e-06,"exit_reason":"force_exit","initial_stop_loss_abs":8.0406e-05,"initial_stop_loss_ratio":0.1,"stop_loss_abs":8.0406e-05,"stop_loss_ratio":0.1,"min_rate":8.8e-05,"max_rate":8.934e-05,"is_open":false,"buy_tag":null,"open_timestamp":1517268600000.0,"close_timestamp":1517287500000.0}],"locks":[],"best_pair":{"key":"LTC/BTC","trades":8,"profit_mean":0.00748129625,"profit_mean_pct":0.748129625,"profit_sum":0.05985037,"profit_sum_pct":5.99,"profit_total_abs":0.0015944746365914707,"profit_total":0.15944746365914708,"profit_total_pct":15.94,"duration_avg":"1:59:00","wins":8,"draws":0,"losses":0},"worst_pair":{"key":"XMR/BTC","trades":16,"profit_mean":-0.0027899012500000007,"profit_mean_pct":-0.2789901250000001,"profit_sum":-0.04463842000000001,"profit_sum_pct":-4.46,"profit_total_abs":0.0006671885263157366,"profit_total":0.06671885263157366,"profit_total_pct":6.67,"duration_avg":"8:41:00","wins":15,"draws":0,"losses":1},"results_per_pair":[{"key":"ETH/BTC","trades":21,"profit_mean":0.0009500057142857142,"profit_mean_pct":0.09500057142857142,"profit_sum":0.01995012,"profit_sum_pct":2.0,"profit_total_abs":0.011505731278195264,"profit_total":1.1505731278195264,"profit_total_pct":115.06,"duration_avg":"2:17:00","wins":21,"draws":0,"losses":0},{"key":"DASH/BTC","trades":16,"profit_mean":0.0018703237499999997,"profit_mean_pct":0.18703237499999997,"profit_sum":0.029925179999999996,"profit_sum_pct":2.99,"profit_total_abs":0.007475052681704161,"profit_total":0.7475052681704161,"profit_total_pct":74.75,"duration_avg":"3:03:00","wins":16,"draws":0,"losses":0},{"key":"ZEC/BTC","trades":21,"profit_mean":-0.00039290904761904774,"profit_mean_pct":-0.03929090476190478,"profit_sum":-0.008251090000000003,"profit_sum_pct":-0.83,"profit_total_abs":0.004452605639097655,"profit_total":0.4452605639097655,"profit_total_pct":44.53,"duration_avg":"4:17:00","wins":20,"draws":0,"losses":1},{"key":"LTC/BTC","trades":8,"profit_mean":0.00748129625,"profit_mean_pct":0.748129625,"profit_sum":0.05985037,"profit_sum_pct":5.99,"profit_total_abs":0.0015944746365914707,"profit_total":0.15944746365914708,"profit_total_pct":15.94,"duration_avg":"1:59:00","wins":8,"draws":0,"losses":0},{"key":"XMR/BTC","trades":16,"profit_mean":-0.0027899012500000007,"profit_mean_pct":-0.2789901250000001,"profit_sum":-0.04463842000000001,"profit_sum_pct":-4.46,"profit_total_abs":0.0006671885263157366,"profit_total":0.06671885263157366,"profit_total_pct":6.67,"duration_avg":"8:41:00","wins":15,"draws":0,"losses":1},{"key":"ETC/BTC","trades":20,"profit_mean":0.0022568569999999997,"profit_mean_pct":0.22568569999999996,"profit_sum":0.04513713999999999,"profit_sum_pct":4.51,"profit_total_abs":0.00036538235338345404,"profit_total":0.0365382353383454,"profit_total_pct":3.65,"duration_avg":"1:45:00","wins":19,"draws":0,"losses":1},{"key":"TRX/BTC","trades":15,"profit_mean":0.0023467073333333323,"profit_mean_pct":0.23467073333333321,"profit_sum":0.035200609999999986,"profit_sum_pct":3.52,"profit_total_abs":1.1329523809523682e-05,"profit_total":0.0011329523809523682,"profit_total_pct":0.11,"duration_avg":"2:28:00","wins":13,"draws":0,"losses":2},{"key":"XLM/BTC","trades":21,"profit_mean":0.0026243899999999994,"profit_mean_pct":0.2624389999999999,"profit_sum":0.05511218999999999,"profit_sum_pct":5.51,"profit_total_abs":7.340779448621465e-06,"profit_total":0.0007340779448621465,"profit_total_pct":0.07,"duration_avg":"3:21:00","wins":20,"draws":0,"losses":1},{"key":"ADA/BTC","trades":29,"profit_mean":-0.0011598141379310352,"profit_mean_pct":-0.11598141379310352,"profit_sum":-0.03363461000000002,"profit_sum_pct":-3.36,"profit_total_abs":4.916634085212862e-06,"profit_total":0.0004916634085212862,"profit_total_pct":0.05,"duration_avg":"5:35:00","wins":27,"draws":0,"losses":2},{"key":"NXT/BTC","trades":12,"profit_mean":-0.0012261025000000006,"profit_mean_pct":-0.12261025000000006,"profit_sum":-0.014713230000000008,"profit_sum_pct":-1.47,"profit_total_abs":1.4774411027568458e-06,"profit_total":0.00014774411027568458,"profit_total_pct":0.01,"duration_avg":"0:57:00","wins":11,"draws":0,"losses":1},{"key":"TOTAL","trades":179,"profit_mean":0.0008041243575418989,"profit_mean_pct":0.0804124357541899,"profit_sum":0.1439382599999999,"profit_sum_pct":14.39,"profit_total_abs":0.026085499493733857,"profit_total":2.6085499493733857,"profit_total_pct":260.85,"duration_avg":"3:40:00","wins":170,"draws":0,"losses":9}],"results_per_enter_tag":[{"key":"TOTAL","trades":179,"profit_mean":0.0008041243575418989,"profit_mean_pct":0.0804124357541899,"profit_sum":0.1439382599999999,"profit_sum_pct":14.39,"profit_total_abs":0.026085499493733857,"profit_total":2.6085499493733857,"profit_total_pct":260.85,"duration_avg":"3:40:00","wins":170,"draws":0,"losses":9}],"exit_reason_summary":[{"exit_reason":"roi","trades":170,"wins":170,"draws":0,"losses":0,"profit_mean":0.005398268352941177,"profit_mean_pct":0.54,"profit_sum":0.91770562,"profit_sum_pct":91.77,"profit_total_abs":0.031232837493733862,"profit_total":0.30590187333333335,"profit_total_pct":30.59},{"exit_reason":"stop_loss","trades":6,"wins":0,"draws":0,"losses":6,"profit_mean":-0.10448878000000002,"profit_mean_pct":-10.45,"profit_sum":-0.6269326800000001,"profit_sum_pct":-62.69,"profit_total_abs":-0.0033602680000000026,"profit_total":-0.20897756000000003,"profit_total_pct":-20.9},{"exit_reason":"force_exit","trades":3,"wins":0,"draws":0,"losses":3,"profit_mean":-0.04894489333333333,"profit_mean_pct":-4.89,"profit_sum":-0.14683468,"profit_sum_pct":-14.68,"profit_total_abs":-0.001787070000000003,"profit_total":-0.04894489333333333,"profit_total_pct":-4.89}],"left_open_trades":[{"key":"TOTAL","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0}],"total_trades":179,"total_volume":0.17900000000000005,"avg_stake_amount":0.0010000000000000002,"profit_mean":0.0008041243575418989,"profit_median":0.0,"profit_total":2.6085499493733857,"profit_total_abs":0.026085499493733857,"backtest_start":"2018-01-10 07:15:00","backtest_start_ts":1515568500000,"backtest_end":"2018-01-30 04:45:00","backtest_end_ts":1517287500000,"backtest_days":19,"backtest_run_start_ts":"2020-10-01 18:00:00+00:00","backtest_run_end_ts":"2020-10-01 18:01:00+00:00","trades_per_day":9.42,"market_change":1.22,"pairlist":[],"stake_amount":0.001,"stake_currency":"BTC","stake_currency_decimals":8,"starting_balance":0.01,"dry_run_wallet":0.01,"final_balance":0.03608549949373386,"rejected_signals":0,"max_open_trades":3,"max_open_trades_setting":3,"timeframe":"5m","timeframe_detail":"","timerange":"","enable_protections":false,"strategy_name":"StrategyTestV2","stoploss":0.1,"trailing_stop":false,"trailing_stop_positive":null,"trailing_stop_positive_offset":0.0,"trailing_only_offset_is_reached":false,"use_custom_stoploss":false,"minimal_roi":{},"use_exit_signal":true,"exit_profit_only":false,"exit_profit_offset":false,"ignore_roi_if_entry_signal":false,"backtest_best_day":0.17955111999999998,"backtest_worst_day":-0.14683468,"backtest_best_day_abs":0.0071570099,"backtest_worst_day_abs":-0.0023093218,"winning_days":19,"draw_days":0,"losing_days":2,"daily_profit":[["2018-01-10",0.0025815306],["2018-01-11",0.0049356655],["2018-01-12",0.0006395218],["2018-01-13",0.0002574589],["2018-01-14",0.0010443828],["2018-01-15",0.0024030209],["2018-01-16",0.0071570099],["2018-01-17",0.001137038],["2018-01-18",0.0013712174],["2018-01-19",0.000584673],["2018-01-20",0.0006143386],["2018-01-21",0.0004749361],["2018-01-22",9.91669e-05],["2018-01-23",0.0015726664],["2018-01-24",0.0006610219],["2018-01-25",-0.0023093218],["2018-01-26",0.0003735204],["2018-01-27",0.0023975191],["2018-01-28",0.0007295947],["2018-01-29",0.0011476082],["2018-01-30",-0.00178707]],"wins":48,"losses":9,"draws":122,"holding_avg":"3:40:00","holding_avg_s":13200.0,"winner_holding_avg":"0:24:00","winner_holding_avg_s":1440.0,"loser_holding_avg":"1 day, 5:57:00","loser_holding_avg_s":107820.0,"max_drawdown":0.21142322000000008,"max_drawdown_account":0.08674033488183289,"max_drawdown_abs":0.0030822220000000025,"drawdown_start":"2018-01-25 01:30:00","drawdown_start_ts":1516843800000.0,"drawdown_end":"2018-01-25 03:50:00","drawdown_end_ts":1516852200000.0,"max_drawdown_low":0.02245167355388436,"max_drawdown_high":0.025533895553884363,"csum_min":0.01000434887218045,"csum_max":0.03608683949373386}},"strategy_comparison":[{"key":"StrategyTestV2","trades":179,"profit_mean":0.0008041243575418989,"profit_mean_pct":0.0804124357541899,"profit_sum":0.1439382599999999,"profit_sum_pct":14.39,"profit_total_abs":0.026085499493733857,"profit_total":2.6085499493733857,"profit_total_pct":260.85,"duration_avg":"3:40:00","wins":170,"draws":0,"losses":9,"max_drawdown_account":0.08674033488183289,"max_drawdown_abs":"0.00308222"}]} 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 + } +} diff --git a/tests/testdata/strategy_SampleStrategy.fthypt b/tests/testdata/strategy_SampleStrategy.fthypt index 6dc2b9ab1..6a64a9c4f 100644 --- a/tests/testdata/strategy_SampleStrategy.fthypt +++ b/tests/testdata/strategy_SampleStrategy.fthypt @@ -1,5 +1,5 @@ -{"loss":100000,"params_dict":{"mfi-value":"20","fastd-value":"21","adx-value":"26","rsi-value":"23","mfi-enabled":true,"fastd-enabled":false,"adx-enabled":false,"rsi-enabled":true,"trigger":"sar_reversal","sell-mfi-value":"97","sell-fastd-value":"85","sell-adx-value":"55","sell-rsi-value":"76","sell-mfi-enabled":true,"sell-fastd-enabled":false,"sell-adx-enabled":true,"sell-rsi-enabled":true,"sell-trigger":"sell-bb_upper","roi_t1":"34","roi_t2":"28","roi_t3":"32","roi_p1":0.031,"roi_p2":0.033,"roi_p3":0.146,"stoploss":-0.05},"params_details":{"buy":{"mfi-value":"20","fastd-value":"21","adx-value":"26","rsi-value":"23","mfi-enabled":true,"fastd-enabled":false,"adx-enabled":false,"rsi-enabled":true,"trigger":"sar_reversal"},"sell":{"sell-mfi-value":"97","sell-fastd-value":"85","sell-adx-value":"55","sell-rsi-value":"76","sell-mfi-enabled":true,"sell-fastd-enabled":false,"sell-adx-enabled":true,"sell-rsi-enabled":true,"sell-trigger":"sell-bb_upper"},"roi":"{0: 0.21, 32: 0.064, 60: 0.031, 94: 0}","stoploss":{"stoploss":-0.05}},"params_not_optimized":{"buy":{},"sell":{}},"results_metrics":{"trades":[],"locks":[],"best_pair":{"key":"ETH/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},"worst_pair":{"key":"ETH/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},"results_per_pair":[{"key":"ETH/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"LTC/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"ETC/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"XLM/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"TRX/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"ADA/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"TOTAL","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0}],"sell_reason_summary":[],"left_open_trades":[{"key":"TOTAL","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0}],"total_trades":0,"total_volume":0.0,"avg_stake_amount":0,"profit_mean":0,"profit_median":0,"profit_total":0.0,"profit_total_abs":0,"backtest_start":"2018-01-10 07:25:00","backtest_start_ts":1515569100000,"backtest_end":"2018-01-30 04:45:00","backtest_end_ts":1517287500000,"backtest_days":19,"backtest_run_start_ts":1620793107,"backtest_run_end_ts":1620793107,"trades_per_day":0.0,"market_change":0,"pairlist":["ETH/BTC","LTC/BTC","ETC/BTC","XLM/BTC","TRX/BTC","ADA/BTC"],"stake_amount":0.05,"stake_currency":"BTC","stake_currency_decimals":8,"starting_balance":1000,"dry_run_wallet":1000,"final_balance":1000,"max_open_trades":3,"max_open_trades_setting":3,"timeframe":"5m","timerange":"","enable_protections":false,"strategy_name":"SampleStrategy","stoploss":-0.1,"trailing_stop":false,"trailing_stop_positive":null,"trailing_stop_positive_offset":0.0,"trailing_only_offset_is_reached":false,"use_custom_stoploss":false,"minimal_roi":{"60":0.01,"30":0.02,"0":0.04},"use_sell_signal":true,"sell_profit_only":false,"sell_profit_offset":0.0,"ignore_roi_if_buy_signal":false,"backtest_best_day":0,"backtest_worst_day":0,"backtest_best_day_abs":0,"backtest_worst_day_abs":0,"winning_days":0,"draw_days":0,"losing_days":0,"wins":0,"losses":0,"draws":0,"holding_avg":"0:00:00","winner_holding_avg":"0:00:00","loser_holding_avg":"0:00:00","max_drawdown":0.0,"max_drawdown_abs":0.0,"max_drawdown_low":0.0,"max_drawdown_high":0.0,"drawdown_start":"1970-01-01 00:00:00+00:00","drawdown_start_ts":0,"drawdown_end":"1970-01-01 00:00:00+00:00","drawdown_end_ts":0,"csum_min":0,"csum_max":0},"results_explanation":" 0 trades. 0/0/0 Wins/Draws/Losses. Avg profit 0.00%. Median profit 0.00%. Total profit 0.00000000 BTC ( 0.00\u03A3%). Avg duration 0:00:00 min.","total_profit":0.0,"current_epoch":1,"is_initial_point":true,"is_best":false} -{"loss":100000,"params_dict":{"mfi-value":"14","fastd-value":"43","adx-value":"30","rsi-value":"24","mfi-enabled":true,"fastd-enabled":true,"adx-enabled":false,"rsi-enabled":true,"trigger":"sar_reversal","sell-mfi-value":"97","sell-fastd-value":"71","sell-adx-value":"82","sell-rsi-value":"99","sell-mfi-enabled":false,"sell-fastd-enabled":false,"sell-adx-enabled":false,"sell-rsi-enabled":true,"sell-trigger":"sell-bb_upper","roi_t1":"84","roi_t2":"35","roi_t3":"19","roi_p1":0.024,"roi_p2":0.022,"roi_p3":0.061,"stoploss":-0.083},"params_details":{"buy":{"mfi-value":"14","fastd-value":"43","adx-value":"30","rsi-value":"24","mfi-enabled":true,"fastd-enabled":true,"adx-enabled":false,"rsi-enabled":true,"trigger":"sar_reversal"},"sell":{"sell-mfi-value":"97","sell-fastd-value":"71","sell-adx-value":"82","sell-rsi-value":"99","sell-mfi-enabled":false,"sell-fastd-enabled":false,"sell-adx-enabled":false,"sell-rsi-enabled":true,"sell-trigger":"sell-bb_upper"},"roi":"{0: 0.107, 19: 0.046, 54: 0.024, 138: 0}","stoploss":{"stoploss":-0.083}},"params_not_optimized":{"buy":{},"sell":{}},"results_metrics":{"trades":[],"locks":[],"best_pair":{"key":"ETH/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},"worst_pair":{"key":"ETH/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},"results_per_pair":[{"key":"ETH/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"LTC/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"ETC/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"XLM/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"TRX/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"ADA/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"TOTAL","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0}],"sell_reason_summary":[],"left_open_trades":[{"key":"TOTAL","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0}],"total_trades":0,"total_volume":0.0,"avg_stake_amount":0,"profit_mean":0,"profit_median":0,"profit_total":0.0,"profit_total_abs":0,"backtest_start":"2018-01-10 07:25:00","backtest_start_ts":1515569100000,"backtest_end":"2018-01-30 04:45:00","backtest_end_ts":1517287500000,"backtest_days":19,"backtest_run_start_ts":1620793107,"backtest_run_end_ts":1620793108,"trades_per_day":0.0,"market_change":0,"pairlist":["ETH/BTC","LTC/BTC","ETC/BTC","XLM/BTC","TRX/BTC","ADA/BTC"],"stake_amount":0.05,"stake_currency":"BTC","stake_currency_decimals":8,"starting_balance":1000,"dry_run_wallet":1000,"final_balance":1000,"max_open_trades":3,"max_open_trades_setting":3,"timeframe":"5m","timerange":"","enable_protections":false,"strategy_name":"SampleStrategy","stoploss":-0.1,"trailing_stop":false,"trailing_stop_positive":null,"trailing_stop_positive_offset":0.0,"trailing_only_offset_is_reached":false,"use_custom_stoploss":false,"minimal_roi":{"60":0.01,"30":0.02,"0":0.04},"use_sell_signal":true,"sell_profit_only":false,"sell_profit_offset":0.0,"ignore_roi_if_buy_signal":false,"backtest_best_day":0,"backtest_worst_day":0,"backtest_best_day_abs":0,"backtest_worst_day_abs":0,"winning_days":0,"draw_days":0,"losing_days":0,"wins":0,"losses":0,"draws":0,"holding_avg":"0:00:00","winner_holding_avg":"0:00:00","loser_holding_avg":"0:00:00","max_drawdown":0.0,"max_drawdown_abs":0.0,"max_drawdown_low":0.0,"max_drawdown_high":0.0,"drawdown_start":"1970-01-01 00:00:00+00:00","drawdown_start_ts":0,"drawdown_end":"1970-01-01 00:00:00+00:00","drawdown_end_ts":0,"csum_min":0,"csum_max":0},"results_explanation":" 0 trades. 0/0/0 Wins/Draws/Losses. Avg profit 0.00%. Median profit 0.00%. Total profit 0.00000000 BTC ( 0.00\u03A3%). Avg duration 0:00:00 min.","total_profit":0.0,"current_epoch":2,"is_initial_point":true,"is_best":false} -{"loss":2.183447401951895,"params_dict":{"mfi-value":"14","fastd-value":"15","adx-value":"40","rsi-value":"36","mfi-enabled":false,"fastd-enabled":true,"adx-enabled":false,"rsi-enabled":false,"trigger":"sar_reversal","sell-mfi-value":"92","sell-fastd-value":"84","sell-adx-value":"61","sell-rsi-value":"61","sell-mfi-enabled":true,"sell-fastd-enabled":true,"sell-adx-enabled":true,"sell-rsi-enabled":true,"sell-trigger":"sell-bb_upper","roi_t1":"68","roi_t2":"41","roi_t3":"21","roi_p1":0.015,"roi_p2":0.064,"roi_p3":0.126,"stoploss":-0.024},"params_details":{"buy":{"mfi-value":"14","fastd-value":"15","adx-value":"40","rsi-value":"36","mfi-enabled":false,"fastd-enabled":true,"adx-enabled":false,"rsi-enabled":false,"trigger":"sar_reversal"},"sell":{"sell-mfi-value":"92","sell-fastd-value":"84","sell-adx-value":"61","sell-rsi-value":"61","sell-mfi-enabled":true,"sell-fastd-enabled":true,"sell-adx-enabled":true,"sell-rsi-enabled":true,"sell-trigger":"sell-bb_upper"},"roi":"{0: 0.20500000000000002, 21: 0.079, 62: 0.015, 130: 0}","stoploss":{"stoploss":-0.024}},"params_not_optimized":{"buy":{},"sell":{}},"results_metrics":{"trades":[{"pair":"LTC/BTC","stake_amount":0.05,"amount":2.94115571,"open_date":"2018-01-11 11:40:00+00:00","close_date":"2018-01-11 19:40:00+00:00","open_rate":0.01700012,"close_rate":0.017119538805820372,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":480,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.01659211712,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.01659211712,"stop_loss_ratio":-0.024,"min_rate":0.01689809,"max_rate":0.0171462,"is_open":false,"open_timestamp":1515670800000.0,"close_timestamp":1515699600000.0},{"pair":"ETH/BTC","stake_amount":0.05,"amount":0.57407318,"open_date":"2018-01-12 11:05:00+00:00","close_date":"2018-01-12 12:30:00+00:00","open_rate":0.08709691,"close_rate":0.08901977203712995,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":85,"profit_ratio":0.01494768,"profit_abs":0.00075,"sell_reason":"roi","initial_stop_loss_abs":0.08500658416,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.08500658416,"stop_loss_ratio":-0.024,"min_rate":0.08702974000000001,"max_rate":0.08929248000000001,"is_open":false,"open_timestamp":1515755100000.0,"close_timestamp":1515760200000.0},{"pair":"LTC/BTC","stake_amount":0.05,"amount":2.93166236,"open_date":"2018-01-12 03:30:00+00:00","close_date":"2018-01-12 13:05:00+00:00","open_rate":0.01705517,"close_rate":0.01717497550928249,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":575,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.016645845920000003,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.016645845920000003,"stop_loss_ratio":-0.024,"min_rate":0.0169841,"max_rate":0.01719135,"is_open":false,"open_timestamp":1515727800000.0,"close_timestamp":1515762300000.0},{"pair":"LTC/BTC","stake_amount":0.05,"amount":2.96876855,"open_date":"2018-01-13 03:50:00+00:00","close_date":"2018-01-13 06:05:00+00:00","open_rate":0.016842,"close_rate":0.016960308078273957,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":135,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.016437792,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.016437792,"stop_loss_ratio":-0.024,"min_rate":0.016836999999999998,"max_rate":0.017,"is_open":false,"open_timestamp":1515815400000.0,"close_timestamp":1515823500000.0},{"pair":"ETH/BTC","stake_amount":0.05,"amount":0.53163205,"open_date":"2018-01-13 13:25:00+00:00","close_date":"2018-01-13 15:35:00+00:00","open_rate":0.09405001,"close_rate":0.09471067238835926,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":130,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.09179280976,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.09179280976,"stop_loss_ratio":-0.024,"min_rate":0.09369894000000001,"max_rate":0.09479997,"is_open":false,"open_timestamp":1515849900000.0,"close_timestamp":1515857700000.0},{"pair":"ETC/BTC","stake_amount":0.05,"amount":19.23816853,"open_date":"2018-01-13 15:30:00+00:00","close_date":"2018-01-13 16:20:00+00:00","open_rate":0.0025989999999999997,"close_rate":0.0028232990466633217,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":50,"profit_ratio":0.07872446,"profit_abs":0.00395,"sell_reason":"roi","initial_stop_loss_abs":0.002536624,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.002536624,"stop_loss_ratio":-0.024,"min_rate":0.00259525,"max_rate":0.0028288700000000003,"is_open":false,"open_timestamp":1515857400000.0,"close_timestamp":1515860400000.0},{"pair":"TRX/BTC","stake_amount":0.05,"amount":492.80504632,"open_date":"2018-01-14 21:35:00+00:00","close_date":"2018-01-14 23:15:00+00:00","open_rate":0.00010146000000000001,"close_rate":0.00010369995985950828,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":100,"profit_ratio":0.01494768,"profit_abs":0.00075,"sell_reason":"roi","initial_stop_loss_abs":9.902496e-05,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":9.902496e-05,"stop_loss_ratio":-0.024,"min_rate":0.0001012,"max_rate":0.00010414,"is_open":false,"open_timestamp":1515965700000.0,"close_timestamp":1515971700000.0},{"pair":"LTC/BTC","stake_amount":0.05,"amount":2.92398174,"open_date":"2018-01-15 12:45:00+00:00","close_date":"2018-01-15 21:05:00+00:00","open_rate":0.01709997,"close_rate":0.01722009021073758,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":500,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.016689570719999998,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.016689570719999998,"stop_loss_ratio":-0.024,"min_rate":0.01694,"max_rate":0.01725,"is_open":false,"open_timestamp":1516020300000.0,"close_timestamp":1516050300000.0},{"pair":"XLM/BTC","stake_amount":0.05,"amount":1111.60515785,"open_date":"2018-01-15 19:50:00+00:00","close_date":"2018-01-15 23:45:00+00:00","open_rate":4.4980000000000006e-05,"close_rate":4.390048e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":235,"profit_ratio":-0.03080817,"profit_abs":-0.0015458,"sell_reason":"stop_loss","initial_stop_loss_abs":4.390048e-05,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":4.390048e-05,"stop_loss_ratio":-0.024,"min_rate":4.409e-05,"max_rate":4.502e-05,"is_open":false,"open_timestamp":1516045800000.0,"close_timestamp":1516059900000.0},{"pair":"TRX/BTC","stake_amount":0.05,"amount":519.80455349,"open_date":"2018-01-21 03:55:00+00:00","close_date":"2018-01-21 04:05:00+00:00","open_rate":9.619e-05,"close_rate":9.388144e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":10,"profit_ratio":-0.03080817,"profit_abs":-0.0015458,"sell_reason":"stop_loss","initial_stop_loss_abs":9.388144e-05,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":9.388144e-05,"stop_loss_ratio":-0.024,"min_rate":9.568e-05,"max_rate":9.673e-05,"is_open":false,"open_timestamp":1516506900000.0,"close_timestamp":1516507500000.0},{"pair":"LTC/BTC","stake_amount":0.05,"amount":3.029754,"open_date":"2018-01-20 22:15:00+00:00","close_date":"2018-01-21 07:45:00+00:00","open_rate":0.01650299,"close_rate":0.016106918239999997,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":570,"profit_ratio":-0.03080817,"profit_abs":-0.0015458,"sell_reason":"stop_loss","initial_stop_loss_abs":0.016106918239999997,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.016106918239999997,"stop_loss_ratio":-0.024,"min_rate":0.0162468,"max_rate":0.01663179,"is_open":false,"open_timestamp":1516486500000.0,"close_timestamp":1516520700000.0},{"pair":"ETC/BTC","stake_amount":0.05,"amount":18.75461832,"open_date":"2018-01-21 13:00:00+00:00","close_date":"2018-01-21 16:25:00+00:00","open_rate":0.00266601,"close_rate":0.00260202576,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":205,"profit_ratio":-0.03080817,"profit_abs":-0.0015458,"sell_reason":"stop_loss","initial_stop_loss_abs":0.00260202576,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.00260202576,"stop_loss_ratio":-0.024,"min_rate":0.0026290800000000002,"max_rate":0.00269384,"is_open":false,"open_timestamp":1516539600000.0,"close_timestamp":1516551900000.0},{"pair":"TRX/BTC","stake_amount":0.05,"amount":552.18111541,"open_date":"2018-01-22 02:10:00+00:00","close_date":"2018-01-22 04:20:00+00:00","open_rate":9.055e-05,"close_rate":9.118607626693427e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":130,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":8.83768e-05,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":8.83768e-05,"stop_loss_ratio":-0.024,"min_rate":9.013e-05,"max_rate":9.197e-05,"is_open":false,"open_timestamp":1516587000000.0,"close_timestamp":1516594800000.0},{"pair":"LTC/BTC","stake_amount":0.05,"amount":2.99733237,"open_date":"2018-01-22 03:20:00+00:00","close_date":"2018-01-22 13:50:00+00:00","open_rate":0.0166815,"close_rate":0.016281143999999997,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":630,"profit_ratio":-0.03080817,"profit_abs":-0.0015458,"sell_reason":"stop_loss","initial_stop_loss_abs":0.016281143999999997,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.016281143999999997,"stop_loss_ratio":-0.024,"min_rate":0.01641443,"max_rate":0.016800000000000002,"is_open":false,"open_timestamp":1516591200000.0,"close_timestamp":1516629000000.0},{"pair":"TRX/BTC","stake_amount":0.05,"amount":503.52467271,"open_date":"2018-01-23 08:55:00+00:00","close_date":"2018-01-23 09:40:00+00:00","open_rate":9.93e-05,"close_rate":9.69168e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":45,"profit_ratio":-0.03080817,"profit_abs":-0.0015458,"sell_reason":"stop_loss","initial_stop_loss_abs":9.69168e-05,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":9.69168e-05,"stop_loss_ratio":-0.024,"min_rate":9.754e-05,"max_rate":0.00010025,"is_open":false,"open_timestamp":1516697700000.0,"close_timestamp":1516700400000.0},{"pair":"ETH/BTC","stake_amount":0.05,"amount":0.55148073,"open_date":"2018-01-24 02:10:00+00:00","close_date":"2018-01-24 04:40:00+00:00","open_rate":0.090665,"close_rate":0.09130188409433015,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":150,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.08848903999999999,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.08848903999999999,"stop_loss_ratio":-0.024,"min_rate":0.090665,"max_rate":0.09146000000000001,"is_open":false,"open_timestamp":1516759800000.0,"close_timestamp":1516768800000.0},{"pair":"ETC/BTC","stake_amount":0.05,"amount":19.10584639,"open_date":"2018-01-24 19:20:00+00:00","close_date":"2018-01-24 21:35:00+00:00","open_rate":0.002617,"close_rate":0.0026353833416959357,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":135,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.002554192,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.002554192,"stop_loss_ratio":-0.024,"min_rate":0.002617,"max_rate":0.00264999,"is_open":false,"open_timestamp":1516821600000.0,"close_timestamp":1516829700000.0},{"pair":"ETC/BTC","stake_amount":0.05,"amount":19.34602691,"open_date":"2018-01-25 14:35:00+00:00","close_date":"2018-01-25 16:35:00+00:00","open_rate":0.00258451,"close_rate":0.002641568926241846,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":120,"profit_ratio":0.01494768,"profit_abs":0.00075,"sell_reason":"roi","initial_stop_loss_abs":0.00252248176,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.00252248176,"stop_loss_ratio":-0.024,"min_rate":0.00258451,"max_rate":0.00264579,"is_open":false,"open_timestamp":1516890900000.0,"close_timestamp":1516898100000.0},{"pair":"LTC/BTC","stake_amount":0.05,"amount":3.11910295,"open_date":"2018-01-24 23:05:00+00:00","close_date":"2018-01-25 16:55:00+00:00","open_rate":0.01603025,"close_rate":0.016142855870546913,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":1070,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.015645523999999997,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.015645523999999997,"stop_loss_ratio":-0.024,"min_rate":0.015798760000000002,"max_rate":0.01617,"is_open":false,"open_timestamp":1516835100000.0,"close_timestamp":1516899300000.0},{"pair":"TRX/BTC","stake_amount":0.05,"amount":553.70985604,"open_date":"2018-01-26 19:30:00+00:00","close_date":"2018-01-26 23:30:00+00:00","open_rate":9.03e-05,"close_rate":9.093432012042147e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":240,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":8.813279999999999e-05,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":8.813279999999999e-05,"stop_loss_ratio":-0.024,"min_rate":8.961e-05,"max_rate":9.1e-05,"is_open":false,"open_timestamp":1516995000000.0,"close_timestamp":1517009400000.0},{"pair":"ETC/BTC","stake_amount":0.05,"amount":19.22929005,"open_date":"2018-01-26 21:15:00+00:00","close_date":"2018-01-28 03:50:00+00:00","open_rate":0.0026002,"close_rate":0.0026184653286502758,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":1835,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.0025377952,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.0025377952,"stop_loss_ratio":-0.024,"min_rate":0.00254702,"max_rate":0.00262797,"is_open":false,"open_timestamp":1517001300000.0,"close_timestamp":1517111400000.0},{"pair":"LTC/BTC","stake_amount":0.05,"amount":3.15677093,"open_date":"2018-01-27 22:05:00+00:00","close_date":"2018-01-28 10:45:00+00:00","open_rate":0.01583897,"close_rate":0.015950232207727046,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":760,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.01545883472,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.01545883472,"stop_loss_ratio":-0.024,"min_rate":0.015700000000000002,"max_rate":0.01596521,"is_open":false,"open_timestamp":1517090700000.0,"close_timestamp":1517136300000.0}],"locks":[],"best_pair":{"key":"ETC/BTC","trades":5,"profit_mean":0.012572794000000002,"profit_mean_pct":1.2572794000000003,"profit_sum":0.06286397,"profit_sum_pct":6.29,"profit_total_abs":0.0031542000000000002,"profit_total":3.1542000000000002e-06,"profit_total_pct":0.0,"duration_avg":"7:49:00","wins":2,"draws":2,"losses":1},"worst_pair":{"key":"LTC/BTC","trades":8,"profit_mean":-0.0077020425,"profit_mean_pct":-0.77020425,"profit_sum":-0.06161634,"profit_sum_pct":-6.16,"profit_total_abs":-0.0030916,"profit_total":-3.0915999999999998e-06,"profit_total_pct":-0.0,"duration_avg":"9:50:00","wins":0,"draws":6,"losses":2},"results_per_pair":[{"key":"ETC/BTC","trades":5,"profit_mean":0.012572794000000002,"profit_mean_pct":1.2572794000000003,"profit_sum":0.06286397,"profit_sum_pct":6.29,"profit_total_abs":0.0031542000000000002,"profit_total":3.1542000000000002e-06,"profit_total_pct":0.0,"duration_avg":"7:49:00","wins":2,"draws":2,"losses":1},{"key":"ETH/BTC","trades":3,"profit_mean":0.00498256,"profit_mean_pct":0.498256,"profit_sum":0.01494768,"profit_sum_pct":1.49,"profit_total_abs":0.00075,"profit_total":7.5e-07,"profit_total_pct":0.0,"duration_avg":"2:02:00","wins":1,"draws":2,"losses":0},{"key":"ADA/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"XLM/BTC","trades":1,"profit_mean":-0.03080817,"profit_mean_pct":-3.080817,"profit_sum":-0.03080817,"profit_sum_pct":-3.08,"profit_total_abs":-0.0015458,"profit_total":-1.5457999999999999e-06,"profit_total_pct":-0.0,"duration_avg":"3:55:00","wins":0,"draws":0,"losses":1},{"key":"TRX/BTC","trades":5,"profit_mean":-0.009333732,"profit_mean_pct":-0.9333732000000001,"profit_sum":-0.04666866,"profit_sum_pct":-4.67,"profit_total_abs":-0.0023416,"profit_total":-2.3416e-06,"profit_total_pct":-0.0,"duration_avg":"1:45:00","wins":1,"draws":2,"losses":2},{"key":"LTC/BTC","trades":8,"profit_mean":-0.0077020425,"profit_mean_pct":-0.77020425,"profit_sum":-0.06161634,"profit_sum_pct":-6.16,"profit_total_abs":-0.0030916,"profit_total":-3.0915999999999998e-06,"profit_total_pct":-0.0,"duration_avg":"9:50:00","wins":0,"draws":6,"losses":2},{"key":"TOTAL","trades":22,"profit_mean":-0.0027855236363636365,"profit_mean_pct":-0.27855236363636365,"profit_sum":-0.06128152,"profit_sum_pct":-6.13,"profit_total_abs":-0.0030748,"profit_total":-3.0747999999999998e-06,"profit_total_pct":-0.0,"duration_avg":"6:12:00","wins":4,"draws":12,"losses":6}],"sell_reason_summary":[{"sell_reason":"roi","trades":16,"wins":4,"draws":12,"losses":0,"profit_mean":0.00772296875,"profit_mean_pct":0.77,"profit_sum":0.1235675,"profit_sum_pct":12.36,"profit_total_abs":0.006200000000000001,"profit_total":0.041189166666666666,"profit_total_pct":4.12},{"sell_reason":"stop_loss","trades":6,"wins":0,"draws":0,"losses":6,"profit_mean":-0.03080817,"profit_mean_pct":-3.08,"profit_sum":-0.18484902,"profit_sum_pct":-18.48,"profit_total_abs":-0.0092748,"profit_total":-0.06161634,"profit_total_pct":-6.16}],"left_open_trades":[{"key":"TOTAL","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0}],"total_trades":22,"total_volume":1.1000000000000003,"avg_stake_amount":0.05000000000000002,"profit_mean":-0.0027855236363636365,"profit_median":0.0,"profit_total":-3.0747999999999998e-06,"profit_total_abs":-0.0030748,"backtest_start":"2018-01-10 07:25:00","backtest_start_ts":1515569100000,"backtest_end":"2018-01-30 04:45:00","backtest_end_ts":1517287500000,"backtest_days":19,"backtest_run_start_ts":1620793107,"backtest_run_end_ts":1620793108,"trades_per_day":1.16,"market_change":0,"pairlist":["ETH/BTC","LTC/BTC","ETC/BTC","XLM/BTC","TRX/BTC","ADA/BTC"],"stake_amount":0.05,"stake_currency":"BTC","stake_currency_decimals":8,"starting_balance":1000,"dry_run_wallet":1000,"final_balance":999.9969252,"max_open_trades":3,"max_open_trades_setting":3,"timeframe":"5m","timerange":"","enable_protections":false,"strategy_name":"SampleStrategy","stoploss":-0.1,"trailing_stop":false,"trailing_stop_positive":null,"trailing_stop_positive_offset":0.0,"trailing_only_offset_is_reached":false,"use_custom_stoploss":false,"minimal_roi":{"60":0.01,"30":0.02,"0":0.04},"use_sell_signal":true,"sell_profit_only":false,"sell_profit_offset":0.0,"ignore_roi_if_buy_signal":false,"backtest_best_day":0.07872446,"backtest_worst_day":-0.09242451,"backtest_best_day_abs":0.00395,"backtest_worst_day_abs":-0.0046374,"winning_days":4,"draw_days":10,"losing_days":4,"wins":4,"losses":6,"draws":12,"holding_avg":"6:12:00","winner_holding_avg":"1:29:00","loser_holding_avg":"4:42:00","max_drawdown":0.18484901999999998,"max_drawdown_abs":0.0092748,"drawdown_start":"2018-01-14 23:15:00","drawdown_start_ts":1515971700000.0,"drawdown_end":"2018-01-23 09:40:00","drawdown_end_ts":1516700400000.0,"max_drawdown_low":-0.0038247999999999997,"max_drawdown_high":0.00545,"csum_min":999.9961752,"csum_max":1000.00545},"results_explanation":" 22 trades. 4/12/6 Wins/Draws/Losses. Avg profit -0.28%. Median profit 0.00%. Total profit -0.00307480 BTC ( -0.00\u03A3%). Avg duration 6:12:00 min.","total_profit":-3.0747999999999998e-06,"current_epoch":3,"is_initial_point":true,"is_best":true} -{"loss":-4.9544427978437175,"params_dict":{"mfi-value":"23","fastd-value":"40","adx-value":"50","rsi-value":"27","mfi-enabled":false,"fastd-enabled":true,"adx-enabled":true,"rsi-enabled":true,"trigger":"bb_lower","sell-mfi-value":"87","sell-fastd-value":"60","sell-adx-value":"81","sell-rsi-value":"69","sell-mfi-enabled":true,"sell-fastd-enabled":true,"sell-adx-enabled":false,"sell-rsi-enabled":false,"sell-trigger":"sell-sar_reversal","roi_t1":"105","roi_t2":"43","roi_t3":"12","roi_p1":0.03,"roi_p2":0.036,"roi_p3":0.103,"stoploss":-0.081},"params_details":{"buy":{"mfi-value":"23","fastd-value":"40","adx-value":"50","rsi-value":"27","mfi-enabled":false,"fastd-enabled":true,"adx-enabled":true,"rsi-enabled":true,"trigger":"bb_lower"},"sell":{"sell-mfi-value":"87","sell-fastd-value":"60","sell-adx-value":"81","sell-rsi-value":"69","sell-mfi-enabled":true,"sell-fastd-enabled":true,"sell-adx-enabled":false,"sell-rsi-enabled":false,"sell-trigger":"sell-sar_reversal"},"roi":"{0: 0.16899999999999998, 12: 0.066, 55: 0.03, 160: 0}","stoploss":{"stoploss":-0.081}},"params_not_optimized":{"buy":{},"sell":{}},"results_metrics":{"trades":[{"pair":"XLM/BTC","stake_amount":0.05,"amount":1086.95652174,"open_date":"2018-01-13 13:30:00+00:00","close_date":"2018-01-13 16:30:00+00:00","open_rate":4.6e-05,"close_rate":4.632313095835424e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":180,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":4.2274e-05,"initial_stop_loss_ratio":-0.081,"stop_loss_abs":4.2274e-05,"stop_loss_ratio":-0.081,"min_rate":4.4980000000000006e-05,"max_rate":4.673e-05,"is_open":false,"open_timestamp":1515850200000.0,"close_timestamp":1515861000000.0},{"pair":"ADA/BTC","stake_amount":0.05,"amount":851.35365231,"open_date":"2018-01-15 14:50:00+00:00","close_date":"2018-01-15 16:15:00+00:00","open_rate":5.873000000000001e-05,"close_rate":6.0910642247867544e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":85,"profit_ratio":0.02989537,"profit_abs":0.0015,"sell_reason":"roi","initial_stop_loss_abs":5.397287000000001e-05,"initial_stop_loss_ratio":-0.081,"stop_loss_abs":5.397287000000001e-05,"stop_loss_ratio":-0.081,"min_rate":5.873000000000001e-05,"max_rate":6.120000000000001e-05,"is_open":false,"open_timestamp":1516027800000.0,"close_timestamp":1516032900000.0},{"pair":"ADA/BTC","stake_amount":0.05,"amount":896.86098655,"open_date":"2018-01-16 00:35:00+00:00","close_date":"2018-01-16 03:15:00+00:00","open_rate":5.575000000000001e-05,"close_rate":5.6960000000000004e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":160,"profit_ratio":0.01457705,"profit_abs":0.0007314,"sell_reason":"roi","initial_stop_loss_abs":5.123425000000001e-05,"initial_stop_loss_ratio":-0.081,"stop_loss_abs":5.123425000000001e-05,"stop_loss_ratio":-0.081,"min_rate":5.575000000000001e-05,"max_rate":5.730000000000001e-05,"is_open":false,"open_timestamp":1516062900000.0,"close_timestamp":1516072500000.0},{"pair":"TRX/BTC","stake_amount":0.05,"amount":747.160789,"open_date":"2018-01-16 22:30:00+00:00","close_date":"2018-01-16 22:45:00+00:00","open_rate":6.692e-05,"close_rate":7.182231811339689e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":15,"profit_ratio":0.06576981,"profit_abs":0.0033,"sell_reason":"roi","initial_stop_loss_abs":6.149948000000001e-05,"initial_stop_loss_ratio":-0.081,"stop_loss_abs":6.149948000000001e-05,"stop_loss_ratio":-0.081,"min_rate":6.692e-05,"max_rate":7.566e-05,"is_open":false,"open_timestamp":1516141800000.0,"close_timestamp":1516142700000.0},{"pair":"TRX/BTC","stake_amount":0.05,"amount":720.5649229,"open_date":"2018-01-17 15:15:00+00:00","close_date":"2018-01-17 16:40:00+00:00","open_rate":6.939000000000001e-05,"close_rate":7.19664475664827e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":85,"profit_ratio":0.02989537,"profit_abs":0.0015,"sell_reason":"roi","initial_stop_loss_abs":6.376941000000001e-05,"initial_stop_loss_ratio":-0.081,"stop_loss_abs":6.376941000000001e-05,"stop_loss_ratio":-0.081,"min_rate":6.758e-05,"max_rate":7.244e-05,"is_open":false,"open_timestamp":1516202100000.0,"close_timestamp":1516207200000.0},{"pair":"XLM/BTC","stake_amount":0.05,"amount":1144.42664225,"open_date":"2018-01-18 22:20:00+00:00","close_date":"2018-01-19 00:35:00+00:00","open_rate":4.3690000000000004e-05,"close_rate":4.531220772704466e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":135,"profit_ratio":0.02989537,"profit_abs":0.0015,"sell_reason":"roi","initial_stop_loss_abs":4.015111e-05,"initial_stop_loss_ratio":-0.081,"stop_loss_abs":4.015111e-05,"stop_loss_ratio":-0.081,"min_rate":4.3690000000000004e-05,"max_rate":4.779e-05,"is_open":false,"open_timestamp":1516314000000.0,"close_timestamp":1516322100000.0},{"pair":"ADA/BTC","stake_amount":0.05,"amount":876.57784011,"open_date":"2018-01-18 22:25:00+00:00","close_date":"2018-01-19 01:05:00+00:00","open_rate":5.704e-05,"close_rate":5.792e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":160,"profit_ratio":0.00834457,"profit_abs":0.00041869,"sell_reason":"roi","initial_stop_loss_abs":5.2419760000000006e-05,"initial_stop_loss_ratio":-0.081,"stop_loss_abs":5.2419760000000006e-05,"stop_loss_ratio":-0.081,"min_rate":5.704e-05,"max_rate":5.8670000000000006e-05,"is_open":false,"open_timestamp":1516314300000.0,"close_timestamp":1516323900000.0},{"pair":"TRX/BTC","stake_amount":0.05,"amount":525.59655209,"open_date":"2018-01-20 05:05:00+00:00","close_date":"2018-01-20 06:25:00+00:00","open_rate":9.513e-05,"close_rate":9.86621726041144e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":80,"profit_ratio":0.02989537,"profit_abs":0.0015,"sell_reason":"roi","initial_stop_loss_abs":8.742447000000001e-05,"initial_stop_loss_ratio":-0.081,"stop_loss_abs":8.742447000000001e-05,"stop_loss_ratio":-0.081,"min_rate":9.513e-05,"max_rate":9.95e-05,"is_open":false,"open_timestamp":1516424700000.0,"close_timestamp":1516429500000.0},{"pair":"ADA/BTC","stake_amount":0.05,"amount":920.64076597,"open_date":"2018-01-26 07:40:00+00:00","close_date":"2018-01-26 10:20:00+00:00","open_rate":5.431000000000001e-05,"close_rate":5.474000000000001e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":160,"profit_ratio":0.0008867,"profit_abs":4.449e-05,"sell_reason":"roi","initial_stop_loss_abs":4.991089000000001e-05,"initial_stop_loss_ratio":-0.081,"stop_loss_abs":4.991089000000001e-05,"stop_loss_ratio":-0.081,"min_rate":5.3670000000000006e-05,"max_rate":5.5e-05,"is_open":false,"open_timestamp":1516952400000.0,"close_timestamp":1516962000000.0},{"pair":"XLM/BTC","stake_amount":0.05,"amount":944.28706327,"open_date":"2018-01-28 04:35:00+00:00","close_date":"2018-01-30 04:45:00+00:00","open_rate":5.2950000000000006e-05,"close_rate":4.995000000000001e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":2890,"profit_ratio":-0.06323759,"profit_abs":-0.00317295,"sell_reason":"force_sell","initial_stop_loss_abs":4.866105000000001e-05,"initial_stop_loss_ratio":-0.081,"stop_loss_abs":4.866105000000001e-05,"stop_loss_ratio":-0.081,"min_rate":4.980000000000001e-05,"max_rate":5.3280000000000005e-05,"is_open":true,"open_timestamp":1517114100000.0,"close_timestamp":1517287500000.0}],"locks":[],"best_pair":{"key":"TRX/BTC","trades":3,"profit_mean":0.04185351666666667,"profit_mean_pct":4.185351666666667,"profit_sum":0.12556055,"profit_sum_pct":12.56,"profit_total_abs":0.0063,"profit_total":6.3e-06,"profit_total_pct":0.0,"duration_avg":"1:00:00","wins":3,"draws":0,"losses":0},"worst_pair":{"key":"XLM/BTC","trades":3,"profit_mean":-0.01111407333333333,"profit_mean_pct":-1.111407333333333,"profit_sum":-0.03334221999999999,"profit_sum_pct":-3.33,"profit_total_abs":-0.0016729499999999999,"profit_total":-1.6729499999999998e-06,"profit_total_pct":-0.0,"duration_avg":"17:48:00","wins":1,"draws":1,"losses":1},"results_per_pair":[{"key":"TRX/BTC","trades":3,"profit_mean":0.04185351666666667,"profit_mean_pct":4.185351666666667,"profit_sum":0.12556055,"profit_sum_pct":12.56,"profit_total_abs":0.0063,"profit_total":6.3e-06,"profit_total_pct":0.0,"duration_avg":"1:00:00","wins":3,"draws":0,"losses":0},{"key":"ADA/BTC","trades":4,"profit_mean":0.0134259225,"profit_mean_pct":1.34259225,"profit_sum":0.05370369,"profit_sum_pct":5.37,"profit_total_abs":0.00269458,"profit_total":2.69458e-06,"profit_total_pct":0.0,"duration_avg":"2:21:00","wins":4,"draws":0,"losses":0},{"key":"ETH/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"LTC/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"ETC/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"XLM/BTC","trades":3,"profit_mean":-0.01111407333333333,"profit_mean_pct":-1.111407333333333,"profit_sum":-0.03334221999999999,"profit_sum_pct":-3.33,"profit_total_abs":-0.0016729499999999999,"profit_total":-1.6729499999999998e-06,"profit_total_pct":-0.0,"duration_avg":"17:48:00","wins":1,"draws":1,"losses":1},{"key":"TOTAL","trades":10,"profit_mean":0.014592201999999999,"profit_mean_pct":1.4592201999999999,"profit_sum":0.14592201999999999,"profit_sum_pct":14.59,"profit_total_abs":0.00732163,"profit_total":7.32163e-06,"profit_total_pct":0.0,"duration_avg":"6:35:00","wins":8,"draws":1,"losses":1}],"sell_reason_summary":[{"sell_reason":"roi","trades":9,"wins":8,"draws":1,"losses":0,"profit_mean":0.023239956666666665,"profit_mean_pct":2.32,"profit_sum":0.20915961,"profit_sum_pct":20.92,"profit_total_abs":0.01049458,"profit_total":0.06971987,"profit_total_pct":6.97},{"sell_reason":"force_sell","trades":1,"wins":0,"draws":0,"losses":1,"profit_mean":-0.06323759,"profit_mean_pct":-6.32,"profit_sum":-0.06323759,"profit_sum_pct":-6.32,"profit_total_abs":-0.00317295,"profit_total":-0.021079196666666664,"profit_total_pct":-2.11}],"left_open_trades":[{"key":"XLM/BTC","trades":1,"profit_mean":-0.06323759,"profit_mean_pct":-6.323759,"profit_sum":-0.06323759,"profit_sum_pct":-6.32,"profit_total_abs":-0.00317295,"profit_total":-3.17295e-06,"profit_total_pct":-0.0,"duration_avg":"2 days, 0:10:00","wins":0,"draws":0,"losses":1},{"key":"TOTAL","trades":1,"profit_mean":-0.06323759,"profit_mean_pct":-6.323759,"profit_sum":-0.06323759,"profit_sum_pct":-6.32,"profit_total_abs":-0.00317295,"profit_total":-3.17295e-06,"profit_total_pct":-0.0,"duration_avg":"2 days, 0:10:00","wins":0,"draws":0,"losses":1}],"total_trades":10,"total_volume":0.5,"avg_stake_amount":0.05,"profit_mean":0.014592201999999999,"profit_median":0.02223621,"profit_total":7.32163e-06,"profit_total_abs":0.00732163,"backtest_start":"2018-01-10 07:25:00","backtest_start_ts":1515569100000,"backtest_end":"2018-01-30 04:45:00","backtest_end_ts":1517287500000,"backtest_days":19,"backtest_run_start_ts":1620793107,"backtest_run_end_ts":1620793108,"trades_per_day":0.53,"market_change":0,"pairlist":["ETH/BTC","LTC/BTC","ETC/BTC","XLM/BTC","TRX/BTC","ADA/BTC"],"stake_amount":0.05,"stake_currency":"BTC","stake_currency_decimals":8,"starting_balance":1000,"dry_run_wallet":1000,"final_balance":1000.00732163,"max_open_trades":3,"max_open_trades_setting":3,"timeframe":"5m","timerange":"","enable_protections":false,"strategy_name":"SampleStrategy","stoploss":-0.1,"trailing_stop":false,"trailing_stop_positive":null,"trailing_stop_positive_offset":0.0,"trailing_only_offset_is_reached":false,"use_custom_stoploss":false,"minimal_roi":{"60":0.01,"30":0.02,"0":0.04},"use_sell_signal":true,"sell_profit_only":false,"sell_profit_offset":0.0,"ignore_roi_if_buy_signal":false,"backtest_best_day":0.08034685999999999,"backtest_worst_day":-0.06323759,"backtest_best_day_abs":0.0040314,"backtest_worst_day_abs":-0.00317295,"winning_days":6,"draw_days":11,"losing_days":1,"wins":8,"losses":1,"draws":1,"holding_avg":"6:35:00","winner_holding_avg":"1:50:00","loser_holding_avg":"2 days, 0:10:00","max_drawdown":0.06323759000000001,"max_drawdown_abs":0.00317295,"drawdown_start":"2018-01-26 10:20:00","drawdown_start_ts":1516962000000.0,"drawdown_end":"2018-01-30 04:45:00","drawdown_end_ts":1517287500000.0,"max_drawdown_low":0.007321629999999998,"max_drawdown_high":0.010494579999999998,"csum_min":1000.0,"csum_max":1000.01049458},"results_explanation":" 10 trades. 8/1/1 Wins/Draws/Losses. Avg profit 1.46%. Median profit 2.22%. Total profit 0.00732163 BTC ( 0.00\u03A3%). Avg duration 6:35:00 min.","total_profit":7.32163e-06,"current_epoch":4,"is_initial_point":true,"is_best":true} -{"loss":0.16709185414267655,"params_dict":{"mfi-value":"10","fastd-value":"45","adx-value":"28","rsi-value":"37","mfi-enabled":false,"fastd-enabled":false,"adx-enabled":true,"rsi-enabled":true,"trigger":"macd_cross_signal","sell-mfi-value":"85","sell-fastd-value":"56","sell-adx-value":"98","sell-rsi-value":"89","sell-mfi-enabled":true,"sell-fastd-enabled":false,"sell-adx-enabled":true,"sell-rsi-enabled":false,"sell-trigger":"sell-sar_reversal","roi_t1":"85","roi_t2":"11","roi_t3":"24","roi_p1":0.04,"roi_p2":0.043,"roi_p3":0.053,"stoploss":-0.057},"params_details":{"buy":{"mfi-value":"10","fastd-value":"45","adx-value":"28","rsi-value":"37","mfi-enabled":false,"fastd-enabled":false,"adx-enabled":true,"rsi-enabled":true,"trigger":"macd_cross_signal"},"sell":{"sell-mfi-value":"85","sell-fastd-value":"56","sell-adx-value":"98","sell-rsi-value":"89","sell-mfi-enabled":true,"sell-fastd-enabled":false,"sell-adx-enabled":true,"sell-rsi-enabled":false,"sell-trigger":"sell-sar_reversal"},"roi":"{0: 0.13599999999999998, 24: 0.08299999999999999, 35: 0.04, 120: 0}","stoploss":{"stoploss":-0.057}},"params_not_optimized":{"buy":{},"sell":{}},"results_metrics":{"trades":[{"pair":"ETH/BTC","stake_amount":0.05,"amount":0.56173464,"open_date":"2018-01-10 19:15:00+00:00","close_date":"2018-01-10 21:15:00+00:00","open_rate":0.08901,"close_rate":0.09112999000000001,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":120,"profit_ratio":0.01667571,"profit_abs":0.0008367,"sell_reason":"roi","initial_stop_loss_abs":0.08393643,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":0.08393643,"stop_loss_ratio":-0.057,"min_rate":0.08894498,"max_rate":0.09116998,"is_open":false,"open_timestamp":1515611700000.0,"close_timestamp":1515618900000.0},{"pair":"ADA/BTC","stake_amount":0.05,"amount":794.65988557,"open_date":"2018-01-13 11:30:00+00:00","close_date":"2018-01-13 15:10:00+00:00","open_rate":6.292e-05,"close_rate":5.9333559999999994e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":220,"profit_ratio":-0.06357798,"profit_abs":-0.00319003,"sell_reason":"stop_loss","initial_stop_loss_abs":5.9333559999999994e-05,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":5.9333559999999994e-05,"stop_loss_ratio":-0.057,"min_rate":5.9900000000000006e-05,"max_rate":6.353e-05,"is_open":false,"open_timestamp":1515843000000.0,"close_timestamp":1515856200000.0},{"pair":"XLM/BTC","stake_amount":0.05,"amount":1086.95652174,"open_date":"2018-01-13 14:35:00+00:00","close_date":"2018-01-13 21:40:00+00:00","open_rate":4.6e-05,"close_rate":4.632313095835424e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":425,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":4.3378e-05,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":4.3378e-05,"stop_loss_ratio":-0.057,"min_rate":4.4980000000000006e-05,"max_rate":4.6540000000000005e-05,"is_open":false,"open_timestamp":1515854100000.0,"close_timestamp":1515879600000.0},{"pair":"ETH/BTC","stake_amount":0.05,"amount":0.53757603,"open_date":"2018-01-15 13:15:00+00:00","close_date":"2018-01-15 15:15:00+00:00","open_rate":0.0930101,"close_rate":0.09366345745107878,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":120,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.0877085243,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":0.0877085243,"stop_loss_ratio":-0.057,"min_rate":0.09188489999999999,"max_rate":0.09380000000000001,"is_open":false,"open_timestamp":1516022100000.0,"close_timestamp":1516029300000.0},{"pair":"ETC/BTC","stake_amount":0.05,"amount":17.07469496,"open_date":"2018-01-15 14:35:00+00:00","close_date":"2018-01-15 16:35:00+00:00","open_rate":0.00292831,"close_rate":0.00297503,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":120,"profit_ratio":0.00886772,"profit_abs":0.00044494,"sell_reason":"roi","initial_stop_loss_abs":0.0027613963299999997,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":0.0027613963299999997,"stop_loss_ratio":-0.057,"min_rate":0.00292831,"max_rate":0.00301259,"is_open":false,"open_timestamp":1516026900000.0,"close_timestamp":1516034100000.0},{"pair":"TRX/BTC","stake_amount":0.05,"amount":702.44450688,"open_date":"2018-01-17 04:25:00+00:00","close_date":"2018-01-17 05:00:00+00:00","open_rate":7.118e-05,"close_rate":7.453721023582538e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":35,"profit_ratio":0.03986049,"profit_abs":0.002,"sell_reason":"roi","initial_stop_loss_abs":6.712274e-05,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":6.712274e-05,"stop_loss_ratio":-0.057,"min_rate":7.118e-05,"max_rate":7.658000000000002e-05,"is_open":false,"open_timestamp":1516163100000.0,"close_timestamp":1516165200000.0},{"pair":"ETC/BTC","stake_amount":0.05,"amount":18.86756854,"open_date":"2018-01-20 06:05:00+00:00","close_date":"2018-01-20 08:05:00+00:00","open_rate":0.00265005,"close_rate":0.00266995,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":120,"profit_ratio":0.00048133,"profit_abs":2.415e-05,"sell_reason":"roi","initial_stop_loss_abs":0.00249899715,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":0.00249899715,"stop_loss_ratio":-0.057,"min_rate":0.00265005,"max_rate":0.00271,"is_open":false,"open_timestamp":1516428300000.0,"close_timestamp":1516435500000.0},{"pair":"ADA/BTC","stake_amount":0.05,"amount":966.18357488,"open_date":"2018-01-22 03:25:00+00:00","close_date":"2018-01-22 07:05:00+00:00","open_rate":5.1750000000000004e-05,"close_rate":5.211352232814853e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":220,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":4.8800250000000004e-05,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":4.8800250000000004e-05,"stop_loss_ratio":-0.057,"min_rate":5.1750000000000004e-05,"max_rate":5.2170000000000004e-05,"is_open":false,"open_timestamp":1516591500000.0,"close_timestamp":1516604700000.0},{"pair":"ETC/BTC","stake_amount":0.05,"amount":18.95303438,"open_date":"2018-01-23 13:10:00+00:00","close_date":"2018-01-23 16:00:00+00:00","open_rate":0.0026381,"close_rate":0.002656631560461616,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":170,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.0024877283,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":0.0024877283,"stop_loss_ratio":-0.057,"min_rate":0.0026100000000000003,"max_rate":0.00266,"is_open":false,"open_timestamp":1516713000000.0,"close_timestamp":1516723200000.0},{"pair":"ADA/BTC","stake_amount":0.05,"amount":912.40875912,"open_date":"2018-01-26 06:30:00+00:00","close_date":"2018-01-26 10:45:00+00:00","open_rate":5.480000000000001e-05,"close_rate":5.518494731560462e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":255,"profit_ratio":-0.0,"profit_abs":-0.0,"sell_reason":"roi","initial_stop_loss_abs":5.1676400000000006e-05,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":5.1676400000000006e-05,"stop_loss_ratio":-0.057,"min_rate":5.3670000000000006e-05,"max_rate":5.523e-05,"is_open":false,"open_timestamp":1516948200000.0,"close_timestamp":1516963500000.0},{"pair":"ADA/BTC","stake_amount":0.05,"amount":909.58704748,"open_date":"2018-01-27 02:10:00+00:00","close_date":"2018-01-27 05:40:00+00:00","open_rate":5.4970000000000004e-05,"close_rate":5.535614149523332e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":210,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":5.183671e-05,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":5.183671e-05,"stop_loss_ratio":-0.057,"min_rate":5.472000000000001e-05,"max_rate":5.556e-05,"is_open":false,"open_timestamp":1517019000000.0,"close_timestamp":1517031600000.0}],"locks":[],"best_pair":{"key":"TRX/BTC","trades":1,"profit_mean":0.03986049,"profit_mean_pct":3.986049,"profit_sum":0.03986049,"profit_sum_pct":3.99,"profit_total_abs":0.002,"profit_total":2e-06,"profit_total_pct":0.0,"duration_avg":"0:35:00","wins":1,"draws":0,"losses":0},"worst_pair":{"key":"ADA/BTC","trades":4,"profit_mean":-0.015894495,"profit_mean_pct":-1.5894495000000002,"profit_sum":-0.06357798,"profit_sum_pct":-6.36,"profit_total_abs":-0.00319003,"profit_total":-3.19003e-06,"profit_total_pct":-0.0,"duration_avg":"3:46:00","wins":0,"draws":3,"losses":1},"results_per_pair":[{"key":"TRX/BTC","trades":1,"profit_mean":0.03986049,"profit_mean_pct":3.986049,"profit_sum":0.03986049,"profit_sum_pct":3.99,"profit_total_abs":0.002,"profit_total":2e-06,"profit_total_pct":0.0,"duration_avg":"0:35:00","wins":1,"draws":0,"losses":0},{"key":"ETH/BTC","trades":2,"profit_mean":0.008337855,"profit_mean_pct":0.8337855,"profit_sum":0.01667571,"profit_sum_pct":1.67,"profit_total_abs":0.0008367,"profit_total":8.367e-07,"profit_total_pct":0.0,"duration_avg":"2:00:00","wins":1,"draws":1,"losses":0},{"key":"ETC/BTC","trades":3,"profit_mean":0.0031163500000000004,"profit_mean_pct":0.31163500000000005,"profit_sum":0.009349050000000001,"profit_sum_pct":0.93,"profit_total_abs":0.00046909,"profit_total":4.6909000000000003e-07,"profit_total_pct":0.0,"duration_avg":"2:17:00","wins":2,"draws":1,"losses":0},{"key":"LTC/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"XLM/BTC","trades":1,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"7:05:00","wins":0,"draws":1,"losses":0},{"key":"ADA/BTC","trades":4,"profit_mean":-0.015894495,"profit_mean_pct":-1.5894495000000002,"profit_sum":-0.06357798,"profit_sum_pct":-6.36,"profit_total_abs":-0.00319003,"profit_total":-3.19003e-06,"profit_total_pct":-0.0,"duration_avg":"3:46:00","wins":0,"draws":3,"losses":1},{"key":"TOTAL","trades":11,"profit_mean":0.00020975181818181756,"profit_mean_pct":0.020975181818181757,"profit_sum":0.002307269999999993,"profit_sum_pct":0.23,"profit_total_abs":0.00011576000000000034,"profit_total":1.1576000000000034e-07,"profit_total_pct":0.0,"duration_avg":"3:03:00","wins":4,"draws":6,"losses":1}],"sell_reason_summary":[{"sell_reason":"roi","trades":10,"wins":4,"draws":6,"losses":0,"profit_mean":0.0065885250000000005,"profit_mean_pct":0.66,"profit_sum":0.06588525,"profit_sum_pct":6.59,"profit_total_abs":0.0033057900000000003,"profit_total":0.021961750000000002,"profit_total_pct":2.2},{"sell_reason":"stop_loss","trades":1,"wins":0,"draws":0,"losses":1,"profit_mean":-0.06357798,"profit_mean_pct":-6.36,"profit_sum":-0.06357798,"profit_sum_pct":-6.36,"profit_total_abs":-0.00319003,"profit_total":-0.021192660000000002,"profit_total_pct":-2.12}],"left_open_trades":[{"key":"TOTAL","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0}],"total_trades":11,"total_volume":0.55,"avg_stake_amount":0.05,"profit_mean":0.00020975181818181756,"profit_median":0.0,"profit_total":1.1576000000000034e-07,"profit_total_abs":0.00011576000000000034,"backtest_start":"2018-01-10 07:25:00","backtest_start_ts":1515569100000,"backtest_end":"2018-01-30 04:45:00","backtest_end_ts":1517287500000,"backtest_days":19,"backtest_run_start_ts":1620793107,"backtest_run_end_ts":1620793108,"trades_per_day":0.58,"market_change":0,"pairlist":["ETH/BTC","LTC/BTC","ETC/BTC","XLM/BTC","TRX/BTC","ADA/BTC"],"stake_amount":0.05,"stake_currency":"BTC","stake_currency_decimals":8,"starting_balance":1000,"dry_run_wallet":1000,"final_balance":1000.00011576,"max_open_trades":3,"max_open_trades_setting":3,"timeframe":"5m","timerange":"","enable_protections":false,"strategy_name":"SampleStrategy","stoploss":-0.1,"trailing_stop":false,"trailing_stop_positive":null,"trailing_stop_positive_offset":0.0,"trailing_only_offset_is_reached":false,"use_custom_stoploss":false,"minimal_roi":{"60":0.01,"30":0.02,"0":0.04},"use_sell_signal":true,"sell_profit_only":false,"sell_profit_offset":0.0,"ignore_roi_if_buy_signal":false,"backtest_best_day":0.03986049,"backtest_worst_day":-0.06357798,"backtest_best_day_abs":0.002,"backtest_worst_day_abs":-0.00319003,"winning_days":4,"draw_days":13,"losing_days":1,"wins":4,"losses":1,"draws":6,"holding_avg":"3:03:00","winner_holding_avg":"1:39:00","loser_holding_avg":"3:40:00","max_drawdown":0.06357798,"max_drawdown_abs":0.00319003,"drawdown_start":"2018-01-10 21:15:00","drawdown_start_ts":1515618900000.0,"drawdown_end":"2018-01-13 15:10:00","drawdown_end_ts":1515856200000.0,"max_drawdown_low":-0.00235333,"max_drawdown_high":0.0008367,"csum_min":999.99764667,"csum_max":1000.0008367},"results_explanation":" 11 trades. 4/6/1 Wins/Draws/Losses. Avg profit 0.02%. Median profit 0.00%. Total profit 0.00011576 BTC ( 0.00\u03A3%). Avg duration 3:03:00 min.","total_profit":1.1576000000000034e-07,"current_epoch":5,"is_initial_point":true,"is_best":false} +{"loss":100000,"params_dict":{"mfi-value":"20","fastd-value":"21","adx-value":"26","rsi-value":"23","mfi-enabled":true,"fastd-enabled":false,"adx-enabled":false,"rsi-enabled":true,"trigger":"sar_reversal","sell-mfi-value":"97","sell-fastd-value":"85","sell-adx-value":"55","sell-rsi-value":"76","sell-mfi-enabled":true,"sell-fastd-enabled":false,"sell-adx-enabled":true,"sell-rsi-enabled":true,"sell-trigger":"sell-bb_upper","roi_t1":"34","roi_t2":"28","roi_t3":"32","roi_p1":0.031,"roi_p2":0.033,"roi_p3":0.146,"stoploss":-0.05},"params_details":{"buy":{"mfi-value":"20","fastd-value":"21","adx-value":"26","rsi-value":"23","mfi-enabled":true,"fastd-enabled":false,"adx-enabled":false,"rsi-enabled":true,"trigger":"sar_reversal"},"sell":{"sell-mfi-value":"97","sell-fastd-value":"85","sell-adx-value":"55","sell-rsi-value":"76","sell-mfi-enabled":true,"sell-fastd-enabled":false,"sell-adx-enabled":true,"sell-rsi-enabled":true,"sell-trigger":"sell-bb_upper"},"roi":"{0: 0.21, 32: 0.064, 60: 0.031, 94: 0}","stoploss":{"stoploss":-0.05}},"params_not_optimized":{"buy":{},"sell":{}},"results_metrics":{"trades":[],"locks":[],"best_pair":{"key":"ETH/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},"worst_pair":{"key":"ETH/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},"results_per_pair":[{"key":"ETH/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"LTC/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"ETC/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"XLM/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"TRX/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"ADA/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"TOTAL","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0}],"sell_reason_summary":[],"left_open_trades":[{"key":"TOTAL","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0}],"total_trades":0,"total_volume":0.0,"avg_stake_amount":0,"profit_mean":0,"profit_median":0,"profit_total":0.0,"profit_total_abs":0,"backtest_start":"2018-01-10 07:25:00","backtest_start_ts":1515569100000,"backtest_end":"2018-01-30 04:45:00","backtest_end_ts":1517287500000,"backtest_days":19,"backtest_run_start_ts":1620793107,"backtest_run_end_ts":1620793107,"trades_per_day":0.0,"market_change":0,"pairlist":["ETH/BTC","LTC/BTC","ETC/BTC","XLM/BTC","TRX/BTC","ADA/BTC"],"stake_amount":0.05,"stake_currency":"BTC","stake_currency_decimals":8,"starting_balance":1000,"dry_run_wallet":1000,"final_balance":1000,"max_open_trades":3,"max_open_trades_setting":3,"timeframe":"5m","timerange":"","enable_protections":false,"strategy_name":"SampleStrategy","stoploss":-0.1,"trailing_stop":false,"trailing_stop_positive":null,"trailing_stop_positive_offset":0.0,"trailing_only_offset_is_reached":false,"use_custom_stoploss":false,"minimal_roi":{"60":0.01,"30":0.02,"0":0.04},"use_exit_signal":true,"exit_profit_only":false,"exit_profit_offset":0.0,"ignore_roi_if_entry_signal":false,"backtest_best_day":0,"backtest_worst_day":0,"backtest_best_day_abs":0,"backtest_worst_day_abs":0,"winning_days":0,"draw_days":0,"losing_days":0,"wins":0,"losses":0,"draws":0,"holding_avg":"0:00:00","winner_holding_avg":"0:00:00","loser_holding_avg":"0:00:00","max_drawdown":0.0,"max_drawdown_abs":0.0,"max_drawdown_low":0.0,"max_drawdown_high":0.0,"drawdown_start":"1970-01-01 00:00:00+00:00","drawdown_start_ts":0,"drawdown_end":"1970-01-01 00:00:00+00:00","drawdown_end_ts":0,"csum_min":0,"csum_max":0},"results_explanation":" 0 trades. 0/0/0 Wins/Draws/Losses. Avg profit 0.00%. Median profit 0.00%. Total profit 0.00000000 BTC ( 0.00\u03A3%). Avg duration 0:00:00 min.","total_profit":0.0,"current_epoch":1,"is_initial_point":true,"is_best":false} +{"loss":100000,"params_dict":{"mfi-value":"14","fastd-value":"43","adx-value":"30","rsi-value":"24","mfi-enabled":true,"fastd-enabled":true,"adx-enabled":false,"rsi-enabled":true,"trigger":"sar_reversal","sell-mfi-value":"97","sell-fastd-value":"71","sell-adx-value":"82","sell-rsi-value":"99","sell-mfi-enabled":false,"sell-fastd-enabled":false,"sell-adx-enabled":false,"sell-rsi-enabled":true,"sell-trigger":"sell-bb_upper","roi_t1":"84","roi_t2":"35","roi_t3":"19","roi_p1":0.024,"roi_p2":0.022,"roi_p3":0.061,"stoploss":-0.083},"params_details":{"buy":{"mfi-value":"14","fastd-value":"43","adx-value":"30","rsi-value":"24","mfi-enabled":true,"fastd-enabled":true,"adx-enabled":false,"rsi-enabled":true,"trigger":"sar_reversal"},"sell":{"sell-mfi-value":"97","sell-fastd-value":"71","sell-adx-value":"82","sell-rsi-value":"99","sell-mfi-enabled":false,"sell-fastd-enabled":false,"sell-adx-enabled":false,"sell-rsi-enabled":true,"sell-trigger":"sell-bb_upper"},"roi":"{0: 0.107, 19: 0.046, 54: 0.024, 138: 0}","stoploss":{"stoploss":-0.083}},"params_not_optimized":{"buy":{},"sell":{}},"results_metrics":{"trades":[],"locks":[],"best_pair":{"key":"ETH/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},"worst_pair":{"key":"ETH/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},"results_per_pair":[{"key":"ETH/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"LTC/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"ETC/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"XLM/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"TRX/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"ADA/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"TOTAL","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0}],"sell_reason_summary":[],"left_open_trades":[{"key":"TOTAL","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0,"profit_sum_pct":0.0,"profit_total_abs":0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0}],"total_trades":0,"total_volume":0.0,"avg_stake_amount":0,"profit_mean":0,"profit_median":0,"profit_total":0.0,"profit_total_abs":0,"backtest_start":"2018-01-10 07:25:00","backtest_start_ts":1515569100000,"backtest_end":"2018-01-30 04:45:00","backtest_end_ts":1517287500000,"backtest_days":19,"backtest_run_start_ts":1620793107,"backtest_run_end_ts":1620793108,"trades_per_day":0.0,"market_change":0,"pairlist":["ETH/BTC","LTC/BTC","ETC/BTC","XLM/BTC","TRX/BTC","ADA/BTC"],"stake_amount":0.05,"stake_currency":"BTC","stake_currency_decimals":8,"starting_balance":1000,"dry_run_wallet":1000,"final_balance":1000,"max_open_trades":3,"max_open_trades_setting":3,"timeframe":"5m","timerange":"","enable_protections":false,"strategy_name":"SampleStrategy","stoploss":-0.1,"trailing_stop":false,"trailing_stop_positive":null,"trailing_stop_positive_offset":0.0,"trailing_only_offset_is_reached":false,"use_custom_stoploss":false,"minimal_roi":{"60":0.01,"30":0.02,"0":0.04},"use_exit_signal":true,"exit_profit_only":false,"exit_profit_offset":0.0,"ignore_roi_if_entry_signal":false,"backtest_best_day":0,"backtest_worst_day":0,"backtest_best_day_abs":0,"backtest_worst_day_abs":0,"winning_days":0,"draw_days":0,"losing_days":0,"wins":0,"losses":0,"draws":0,"holding_avg":"0:00:00","winner_holding_avg":"0:00:00","loser_holding_avg":"0:00:00","max_drawdown":0.0,"max_drawdown_abs":0.0,"max_drawdown_low":0.0,"max_drawdown_high":0.0,"drawdown_start":"1970-01-01 00:00:00+00:00","drawdown_start_ts":0,"drawdown_end":"1970-01-01 00:00:00+00:00","drawdown_end_ts":0,"csum_min":0,"csum_max":0},"results_explanation":" 0 trades. 0/0/0 Wins/Draws/Losses. Avg profit 0.00%. Median profit 0.00%. Total profit 0.00000000 BTC ( 0.00\u03A3%). Avg duration 0:00:00 min.","total_profit":0.0,"current_epoch":2,"is_initial_point":true,"is_best":false} +{"loss":2.183447401951895,"params_dict":{"mfi-value":"14","fastd-value":"15","adx-value":"40","rsi-value":"36","mfi-enabled":false,"fastd-enabled":true,"adx-enabled":false,"rsi-enabled":false,"trigger":"sar_reversal","sell-mfi-value":"92","sell-fastd-value":"84","sell-adx-value":"61","sell-rsi-value":"61","sell-mfi-enabled":true,"sell-fastd-enabled":true,"sell-adx-enabled":true,"sell-rsi-enabled":true,"sell-trigger":"sell-bb_upper","roi_t1":"68","roi_t2":"41","roi_t3":"21","roi_p1":0.015,"roi_p2":0.064,"roi_p3":0.126,"stoploss":-0.024},"params_details":{"buy":{"mfi-value":"14","fastd-value":"15","adx-value":"40","rsi-value":"36","mfi-enabled":false,"fastd-enabled":true,"adx-enabled":false,"rsi-enabled":false,"trigger":"sar_reversal"},"sell":{"sell-mfi-value":"92","sell-fastd-value":"84","sell-adx-value":"61","sell-rsi-value":"61","sell-mfi-enabled":true,"sell-fastd-enabled":true,"sell-adx-enabled":true,"sell-rsi-enabled":true,"sell-trigger":"sell-bb_upper"},"roi":"{0: 0.20500000000000002, 21: 0.079, 62: 0.015, 130: 0}","stoploss":{"stoploss":-0.024}},"params_not_optimized":{"buy":{},"sell":{}},"results_metrics":{"trades":[{"pair":"LTC/BTC","stake_amount":0.05,"amount":2.94115571,"open_date":"2018-01-11 11:40:00+00:00","close_date":"2018-01-11 19:40:00+00:00","open_rate":0.01700012,"close_rate":0.017119538805820372,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":480,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.01659211712,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.01659211712,"stop_loss_ratio":-0.024,"min_rate":0.01689809,"max_rate":0.0171462,"is_open":false,"open_timestamp":1515670800000.0,"close_timestamp":1515699600000.0},{"pair":"ETH/BTC","stake_amount":0.05,"amount":0.57407318,"open_date":"2018-01-12 11:05:00+00:00","close_date":"2018-01-12 12:30:00+00:00","open_rate":0.08709691,"close_rate":0.08901977203712995,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":85,"profit_ratio":0.01494768,"profit_abs":0.00075,"sell_reason":"roi","initial_stop_loss_abs":0.08500658416,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.08500658416,"stop_loss_ratio":-0.024,"min_rate":0.08702974000000001,"max_rate":0.08929248000000001,"is_open":false,"open_timestamp":1515755100000.0,"close_timestamp":1515760200000.0},{"pair":"LTC/BTC","stake_amount":0.05,"amount":2.93166236,"open_date":"2018-01-12 03:30:00+00:00","close_date":"2018-01-12 13:05:00+00:00","open_rate":0.01705517,"close_rate":0.01717497550928249,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":575,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.016645845920000003,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.016645845920000003,"stop_loss_ratio":-0.024,"min_rate":0.0169841,"max_rate":0.01719135,"is_open":false,"open_timestamp":1515727800000.0,"close_timestamp":1515762300000.0},{"pair":"LTC/BTC","stake_amount":0.05,"amount":2.96876855,"open_date":"2018-01-13 03:50:00+00:00","close_date":"2018-01-13 06:05:00+00:00","open_rate":0.016842,"close_rate":0.016960308078273957,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":135,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.016437792,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.016437792,"stop_loss_ratio":-0.024,"min_rate":0.016836999999999998,"max_rate":0.017,"is_open":false,"open_timestamp":1515815400000.0,"close_timestamp":1515823500000.0},{"pair":"ETH/BTC","stake_amount":0.05,"amount":0.53163205,"open_date":"2018-01-13 13:25:00+00:00","close_date":"2018-01-13 15:35:00+00:00","open_rate":0.09405001,"close_rate":0.09471067238835926,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":130,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.09179280976,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.09179280976,"stop_loss_ratio":-0.024,"min_rate":0.09369894000000001,"max_rate":0.09479997,"is_open":false,"open_timestamp":1515849900000.0,"close_timestamp":1515857700000.0},{"pair":"ETC/BTC","stake_amount":0.05,"amount":19.23816853,"open_date":"2018-01-13 15:30:00+00:00","close_date":"2018-01-13 16:20:00+00:00","open_rate":0.0025989999999999997,"close_rate":0.0028232990466633217,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":50,"profit_ratio":0.07872446,"profit_abs":0.00395,"sell_reason":"roi","initial_stop_loss_abs":0.002536624,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.002536624,"stop_loss_ratio":-0.024,"min_rate":0.00259525,"max_rate":0.0028288700000000003,"is_open":false,"open_timestamp":1515857400000.0,"close_timestamp":1515860400000.0},{"pair":"TRX/BTC","stake_amount":0.05,"amount":492.80504632,"open_date":"2018-01-14 21:35:00+00:00","close_date":"2018-01-14 23:15:00+00:00","open_rate":0.00010146000000000001,"close_rate":0.00010369995985950828,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":100,"profit_ratio":0.01494768,"profit_abs":0.00075,"sell_reason":"roi","initial_stop_loss_abs":9.902496e-05,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":9.902496e-05,"stop_loss_ratio":-0.024,"min_rate":0.0001012,"max_rate":0.00010414,"is_open":false,"open_timestamp":1515965700000.0,"close_timestamp":1515971700000.0},{"pair":"LTC/BTC","stake_amount":0.05,"amount":2.92398174,"open_date":"2018-01-15 12:45:00+00:00","close_date":"2018-01-15 21:05:00+00:00","open_rate":0.01709997,"close_rate":0.01722009021073758,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":500,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.016689570719999998,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.016689570719999998,"stop_loss_ratio":-0.024,"min_rate":0.01694,"max_rate":0.01725,"is_open":false,"open_timestamp":1516020300000.0,"close_timestamp":1516050300000.0},{"pair":"XLM/BTC","stake_amount":0.05,"amount":1111.60515785,"open_date":"2018-01-15 19:50:00+00:00","close_date":"2018-01-15 23:45:00+00:00","open_rate":4.4980000000000006e-05,"close_rate":4.390048e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":235,"profit_ratio":-0.03080817,"profit_abs":-0.0015458,"sell_reason":"stop_loss","initial_stop_loss_abs":4.390048e-05,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":4.390048e-05,"stop_loss_ratio":-0.024,"min_rate":4.409e-05,"max_rate":4.502e-05,"is_open":false,"open_timestamp":1516045800000.0,"close_timestamp":1516059900000.0},{"pair":"TRX/BTC","stake_amount":0.05,"amount":519.80455349,"open_date":"2018-01-21 03:55:00+00:00","close_date":"2018-01-21 04:05:00+00:00","open_rate":9.619e-05,"close_rate":9.388144e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":10,"profit_ratio":-0.03080817,"profit_abs":-0.0015458,"sell_reason":"stop_loss","initial_stop_loss_abs":9.388144e-05,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":9.388144e-05,"stop_loss_ratio":-0.024,"min_rate":9.568e-05,"max_rate":9.673e-05,"is_open":false,"open_timestamp":1516506900000.0,"close_timestamp":1516507500000.0},{"pair":"LTC/BTC","stake_amount":0.05,"amount":3.029754,"open_date":"2018-01-20 22:15:00+00:00","close_date":"2018-01-21 07:45:00+00:00","open_rate":0.01650299,"close_rate":0.016106918239999997,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":570,"profit_ratio":-0.03080817,"profit_abs":-0.0015458,"sell_reason":"stop_loss","initial_stop_loss_abs":0.016106918239999997,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.016106918239999997,"stop_loss_ratio":-0.024,"min_rate":0.0162468,"max_rate":0.01663179,"is_open":false,"open_timestamp":1516486500000.0,"close_timestamp":1516520700000.0},{"pair":"ETC/BTC","stake_amount":0.05,"amount":18.75461832,"open_date":"2018-01-21 13:00:00+00:00","close_date":"2018-01-21 16:25:00+00:00","open_rate":0.00266601,"close_rate":0.00260202576,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":205,"profit_ratio":-0.03080817,"profit_abs":-0.0015458,"sell_reason":"stop_loss","initial_stop_loss_abs":0.00260202576,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.00260202576,"stop_loss_ratio":-0.024,"min_rate":0.0026290800000000002,"max_rate":0.00269384,"is_open":false,"open_timestamp":1516539600000.0,"close_timestamp":1516551900000.0},{"pair":"TRX/BTC","stake_amount":0.05,"amount":552.18111541,"open_date":"2018-01-22 02:10:00+00:00","close_date":"2018-01-22 04:20:00+00:00","open_rate":9.055e-05,"close_rate":9.118607626693427e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":130,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":8.83768e-05,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":8.83768e-05,"stop_loss_ratio":-0.024,"min_rate":9.013e-05,"max_rate":9.197e-05,"is_open":false,"open_timestamp":1516587000000.0,"close_timestamp":1516594800000.0},{"pair":"LTC/BTC","stake_amount":0.05,"amount":2.99733237,"open_date":"2018-01-22 03:20:00+00:00","close_date":"2018-01-22 13:50:00+00:00","open_rate":0.0166815,"close_rate":0.016281143999999997,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":630,"profit_ratio":-0.03080817,"profit_abs":-0.0015458,"sell_reason":"stop_loss","initial_stop_loss_abs":0.016281143999999997,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.016281143999999997,"stop_loss_ratio":-0.024,"min_rate":0.01641443,"max_rate":0.016800000000000002,"is_open":false,"open_timestamp":1516591200000.0,"close_timestamp":1516629000000.0},{"pair":"TRX/BTC","stake_amount":0.05,"amount":503.52467271,"open_date":"2018-01-23 08:55:00+00:00","close_date":"2018-01-23 09:40:00+00:00","open_rate":9.93e-05,"close_rate":9.69168e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":45,"profit_ratio":-0.03080817,"profit_abs":-0.0015458,"sell_reason":"stop_loss","initial_stop_loss_abs":9.69168e-05,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":9.69168e-05,"stop_loss_ratio":-0.024,"min_rate":9.754e-05,"max_rate":0.00010025,"is_open":false,"open_timestamp":1516697700000.0,"close_timestamp":1516700400000.0},{"pair":"ETH/BTC","stake_amount":0.05,"amount":0.55148073,"open_date":"2018-01-24 02:10:00+00:00","close_date":"2018-01-24 04:40:00+00:00","open_rate":0.090665,"close_rate":0.09130188409433015,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":150,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.08848903999999999,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.08848903999999999,"stop_loss_ratio":-0.024,"min_rate":0.090665,"max_rate":0.09146000000000001,"is_open":false,"open_timestamp":1516759800000.0,"close_timestamp":1516768800000.0},{"pair":"ETC/BTC","stake_amount":0.05,"amount":19.10584639,"open_date":"2018-01-24 19:20:00+00:00","close_date":"2018-01-24 21:35:00+00:00","open_rate":0.002617,"close_rate":0.0026353833416959357,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":135,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.002554192,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.002554192,"stop_loss_ratio":-0.024,"min_rate":0.002617,"max_rate":0.00264999,"is_open":false,"open_timestamp":1516821600000.0,"close_timestamp":1516829700000.0},{"pair":"ETC/BTC","stake_amount":0.05,"amount":19.34602691,"open_date":"2018-01-25 14:35:00+00:00","close_date":"2018-01-25 16:35:00+00:00","open_rate":0.00258451,"close_rate":0.002641568926241846,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":120,"profit_ratio":0.01494768,"profit_abs":0.00075,"sell_reason":"roi","initial_stop_loss_abs":0.00252248176,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.00252248176,"stop_loss_ratio":-0.024,"min_rate":0.00258451,"max_rate":0.00264579,"is_open":false,"open_timestamp":1516890900000.0,"close_timestamp":1516898100000.0},{"pair":"LTC/BTC","stake_amount":0.05,"amount":3.11910295,"open_date":"2018-01-24 23:05:00+00:00","close_date":"2018-01-25 16:55:00+00:00","open_rate":0.01603025,"close_rate":0.016142855870546913,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":1070,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.015645523999999997,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.015645523999999997,"stop_loss_ratio":-0.024,"min_rate":0.015798760000000002,"max_rate":0.01617,"is_open":false,"open_timestamp":1516835100000.0,"close_timestamp":1516899300000.0},{"pair":"TRX/BTC","stake_amount":0.05,"amount":553.70985604,"open_date":"2018-01-26 19:30:00+00:00","close_date":"2018-01-26 23:30:00+00:00","open_rate":9.03e-05,"close_rate":9.093432012042147e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":240,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":8.813279999999999e-05,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":8.813279999999999e-05,"stop_loss_ratio":-0.024,"min_rate":8.961e-05,"max_rate":9.1e-05,"is_open":false,"open_timestamp":1516995000000.0,"close_timestamp":1517009400000.0},{"pair":"ETC/BTC","stake_amount":0.05,"amount":19.22929005,"open_date":"2018-01-26 21:15:00+00:00","close_date":"2018-01-28 03:50:00+00:00","open_rate":0.0026002,"close_rate":0.0026184653286502758,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":1835,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.0025377952,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.0025377952,"stop_loss_ratio":-0.024,"min_rate":0.00254702,"max_rate":0.00262797,"is_open":false,"open_timestamp":1517001300000.0,"close_timestamp":1517111400000.0},{"pair":"LTC/BTC","stake_amount":0.05,"amount":3.15677093,"open_date":"2018-01-27 22:05:00+00:00","close_date":"2018-01-28 10:45:00+00:00","open_rate":0.01583897,"close_rate":0.015950232207727046,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":760,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.01545883472,"initial_stop_loss_ratio":-0.024,"stop_loss_abs":0.01545883472,"stop_loss_ratio":-0.024,"min_rate":0.015700000000000002,"max_rate":0.01596521,"is_open":false,"open_timestamp":1517090700000.0,"close_timestamp":1517136300000.0}],"locks":[],"best_pair":{"key":"ETC/BTC","trades":5,"profit_mean":0.012572794000000002,"profit_mean_pct":1.2572794000000003,"profit_sum":0.06286397,"profit_sum_pct":6.29,"profit_total_abs":0.0031542000000000002,"profit_total":3.1542000000000002e-06,"profit_total_pct":0.0,"duration_avg":"7:49:00","wins":2,"draws":2,"losses":1},"worst_pair":{"key":"LTC/BTC","trades":8,"profit_mean":-0.0077020425,"profit_mean_pct":-0.77020425,"profit_sum":-0.06161634,"profit_sum_pct":-6.16,"profit_total_abs":-0.0030916,"profit_total":-3.0915999999999998e-06,"profit_total_pct":-0.0,"duration_avg":"9:50:00","wins":0,"draws":6,"losses":2},"results_per_pair":[{"key":"ETC/BTC","trades":5,"profit_mean":0.012572794000000002,"profit_mean_pct":1.2572794000000003,"profit_sum":0.06286397,"profit_sum_pct":6.29,"profit_total_abs":0.0031542000000000002,"profit_total":3.1542000000000002e-06,"profit_total_pct":0.0,"duration_avg":"7:49:00","wins":2,"draws":2,"losses":1},{"key":"ETH/BTC","trades":3,"profit_mean":0.00498256,"profit_mean_pct":0.498256,"profit_sum":0.01494768,"profit_sum_pct":1.49,"profit_total_abs":0.00075,"profit_total":7.5e-07,"profit_total_pct":0.0,"duration_avg":"2:02:00","wins":1,"draws":2,"losses":0},{"key":"ADA/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"XLM/BTC","trades":1,"profit_mean":-0.03080817,"profit_mean_pct":-3.080817,"profit_sum":-0.03080817,"profit_sum_pct":-3.08,"profit_total_abs":-0.0015458,"profit_total":-1.5457999999999999e-06,"profit_total_pct":-0.0,"duration_avg":"3:55:00","wins":0,"draws":0,"losses":1},{"key":"TRX/BTC","trades":5,"profit_mean":-0.009333732,"profit_mean_pct":-0.9333732000000001,"profit_sum":-0.04666866,"profit_sum_pct":-4.67,"profit_total_abs":-0.0023416,"profit_total":-2.3416e-06,"profit_total_pct":-0.0,"duration_avg":"1:45:00","wins":1,"draws":2,"losses":2},{"key":"LTC/BTC","trades":8,"profit_mean":-0.0077020425,"profit_mean_pct":-0.77020425,"profit_sum":-0.06161634,"profit_sum_pct":-6.16,"profit_total_abs":-0.0030916,"profit_total":-3.0915999999999998e-06,"profit_total_pct":-0.0,"duration_avg":"9:50:00","wins":0,"draws":6,"losses":2},{"key":"TOTAL","trades":22,"profit_mean":-0.0027855236363636365,"profit_mean_pct":-0.27855236363636365,"profit_sum":-0.06128152,"profit_sum_pct":-6.13,"profit_total_abs":-0.0030748,"profit_total":-3.0747999999999998e-06,"profit_total_pct":-0.0,"duration_avg":"6:12:00","wins":4,"draws":12,"losses":6}],"sell_reason_summary":[{"sell_reason":"roi","trades":16,"wins":4,"draws":12,"losses":0,"profit_mean":0.00772296875,"profit_mean_pct":0.77,"profit_sum":0.1235675,"profit_sum_pct":12.36,"profit_total_abs":0.006200000000000001,"profit_total":0.041189166666666666,"profit_total_pct":4.12},{"sell_reason":"stop_loss","trades":6,"wins":0,"draws":0,"losses":6,"profit_mean":-0.03080817,"profit_mean_pct":-3.08,"profit_sum":-0.18484902,"profit_sum_pct":-18.48,"profit_total_abs":-0.0092748,"profit_total":-0.06161634,"profit_total_pct":-6.16}],"left_open_trades":[{"key":"TOTAL","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0}],"total_trades":22,"total_volume":1.1000000000000003,"avg_stake_amount":0.05000000000000002,"profit_mean":-0.0027855236363636365,"profit_median":0.0,"profit_total":-3.0747999999999998e-06,"profit_total_abs":-0.0030748,"backtest_start":"2018-01-10 07:25:00","backtest_start_ts":1515569100000,"backtest_end":"2018-01-30 04:45:00","backtest_end_ts":1517287500000,"backtest_days":19,"backtest_run_start_ts":1620793107,"backtest_run_end_ts":1620793108,"trades_per_day":1.16,"market_change":0,"pairlist":["ETH/BTC","LTC/BTC","ETC/BTC","XLM/BTC","TRX/BTC","ADA/BTC"],"stake_amount":0.05,"stake_currency":"BTC","stake_currency_decimals":8,"starting_balance":1000,"dry_run_wallet":1000,"final_balance":999.9969252,"max_open_trades":3,"max_open_trades_setting":3,"timeframe":"5m","timerange":"","enable_protections":false,"strategy_name":"SampleStrategy","stoploss":-0.1,"trailing_stop":false,"trailing_stop_positive":null,"trailing_stop_positive_offset":0.0,"trailing_only_offset_is_reached":false,"use_custom_stoploss":false,"minimal_roi":{"60":0.01,"30":0.02,"0":0.04},"use_exit_signal":true,"exit_profit_only":false,"exit_profit_offset":0.0,"ignore_roi_if_entry_signal":false,"backtest_best_day":0.07872446,"backtest_worst_day":-0.09242451,"backtest_best_day_abs":0.00395,"backtest_worst_day_abs":-0.0046374,"winning_days":4,"draw_days":10,"losing_days":4,"wins":4,"losses":6,"draws":12,"holding_avg":"6:12:00","winner_holding_avg":"1:29:00","loser_holding_avg":"4:42:00","max_drawdown":0.18484901999999998,"max_drawdown_abs":0.0092748,"drawdown_start":"2018-01-14 23:15:00","drawdown_start_ts":1515971700000.0,"drawdown_end":"2018-01-23 09:40:00","drawdown_end_ts":1516700400000.0,"max_drawdown_low":-0.0038247999999999997,"max_drawdown_high":0.00545,"csum_min":999.9961752,"csum_max":1000.00545},"results_explanation":" 22 trades. 4/12/6 Wins/Draws/Losses. Avg profit -0.28%. Median profit 0.00%. Total profit -0.00307480 BTC ( -0.00\u03A3%). Avg duration 6:12:00 min.","total_profit":-3.0747999999999998e-06,"current_epoch":3,"is_initial_point":true,"is_best":true} +{"loss":-4.9544427978437175,"params_dict":{"mfi-value":"23","fastd-value":"40","adx-value":"50","rsi-value":"27","mfi-enabled":false,"fastd-enabled":true,"adx-enabled":true,"rsi-enabled":true,"trigger":"bb_lower","sell-mfi-value":"87","sell-fastd-value":"60","sell-adx-value":"81","sell-rsi-value":"69","sell-mfi-enabled":true,"sell-fastd-enabled":true,"sell-adx-enabled":false,"sell-rsi-enabled":false,"sell-trigger":"sell-sar_reversal","roi_t1":"105","roi_t2":"43","roi_t3":"12","roi_p1":0.03,"roi_p2":0.036,"roi_p3":0.103,"stoploss":-0.081},"params_details":{"buy":{"mfi-value":"23","fastd-value":"40","adx-value":"50","rsi-value":"27","mfi-enabled":false,"fastd-enabled":true,"adx-enabled":true,"rsi-enabled":true,"trigger":"bb_lower"},"sell":{"sell-mfi-value":"87","sell-fastd-value":"60","sell-adx-value":"81","sell-rsi-value":"69","sell-mfi-enabled":true,"sell-fastd-enabled":true,"sell-adx-enabled":false,"sell-rsi-enabled":false,"sell-trigger":"sell-sar_reversal"},"roi":"{0: 0.16899999999999998, 12: 0.066, 55: 0.03, 160: 0}","stoploss":{"stoploss":-0.081}},"params_not_optimized":{"buy":{},"sell":{}},"results_metrics":{"trades":[{"pair":"XLM/BTC","stake_amount":0.05,"amount":1086.95652174,"open_date":"2018-01-13 13:30:00+00:00","close_date":"2018-01-13 16:30:00+00:00","open_rate":4.6e-05,"close_rate":4.632313095835424e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":180,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":4.2274e-05,"initial_stop_loss_ratio":-0.081,"stop_loss_abs":4.2274e-05,"stop_loss_ratio":-0.081,"min_rate":4.4980000000000006e-05,"max_rate":4.673e-05,"is_open":false,"open_timestamp":1515850200000.0,"close_timestamp":1515861000000.0},{"pair":"ADA/BTC","stake_amount":0.05,"amount":851.35365231,"open_date":"2018-01-15 14:50:00+00:00","close_date":"2018-01-15 16:15:00+00:00","open_rate":5.873000000000001e-05,"close_rate":6.0910642247867544e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":85,"profit_ratio":0.02989537,"profit_abs":0.0015,"sell_reason":"roi","initial_stop_loss_abs":5.397287000000001e-05,"initial_stop_loss_ratio":-0.081,"stop_loss_abs":5.397287000000001e-05,"stop_loss_ratio":-0.081,"min_rate":5.873000000000001e-05,"max_rate":6.120000000000001e-05,"is_open":false,"open_timestamp":1516027800000.0,"close_timestamp":1516032900000.0},{"pair":"ADA/BTC","stake_amount":0.05,"amount":896.86098655,"open_date":"2018-01-16 00:35:00+00:00","close_date":"2018-01-16 03:15:00+00:00","open_rate":5.575000000000001e-05,"close_rate":5.6960000000000004e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":160,"profit_ratio":0.01457705,"profit_abs":0.0007314,"sell_reason":"roi","initial_stop_loss_abs":5.123425000000001e-05,"initial_stop_loss_ratio":-0.081,"stop_loss_abs":5.123425000000001e-05,"stop_loss_ratio":-0.081,"min_rate":5.575000000000001e-05,"max_rate":5.730000000000001e-05,"is_open":false,"open_timestamp":1516062900000.0,"close_timestamp":1516072500000.0},{"pair":"TRX/BTC","stake_amount":0.05,"amount":747.160789,"open_date":"2018-01-16 22:30:00+00:00","close_date":"2018-01-16 22:45:00+00:00","open_rate":6.692e-05,"close_rate":7.182231811339689e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":15,"profit_ratio":0.06576981,"profit_abs":0.0033,"sell_reason":"roi","initial_stop_loss_abs":6.149948000000001e-05,"initial_stop_loss_ratio":-0.081,"stop_loss_abs":6.149948000000001e-05,"stop_loss_ratio":-0.081,"min_rate":6.692e-05,"max_rate":7.566e-05,"is_open":false,"open_timestamp":1516141800000.0,"close_timestamp":1516142700000.0},{"pair":"TRX/BTC","stake_amount":0.05,"amount":720.5649229,"open_date":"2018-01-17 15:15:00+00:00","close_date":"2018-01-17 16:40:00+00:00","open_rate":6.939000000000001e-05,"close_rate":7.19664475664827e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":85,"profit_ratio":0.02989537,"profit_abs":0.0015,"sell_reason":"roi","initial_stop_loss_abs":6.376941000000001e-05,"initial_stop_loss_ratio":-0.081,"stop_loss_abs":6.376941000000001e-05,"stop_loss_ratio":-0.081,"min_rate":6.758e-05,"max_rate":7.244e-05,"is_open":false,"open_timestamp":1516202100000.0,"close_timestamp":1516207200000.0},{"pair":"XLM/BTC","stake_amount":0.05,"amount":1144.42664225,"open_date":"2018-01-18 22:20:00+00:00","close_date":"2018-01-19 00:35:00+00:00","open_rate":4.3690000000000004e-05,"close_rate":4.531220772704466e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":135,"profit_ratio":0.02989537,"profit_abs":0.0015,"sell_reason":"roi","initial_stop_loss_abs":4.015111e-05,"initial_stop_loss_ratio":-0.081,"stop_loss_abs":4.015111e-05,"stop_loss_ratio":-0.081,"min_rate":4.3690000000000004e-05,"max_rate":4.779e-05,"is_open":false,"open_timestamp":1516314000000.0,"close_timestamp":1516322100000.0},{"pair":"ADA/BTC","stake_amount":0.05,"amount":876.57784011,"open_date":"2018-01-18 22:25:00+00:00","close_date":"2018-01-19 01:05:00+00:00","open_rate":5.704e-05,"close_rate":5.792e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":160,"profit_ratio":0.00834457,"profit_abs":0.00041869,"sell_reason":"roi","initial_stop_loss_abs":5.2419760000000006e-05,"initial_stop_loss_ratio":-0.081,"stop_loss_abs":5.2419760000000006e-05,"stop_loss_ratio":-0.081,"min_rate":5.704e-05,"max_rate":5.8670000000000006e-05,"is_open":false,"open_timestamp":1516314300000.0,"close_timestamp":1516323900000.0},{"pair":"TRX/BTC","stake_amount":0.05,"amount":525.59655209,"open_date":"2018-01-20 05:05:00+00:00","close_date":"2018-01-20 06:25:00+00:00","open_rate":9.513e-05,"close_rate":9.86621726041144e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":80,"profit_ratio":0.02989537,"profit_abs":0.0015,"sell_reason":"roi","initial_stop_loss_abs":8.742447000000001e-05,"initial_stop_loss_ratio":-0.081,"stop_loss_abs":8.742447000000001e-05,"stop_loss_ratio":-0.081,"min_rate":9.513e-05,"max_rate":9.95e-05,"is_open":false,"open_timestamp":1516424700000.0,"close_timestamp":1516429500000.0},{"pair":"ADA/BTC","stake_amount":0.05,"amount":920.64076597,"open_date":"2018-01-26 07:40:00+00:00","close_date":"2018-01-26 10:20:00+00:00","open_rate":5.431000000000001e-05,"close_rate":5.474000000000001e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":160,"profit_ratio":0.0008867,"profit_abs":4.449e-05,"sell_reason":"roi","initial_stop_loss_abs":4.991089000000001e-05,"initial_stop_loss_ratio":-0.081,"stop_loss_abs":4.991089000000001e-05,"stop_loss_ratio":-0.081,"min_rate":5.3670000000000006e-05,"max_rate":5.5e-05,"is_open":false,"open_timestamp":1516952400000.0,"close_timestamp":1516962000000.0},{"pair":"XLM/BTC","stake_amount":0.05,"amount":944.28706327,"open_date":"2018-01-28 04:35:00+00:00","close_date":"2018-01-30 04:45:00+00:00","open_rate":5.2950000000000006e-05,"close_rate":4.995000000000001e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":2890,"profit_ratio":-0.06323759,"profit_abs":-0.00317295,"sell_reason":"force_sell","initial_stop_loss_abs":4.866105000000001e-05,"initial_stop_loss_ratio":-0.081,"stop_loss_abs":4.866105000000001e-05,"stop_loss_ratio":-0.081,"min_rate":4.980000000000001e-05,"max_rate":5.3280000000000005e-05,"is_open":true,"open_timestamp":1517114100000.0,"close_timestamp":1517287500000.0}],"locks":[],"best_pair":{"key":"TRX/BTC","trades":3,"profit_mean":0.04185351666666667,"profit_mean_pct":4.185351666666667,"profit_sum":0.12556055,"profit_sum_pct":12.56,"profit_total_abs":0.0063,"profit_total":6.3e-06,"profit_total_pct":0.0,"duration_avg":"1:00:00","wins":3,"draws":0,"losses":0},"worst_pair":{"key":"XLM/BTC","trades":3,"profit_mean":-0.01111407333333333,"profit_mean_pct":-1.111407333333333,"profit_sum":-0.03334221999999999,"profit_sum_pct":-3.33,"profit_total_abs":-0.0016729499999999999,"profit_total":-1.6729499999999998e-06,"profit_total_pct":-0.0,"duration_avg":"17:48:00","wins":1,"draws":1,"losses":1},"results_per_pair":[{"key":"TRX/BTC","trades":3,"profit_mean":0.04185351666666667,"profit_mean_pct":4.185351666666667,"profit_sum":0.12556055,"profit_sum_pct":12.56,"profit_total_abs":0.0063,"profit_total":6.3e-06,"profit_total_pct":0.0,"duration_avg":"1:00:00","wins":3,"draws":0,"losses":0},{"key":"ADA/BTC","trades":4,"profit_mean":0.0134259225,"profit_mean_pct":1.34259225,"profit_sum":0.05370369,"profit_sum_pct":5.37,"profit_total_abs":0.00269458,"profit_total":2.69458e-06,"profit_total_pct":0.0,"duration_avg":"2:21:00","wins":4,"draws":0,"losses":0},{"key":"ETH/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"LTC/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"ETC/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"XLM/BTC","trades":3,"profit_mean":-0.01111407333333333,"profit_mean_pct":-1.111407333333333,"profit_sum":-0.03334221999999999,"profit_sum_pct":-3.33,"profit_total_abs":-0.0016729499999999999,"profit_total":-1.6729499999999998e-06,"profit_total_pct":-0.0,"duration_avg":"17:48:00","wins":1,"draws":1,"losses":1},{"key":"TOTAL","trades":10,"profit_mean":0.014592201999999999,"profit_mean_pct":1.4592201999999999,"profit_sum":0.14592201999999999,"profit_sum_pct":14.59,"profit_total_abs":0.00732163,"profit_total":7.32163e-06,"profit_total_pct":0.0,"duration_avg":"6:35:00","wins":8,"draws":1,"losses":1}],"sell_reason_summary":[{"sell_reason":"roi","trades":9,"wins":8,"draws":1,"losses":0,"profit_mean":0.023239956666666665,"profit_mean_pct":2.32,"profit_sum":0.20915961,"profit_sum_pct":20.92,"profit_total_abs":0.01049458,"profit_total":0.06971987,"profit_total_pct":6.97},{"sell_reason":"force_sell","trades":1,"wins":0,"draws":0,"losses":1,"profit_mean":-0.06323759,"profit_mean_pct":-6.32,"profit_sum":-0.06323759,"profit_sum_pct":-6.32,"profit_total_abs":-0.00317295,"profit_total":-0.021079196666666664,"profit_total_pct":-2.11}],"left_open_trades":[{"key":"XLM/BTC","trades":1,"profit_mean":-0.06323759,"profit_mean_pct":-6.323759,"profit_sum":-0.06323759,"profit_sum_pct":-6.32,"profit_total_abs":-0.00317295,"profit_total":-3.17295e-06,"profit_total_pct":-0.0,"duration_avg":"2 days, 0:10:00","wins":0,"draws":0,"losses":1},{"key":"TOTAL","trades":1,"profit_mean":-0.06323759,"profit_mean_pct":-6.323759,"profit_sum":-0.06323759,"profit_sum_pct":-6.32,"profit_total_abs":-0.00317295,"profit_total":-3.17295e-06,"profit_total_pct":-0.0,"duration_avg":"2 days, 0:10:00","wins":0,"draws":0,"losses":1}],"total_trades":10,"total_volume":0.5,"avg_stake_amount":0.05,"profit_mean":0.014592201999999999,"profit_median":0.02223621,"profit_total":7.32163e-06,"profit_total_abs":0.00732163,"backtest_start":"2018-01-10 07:25:00","backtest_start_ts":1515569100000,"backtest_end":"2018-01-30 04:45:00","backtest_end_ts":1517287500000,"backtest_days":19,"backtest_run_start_ts":1620793107,"backtest_run_end_ts":1620793108,"trades_per_day":0.53,"market_change":0,"pairlist":["ETH/BTC","LTC/BTC","ETC/BTC","XLM/BTC","TRX/BTC","ADA/BTC"],"stake_amount":0.05,"stake_currency":"BTC","stake_currency_decimals":8,"starting_balance":1000,"dry_run_wallet":1000,"final_balance":1000.00732163,"max_open_trades":3,"max_open_trades_setting":3,"timeframe":"5m","timerange":"","enable_protections":false,"strategy_name":"SampleStrategy","stoploss":-0.1,"trailing_stop":false,"trailing_stop_positive":null,"trailing_stop_positive_offset":0.0,"trailing_only_offset_is_reached":false,"use_custom_stoploss":false,"minimal_roi":{"60":0.01,"30":0.02,"0":0.04},"use_exit_signal":true,"exit_profit_only":false,"exit_profit_offset":0.0,"ignore_roi_if_entry_signal":false,"backtest_best_day":0.08034685999999999,"backtest_worst_day":-0.06323759,"backtest_best_day_abs":0.0040314,"backtest_worst_day_abs":-0.00317295,"winning_days":6,"draw_days":11,"losing_days":1,"wins":8,"losses":1,"draws":1,"holding_avg":"6:35:00","winner_holding_avg":"1:50:00","loser_holding_avg":"2 days, 0:10:00","max_drawdown":0.06323759000000001,"max_drawdown_abs":0.00317295,"drawdown_start":"2018-01-26 10:20:00","drawdown_start_ts":1516962000000.0,"drawdown_end":"2018-01-30 04:45:00","drawdown_end_ts":1517287500000.0,"max_drawdown_low":0.007321629999999998,"max_drawdown_high":0.010494579999999998,"csum_min":1000.0,"csum_max":1000.01049458},"results_explanation":" 10 trades. 8/1/1 Wins/Draws/Losses. Avg profit 1.46%. Median profit 2.22%. Total profit 0.00732163 BTC ( 0.00\u03A3%). Avg duration 6:35:00 min.","total_profit":7.32163e-06,"current_epoch":4,"is_initial_point":true,"is_best":true} +{"loss":0.16709185414267655,"params_dict":{"mfi-value":"10","fastd-value":"45","adx-value":"28","rsi-value":"37","mfi-enabled":false,"fastd-enabled":false,"adx-enabled":true,"rsi-enabled":true,"trigger":"macd_cross_signal","sell-mfi-value":"85","sell-fastd-value":"56","sell-adx-value":"98","sell-rsi-value":"89","sell-mfi-enabled":true,"sell-fastd-enabled":false,"sell-adx-enabled":true,"sell-rsi-enabled":false,"sell-trigger":"sell-sar_reversal","roi_t1":"85","roi_t2":"11","roi_t3":"24","roi_p1":0.04,"roi_p2":0.043,"roi_p3":0.053,"stoploss":-0.057},"params_details":{"buy":{"mfi-value":"10","fastd-value":"45","adx-value":"28","rsi-value":"37","mfi-enabled":false,"fastd-enabled":false,"adx-enabled":true,"rsi-enabled":true,"trigger":"macd_cross_signal"},"sell":{"sell-mfi-value":"85","sell-fastd-value":"56","sell-adx-value":"98","sell-rsi-value":"89","sell-mfi-enabled":true,"sell-fastd-enabled":false,"sell-adx-enabled":true,"sell-rsi-enabled":false,"sell-trigger":"sell-sar_reversal"},"roi":"{0: 0.13599999999999998, 24: 0.08299999999999999, 35: 0.04, 120: 0}","stoploss":{"stoploss":-0.057}},"params_not_optimized":{"buy":{},"sell":{}},"results_metrics":{"trades":[{"pair":"ETH/BTC","stake_amount":0.05,"amount":0.56173464,"open_date":"2018-01-10 19:15:00+00:00","close_date":"2018-01-10 21:15:00+00:00","open_rate":0.08901,"close_rate":0.09112999000000001,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":120,"profit_ratio":0.01667571,"profit_abs":0.0008367,"sell_reason":"roi","initial_stop_loss_abs":0.08393643,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":0.08393643,"stop_loss_ratio":-0.057,"min_rate":0.08894498,"max_rate":0.09116998,"is_open":false,"open_timestamp":1515611700000.0,"close_timestamp":1515618900000.0},{"pair":"ADA/BTC","stake_amount":0.05,"amount":794.65988557,"open_date":"2018-01-13 11:30:00+00:00","close_date":"2018-01-13 15:10:00+00:00","open_rate":6.292e-05,"close_rate":5.9333559999999994e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":220,"profit_ratio":-0.06357798,"profit_abs":-0.00319003,"sell_reason":"stop_loss","initial_stop_loss_abs":5.9333559999999994e-05,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":5.9333559999999994e-05,"stop_loss_ratio":-0.057,"min_rate":5.9900000000000006e-05,"max_rate":6.353e-05,"is_open":false,"open_timestamp":1515843000000.0,"close_timestamp":1515856200000.0},{"pair":"XLM/BTC","stake_amount":0.05,"amount":1086.95652174,"open_date":"2018-01-13 14:35:00+00:00","close_date":"2018-01-13 21:40:00+00:00","open_rate":4.6e-05,"close_rate":4.632313095835424e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":425,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":4.3378e-05,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":4.3378e-05,"stop_loss_ratio":-0.057,"min_rate":4.4980000000000006e-05,"max_rate":4.6540000000000005e-05,"is_open":false,"open_timestamp":1515854100000.0,"close_timestamp":1515879600000.0},{"pair":"ETH/BTC","stake_amount":0.05,"amount":0.53757603,"open_date":"2018-01-15 13:15:00+00:00","close_date":"2018-01-15 15:15:00+00:00","open_rate":0.0930101,"close_rate":0.09366345745107878,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":120,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.0877085243,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":0.0877085243,"stop_loss_ratio":-0.057,"min_rate":0.09188489999999999,"max_rate":0.09380000000000001,"is_open":false,"open_timestamp":1516022100000.0,"close_timestamp":1516029300000.0},{"pair":"ETC/BTC","stake_amount":0.05,"amount":17.07469496,"open_date":"2018-01-15 14:35:00+00:00","close_date":"2018-01-15 16:35:00+00:00","open_rate":0.00292831,"close_rate":0.00297503,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":120,"profit_ratio":0.00886772,"profit_abs":0.00044494,"sell_reason":"roi","initial_stop_loss_abs":0.0027613963299999997,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":0.0027613963299999997,"stop_loss_ratio":-0.057,"min_rate":0.00292831,"max_rate":0.00301259,"is_open":false,"open_timestamp":1516026900000.0,"close_timestamp":1516034100000.0},{"pair":"TRX/BTC","stake_amount":0.05,"amount":702.44450688,"open_date":"2018-01-17 04:25:00+00:00","close_date":"2018-01-17 05:00:00+00:00","open_rate":7.118e-05,"close_rate":7.453721023582538e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":35,"profit_ratio":0.03986049,"profit_abs":0.002,"sell_reason":"roi","initial_stop_loss_abs":6.712274e-05,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":6.712274e-05,"stop_loss_ratio":-0.057,"min_rate":7.118e-05,"max_rate":7.658000000000002e-05,"is_open":false,"open_timestamp":1516163100000.0,"close_timestamp":1516165200000.0},{"pair":"ETC/BTC","stake_amount":0.05,"amount":18.86756854,"open_date":"2018-01-20 06:05:00+00:00","close_date":"2018-01-20 08:05:00+00:00","open_rate":0.00265005,"close_rate":0.00266995,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":120,"profit_ratio":0.00048133,"profit_abs":2.415e-05,"sell_reason":"roi","initial_stop_loss_abs":0.00249899715,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":0.00249899715,"stop_loss_ratio":-0.057,"min_rate":0.00265005,"max_rate":0.00271,"is_open":false,"open_timestamp":1516428300000.0,"close_timestamp":1516435500000.0},{"pair":"ADA/BTC","stake_amount":0.05,"amount":966.18357488,"open_date":"2018-01-22 03:25:00+00:00","close_date":"2018-01-22 07:05:00+00:00","open_rate":5.1750000000000004e-05,"close_rate":5.211352232814853e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":220,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":4.8800250000000004e-05,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":4.8800250000000004e-05,"stop_loss_ratio":-0.057,"min_rate":5.1750000000000004e-05,"max_rate":5.2170000000000004e-05,"is_open":false,"open_timestamp":1516591500000.0,"close_timestamp":1516604700000.0},{"pair":"ETC/BTC","stake_amount":0.05,"amount":18.95303438,"open_date":"2018-01-23 13:10:00+00:00","close_date":"2018-01-23 16:00:00+00:00","open_rate":0.0026381,"close_rate":0.002656631560461616,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":170,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":0.0024877283,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":0.0024877283,"stop_loss_ratio":-0.057,"min_rate":0.0026100000000000003,"max_rate":0.00266,"is_open":false,"open_timestamp":1516713000000.0,"close_timestamp":1516723200000.0},{"pair":"ADA/BTC","stake_amount":0.05,"amount":912.40875912,"open_date":"2018-01-26 06:30:00+00:00","close_date":"2018-01-26 10:45:00+00:00","open_rate":5.480000000000001e-05,"close_rate":5.518494731560462e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":255,"profit_ratio":-0.0,"profit_abs":-0.0,"sell_reason":"roi","initial_stop_loss_abs":5.1676400000000006e-05,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":5.1676400000000006e-05,"stop_loss_ratio":-0.057,"min_rate":5.3670000000000006e-05,"max_rate":5.523e-05,"is_open":false,"open_timestamp":1516948200000.0,"close_timestamp":1516963500000.0},{"pair":"ADA/BTC","stake_amount":0.05,"amount":909.58704748,"open_date":"2018-01-27 02:10:00+00:00","close_date":"2018-01-27 05:40:00+00:00","open_rate":5.4970000000000004e-05,"close_rate":5.535614149523332e-05,"fee_open":0.0035,"fee_close":0.0035,"trade_duration":210,"profit_ratio":0.0,"profit_abs":0.0,"sell_reason":"roi","initial_stop_loss_abs":5.183671e-05,"initial_stop_loss_ratio":-0.057,"stop_loss_abs":5.183671e-05,"stop_loss_ratio":-0.057,"min_rate":5.472000000000001e-05,"max_rate":5.556e-05,"is_open":false,"open_timestamp":1517019000000.0,"close_timestamp":1517031600000.0}],"locks":[],"best_pair":{"key":"TRX/BTC","trades":1,"profit_mean":0.03986049,"profit_mean_pct":3.986049,"profit_sum":0.03986049,"profit_sum_pct":3.99,"profit_total_abs":0.002,"profit_total":2e-06,"profit_total_pct":0.0,"duration_avg":"0:35:00","wins":1,"draws":0,"losses":0},"worst_pair":{"key":"ADA/BTC","trades":4,"profit_mean":-0.015894495,"profit_mean_pct":-1.5894495000000002,"profit_sum":-0.06357798,"profit_sum_pct":-6.36,"profit_total_abs":-0.00319003,"profit_total":-3.19003e-06,"profit_total_pct":-0.0,"duration_avg":"3:46:00","wins":0,"draws":3,"losses":1},"results_per_pair":[{"key":"TRX/BTC","trades":1,"profit_mean":0.03986049,"profit_mean_pct":3.986049,"profit_sum":0.03986049,"profit_sum_pct":3.99,"profit_total_abs":0.002,"profit_total":2e-06,"profit_total_pct":0.0,"duration_avg":"0:35:00","wins":1,"draws":0,"losses":0},{"key":"ETH/BTC","trades":2,"profit_mean":0.008337855,"profit_mean_pct":0.8337855,"profit_sum":0.01667571,"profit_sum_pct":1.67,"profit_total_abs":0.0008367,"profit_total":8.367e-07,"profit_total_pct":0.0,"duration_avg":"2:00:00","wins":1,"draws":1,"losses":0},{"key":"ETC/BTC","trades":3,"profit_mean":0.0031163500000000004,"profit_mean_pct":0.31163500000000005,"profit_sum":0.009349050000000001,"profit_sum_pct":0.93,"profit_total_abs":0.00046909,"profit_total":4.6909000000000003e-07,"profit_total_pct":0.0,"duration_avg":"2:17:00","wins":2,"draws":1,"losses":0},{"key":"LTC/BTC","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0},{"key":"XLM/BTC","trades":1,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"7:05:00","wins":0,"draws":1,"losses":0},{"key":"ADA/BTC","trades":4,"profit_mean":-0.015894495,"profit_mean_pct":-1.5894495000000002,"profit_sum":-0.06357798,"profit_sum_pct":-6.36,"profit_total_abs":-0.00319003,"profit_total":-3.19003e-06,"profit_total_pct":-0.0,"duration_avg":"3:46:00","wins":0,"draws":3,"losses":1},{"key":"TOTAL","trades":11,"profit_mean":0.00020975181818181756,"profit_mean_pct":0.020975181818181757,"profit_sum":0.002307269999999993,"profit_sum_pct":0.23,"profit_total_abs":0.00011576000000000034,"profit_total":1.1576000000000034e-07,"profit_total_pct":0.0,"duration_avg":"3:03:00","wins":4,"draws":6,"losses":1}],"sell_reason_summary":[{"sell_reason":"roi","trades":10,"wins":4,"draws":6,"losses":0,"profit_mean":0.0065885250000000005,"profit_mean_pct":0.66,"profit_sum":0.06588525,"profit_sum_pct":6.59,"profit_total_abs":0.0033057900000000003,"profit_total":0.021961750000000002,"profit_total_pct":2.2},{"sell_reason":"stop_loss","trades":1,"wins":0,"draws":0,"losses":1,"profit_mean":-0.06357798,"profit_mean_pct":-6.36,"profit_sum":-0.06357798,"profit_sum_pct":-6.36,"profit_total_abs":-0.00319003,"profit_total":-0.021192660000000002,"profit_total_pct":-2.12}],"left_open_trades":[{"key":"TOTAL","trades":0,"profit_mean":0.0,"profit_mean_pct":0.0,"profit_sum":0.0,"profit_sum_pct":0.0,"profit_total_abs":0.0,"profit_total":0.0,"profit_total_pct":0.0,"duration_avg":"0:00","wins":0,"draws":0,"losses":0}],"total_trades":11,"total_volume":0.55,"avg_stake_amount":0.05,"profit_mean":0.00020975181818181756,"profit_median":0.0,"profit_total":1.1576000000000034e-07,"profit_total_abs":0.00011576000000000034,"backtest_start":"2018-01-10 07:25:00","backtest_start_ts":1515569100000,"backtest_end":"2018-01-30 04:45:00","backtest_end_ts":1517287500000,"backtest_days":19,"backtest_run_start_ts":1620793107,"backtest_run_end_ts":1620793108,"trades_per_day":0.58,"market_change":0,"pairlist":["ETH/BTC","LTC/BTC","ETC/BTC","XLM/BTC","TRX/BTC","ADA/BTC"],"stake_amount":0.05,"stake_currency":"BTC","stake_currency_decimals":8,"starting_balance":1000,"dry_run_wallet":1000,"final_balance":1000.00011576,"max_open_trades":3,"max_open_trades_setting":3,"timeframe":"5m","timerange":"","enable_protections":false,"strategy_name":"SampleStrategy","stoploss":-0.1,"trailing_stop":false,"trailing_stop_positive":null,"trailing_stop_positive_offset":0.0,"trailing_only_offset_is_reached":false,"use_custom_stoploss":false,"minimal_roi":{"60":0.01,"30":0.02,"0":0.04},"use_exit_signal":true,"exit_profit_only":false,"exit_profit_offset":0.0,"ignore_roi_if_entry_signal":false,"backtest_best_day":0.03986049,"backtest_worst_day":-0.06357798,"backtest_best_day_abs":0.002,"backtest_worst_day_abs":-0.00319003,"winning_days":4,"draw_days":13,"losing_days":1,"wins":4,"losses":1,"draws":6,"holding_avg":"3:03:00","winner_holding_avg":"1:39:00","loser_holding_avg":"3:40:00","max_drawdown":0.06357798,"max_drawdown_abs":0.00319003,"drawdown_start":"2018-01-10 21:15:00","drawdown_start_ts":1515618900000.0,"drawdown_end":"2018-01-13 15:10:00","drawdown_end_ts":1515856200000.0,"max_drawdown_low":-0.00235333,"max_drawdown_high":0.0008367,"csum_min":999.99764667,"csum_max":1000.0008367},"results_explanation":" 11 trades. 4/6/1 Wins/Draws/Losses. Avg profit 0.02%. Median profit 0.00%. Total profit 0.00011576 BTC ( 0.00\u03A3%). Avg duration 3:03:00 min.","total_profit":1.1576000000000034e-07,"current_epoch":5,"is_initial_point":true,"is_best":false} diff --git a/tests/testdata/testconfigs/recursive.json b/tests/testdata/testconfigs/recursive.json new file mode 100644 index 000000000..33ab12008 --- /dev/null +++ b/tests/testdata/testconfigs/recursive.json @@ -0,0 +1,6 @@ +{ + // This file fails as it's loading itself over and over + "add_config_files": [ + "./recursive.json" + ] +} diff --git a/tests/testdata/testconfigs/test_base_config.json b/tests/testdata/testconfigs/test_base_config.json new file mode 100644 index 000000000..d15c5890b --- /dev/null +++ b/tests/testdata/testconfigs/test_base_config.json @@ -0,0 +1,12 @@ +{ + "stake_currency": "", + "dry_run": true, + "exchange": { + "name": "", + "key": "", + "secret": "", + "pair_whitelist": [], + "ccxt_async_config": { + } + } +} diff --git a/tests/testdata/testconfigs/test_pricing2_conf.json b/tests/testdata/testconfigs/test_pricing2_conf.json new file mode 100644 index 000000000..094783a60 --- /dev/null +++ b/tests/testdata/testconfigs/test_pricing2_conf.json @@ -0,0 +1,18 @@ +{ + "entry_pricing": { + "price_side": "same", + "use_order_book": true, + "order_book_top": 1, + "price_last_balance": 0.0, + "check_depth_of_market": { + "enabled": false, + "bids_to_ask_delta": 1 + } + }, + "exit_pricing":{ + "price_side": "other", + "use_order_book": true, + "order_book_top": 1, + "price_last_balance": 0.0 + } +} diff --git a/tests/testdata/testconfigs/test_pricing_conf.json b/tests/testdata/testconfigs/test_pricing_conf.json new file mode 100644 index 000000000..59516d65e --- /dev/null +++ b/tests/testdata/testconfigs/test_pricing_conf.json @@ -0,0 +1,21 @@ +{ + "entry_pricing": { + "price_side": "same", + "use_order_book": true, + "order_book_top": 1, + "price_last_balance": 0.0, + "check_depth_of_market": { + "enabled": false, + "bids_to_ask_delta": 1 + } + }, + "exit_pricing":{ + "price_side": "same", + "use_order_book": true, + "order_book_top": 1, + "price_last_balance": 0.0 + }, + "add_config_files": [ + "./test_pricing2_conf.json" + ] +} diff --git a/tests/testdata/testconfigs/testconfig.json b/tests/testdata/testconfigs/testconfig.json new file mode 100644 index 000000000..87ed6daef --- /dev/null +++ b/tests/testdata/testconfigs/testconfig.json @@ -0,0 +1,6 @@ +{ + "add_config_files": [ + "test_base_config.json", + "test_pricing_conf.json" + ] +}