From 4f5a1e94a7b94c75999404fc06be0d48c7132666 Mon Sep 17 00:00:00 2001 From: shubhendra Date: Sun, 21 Mar 2021 17:14:30 +0530 Subject: [PATCH 01/30] Add .deepsource.toml Signed-off-by: shubhendra --- .deepsource.toml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .deepsource.toml diff --git a/.deepsource.toml b/.deepsource.toml new file mode 100644 index 000000000..7a00ca8d6 --- /dev/null +++ b/.deepsource.toml @@ -0,0 +1,16 @@ +version = 1 + +test_patterns = ["tests/**/test_*.py"] + +exclude_patterns = [ + "docs/**", + "user_data/**", + "build/helpers/**" +] + +[[analyzers]] +name = "python" +enabled = true + + [analyzers.meta] + runtime_version = "3.x.x" From 62d99a0b7406136f24d51e6d704fcc18969a3f5b Mon Sep 17 00:00:00 2001 From: shubhendra Date: Sun, 21 Mar 2021 17:14:30 +0530 Subject: [PATCH 02/30] Remove unnecessary comprehension Signed-off-by: shubhendra --- freqtrade/resolvers/strategy_resolver.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/freqtrade/resolvers/strategy_resolver.py b/freqtrade/resolvers/strategy_resolver.py index b1b66e3ae..19bd014f9 100644 --- a/freqtrade/resolvers/strategy_resolver.py +++ b/freqtrade/resolvers/strategy_resolver.py @@ -196,9 +196,9 @@ class StrategyResolver(IResolver): 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) - if any([x == 2 for x in [strategy._populate_fun_len, + if any(x == 2 for x in [strategy._populate_fun_len, strategy._buy_fun_len, - strategy._sell_fun_len]]): + strategy._sell_fun_len]): strategy.INTERFACE_VERSION = 1 return strategy From 537ad059bc3b643eb2d022ddb798ed4d84aa8c78 Mon Sep 17 00:00:00 2001 From: shubhendra Date: Sun, 21 Mar 2021 17:14:31 +0530 Subject: [PATCH 03/30] Remove unnecessary use of comprehension Signed-off-by: shubhendra --- freqtrade/persistence/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/persistence/models.py b/freqtrade/persistence/models.py index 78f45de0b..465f3d443 100644 --- a/freqtrade/persistence/models.py +++ b/freqtrade/persistence/models.py @@ -611,7 +611,7 @@ class LocalTrade(): else: # Not used during backtesting, but might be used by a strategy - sel_trades = [trade for trade in LocalTrade.trades + LocalTrade.trades_open] + sel_trades = list(LocalTrade.trades + LocalTrade.trades_open) if pair: sel_trades = [trade for trade in sel_trades if trade.pair == pair] From 6d6ad035d6cf7fcedac7697fd69c8948f2e3fd76 Mon Sep 17 00:00:00 2001 From: shubhendra Date: Sun, 21 Mar 2021 17:14:32 +0530 Subject: [PATCH 04/30] Remove length check in favour of truthiness of the object Signed-off-by: shubhendra --- freqtrade/commands/list_commands.py | 2 +- freqtrade/exchange/exchange.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/freqtrade/commands/list_commands.py b/freqtrade/commands/list_commands.py index 9e6076dfb..5f53fc824 100644 --- a/freqtrade/commands/list_commands.py +++ b/freqtrade/commands/list_commands.py @@ -177,7 +177,7 @@ def start_list_markets(args: Dict[str, Any], pairs_only: bool = False) -> None: # human-readable formats. print() - if len(pairs): + if pairs: if args.get('print_list', False): # print data as a list, with human-readable summary print(f"{summary_str}: {', '.join(pairs.keys())}.") diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 5b6e2b20d..9c868df2b 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -958,7 +958,7 @@ class Exchange: while True: t = await self._async_fetch_trades(pair, params={self._trades_pagination_arg: from_id}) - if len(t): + if t: # Skip last id since its the key for the next call trades.extend(t[:-1]) if from_id == t[-1][1] or t[-1][0] > until: @@ -990,7 +990,7 @@ class Exchange: # DEFAULT_TRADES_COLUMNS: 1 -> id while True: t = await self._async_fetch_trades(pair, since=since) - if len(t): + if t: since = t[-1][0] trades.extend(t) # Reached the end of the defined-download period From 910e15b17431a8c7be26fde1346d9ef2fb9e45d1 Mon Sep 17 00:00:00 2001 From: shubhendra Date: Sun, 21 Mar 2021 17:14:33 +0530 Subject: [PATCH 05/30] Remove methods with unnecessary super delegation. Signed-off-by: shubhendra --- freqtrade/plugins/pairlist/PerformanceFilter.py | 5 ----- freqtrade/plugins/protections/cooldown_period.py | 3 --- 2 files changed, 8 deletions(-) diff --git a/freqtrade/plugins/pairlist/PerformanceFilter.py b/freqtrade/plugins/pairlist/PerformanceFilter.py index 7d91bb77c..c1355f655 100644 --- a/freqtrade/plugins/pairlist/PerformanceFilter.py +++ b/freqtrade/plugins/pairlist/PerformanceFilter.py @@ -15,11 +15,6 @@ logger = logging.getLogger(__name__) class PerformanceFilter(IPairList): - def __init__(self, exchange, pairlistmanager, - config: Dict[str, Any], pairlistconfig: Dict[str, Any], - pairlist_pos: int) -> None: - super().__init__(exchange, pairlistmanager, config, pairlistconfig, pairlist_pos) - @property def needstickers(self) -> bool: """ diff --git a/freqtrade/plugins/protections/cooldown_period.py b/freqtrade/plugins/protections/cooldown_period.py index f74f83885..197d74c2e 100644 --- a/freqtrade/plugins/protections/cooldown_period.py +++ b/freqtrade/plugins/protections/cooldown_period.py @@ -15,9 +15,6 @@ class CooldownPeriod(IProtection): has_global_stop: bool = False has_local_stop: bool = True - def __init__(self, config: Dict[str, Any], protection_config: Dict[str, Any]) -> None: - super().__init__(config, protection_config) - def _reason(self) -> str: """ LockReason to use From 45da3a70227cc95ee7610e0bb12dabd348b0086e Mon Sep 17 00:00:00 2001 From: shubhendra Date: Sun, 21 Mar 2021 17:14:34 +0530 Subject: [PATCH 06/30] Refactor unnecessary `else` / `elif` when `if` block has a `continue` statement Signed-off-by: shubhendra --- freqtrade/configuration/directory_operations.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/freqtrade/configuration/directory_operations.py b/freqtrade/configuration/directory_operations.py index 51310f013..1ce8d1461 100644 --- a/freqtrade/configuration/directory_operations.py +++ b/freqtrade/configuration/directory_operations.py @@ -72,6 +72,5 @@ def copy_sample_files(directory: Path, overwrite: bool = False) -> None: if not overwrite: logger.warning(f"File `{targetfile}` exists already, not deploying sample file.") continue - else: - logger.warning(f"File `{targetfile}` exists already, overwriting.") + logger.warning(f"File `{targetfile}` exists already, overwriting.") shutil.copy(str(sourcedir / source), str(targetfile)) From 4d8183491218783c92bc7230d98d00dffdf9b115 Mon Sep 17 00:00:00 2001 From: shubhendra Date: Sun, 21 Mar 2021 17:14:34 +0530 Subject: [PATCH 07/30] Merge `isinstance` calls Signed-off-by: shubhendra --- freqtrade/exchange/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/freqtrade/exchange/common.py b/freqtrade/exchange/common.py index c66db860f..be0a1e483 100644 --- a/freqtrade/exchange/common.py +++ b/freqtrade/exchange/common.py @@ -140,7 +140,7 @@ def retrier(_func=None, retries=API_RETRY_COUNT): logger.warning('retrying %s() still for %s times', f.__name__, count) count -= 1 kwargs.update({'count': count}) - if isinstance(ex, DDosProtection) or isinstance(ex, RetryableOrderError): + if isinstance(ex, (DDosProtection, RetryableOrderError)): # increasing backoff backoff_delay = calculate_backoff(count + 1, retries) logger.info(f"Applying DDosProtection backoff delay: {backoff_delay}") From 39bfe5e1a79263b18c10e5b8ca51c58705885e66 Mon Sep 17 00:00:00 2001 From: Masoud Azizi Date: Fri, 26 Mar 2021 22:50:27 +0430 Subject: [PATCH 08/30] Thee to the --- docs/hyperopt.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/hyperopt.md b/docs/hyperopt.md index 69bc57d1a..96c7354b9 100644 --- a/docs/hyperopt.md +++ b/docs/hyperopt.md @@ -165,7 +165,7 @@ Depending on the space you want to optimize, only some of the below are required * fill `sell_indicator_space` - for sell signal optimization !!! Note - `populate_indicators` needs to create all indicators any of thee spaces may use, otherwise hyperopt will not work. + `populate_indicators` needs to create all indicators any of the spaces may use, otherwise hyperopt will not work. Optional in hyperopt - can also be loaded from a strategy (recommended): From fc8478111e3d4b9810cee75857c68e3768390f82 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 28 Mar 2021 20:06:30 +0200 Subject: [PATCH 09/30] Improve strategy template --- freqtrade/templates/base_strategy.py.j2 | 5 +++-- freqtrade/templates/sample_strategy.py | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/freqtrade/templates/base_strategy.py.j2 b/freqtrade/templates/base_strategy.py.j2 index dd6b773e1..db73d4da3 100644 --- a/freqtrade/templates/base_strategy.py.j2 +++ b/freqtrade/templates/base_strategy.py.j2 @@ -26,8 +26,9 @@ class {{ strategy }}(IStrategy): You must keep: - the lib in the section "Do not remove these libs" - - the prototype for the methods: minimal_roi, stoploss, populate_indicators, populate_buy_trend, - populate_sell_trend, hyperopt_space, buy_strategy_generator + - the methods: populate_indicators, populate_buy_trend, populate_sell_trend + You should keep: + - timeframe, minimal_roi, stoploss, trailing_* """ # Strategy interface version - allow new iterations of the strategy interface. # Check the documentation or the Sample strategy to get the latest version. diff --git a/freqtrade/templates/sample_strategy.py b/freqtrade/templates/sample_strategy.py index db1ba48b8..5dfa42bcc 100644 --- a/freqtrade/templates/sample_strategy.py +++ b/freqtrade/templates/sample_strategy.py @@ -5,7 +5,7 @@ import numpy as np # noqa import pandas as pd # noqa from pandas import DataFrame -from freqtrade.strategy.interface import IStrategy +from freqtrade.strategy import IStrategy # -------------------------------- # Add your lib to import here @@ -27,8 +27,9 @@ class SampleStrategy(IStrategy): You must keep: - the lib in the section "Do not remove these libs" - - the prototype for the methods: minimal_roi, stoploss, populate_indicators, populate_buy_trend, - populate_sell_trend, hyperopt_space, buy_strategy_generator + - the methods: populate_indicators, populate_buy_trend, populate_sell_trend + You should keep: + - timeframe, minimal_roi, stoploss, trailing_* """ # Strategy interface version - allow new iterations of the strategy interface. # Check the documentation or the Sample strategy to get the latest version. From f6211bc00ebe43b4f8ae981658dc9f11a6c711aa Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 28 Mar 2021 20:19:39 +0200 Subject: [PATCH 10/30] new-config should include API config --- freqtrade/commands/build_config_commands.py | 30 +++++++++++++++++++++ freqtrade/templates/base_config.json.j2 | 10 +++---- tests/commands/test_build_config.py | 4 +++ 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/freqtrade/commands/build_config_commands.py b/freqtrade/commands/build_config_commands.py index 3c34ff162..0dee480b3 100644 --- a/freqtrade/commands/build_config_commands.py +++ b/freqtrade/commands/build_config_commands.py @@ -1,4 +1,5 @@ import logging +import secrets from pathlib import Path from typing import Any, Dict, List @@ -138,6 +139,32 @@ def ask_user_config() -> Dict[str, Any]: "message": "Insert Telegram chat id", "when": lambda x: x['telegram'] }, + { + "type": "confirm", + "name": "api_server", + "message": "Do you want to enable the Rest API (includes FreqUI)?", + "default": False, + }, + { + "type": "text", + "name": "api_server_listen_addr", + "message": "Insert Api server Listen Address (best left untouched default!)", + "default": "127.0.0.1", + "when": lambda x: x['api_server'] + }, + { + "type": "text", + "name": "api_server_username", + "message": "Insert api-server username", + "default": "freqtrader", + "when": lambda x: x['api_server'] + }, + { + "type": "text", + "name": "api_server_password", + "message": "Insert api-server password", + "when": lambda x: x['api_server'] + }, ] answers = prompt(questions) @@ -145,6 +172,9 @@ def ask_user_config() -> Dict[str, Any]: # Interrupted questionary sessions return an empty dict. raise OperationalException("User interrupted interactive questions.") + # Force JWT token to be a random string + answers['api_server_jwt_key'] = secrets.token_hex() + return answers diff --git a/freqtrade/templates/base_config.json.j2 b/freqtrade/templates/base_config.json.j2 index 226bf1a81..42f088f9f 100644 --- a/freqtrade/templates/base_config.json.j2 +++ b/freqtrade/templates/base_config.json.j2 @@ -54,15 +54,15 @@ "chat_id": "{{ telegram_chat_id }}" }, "api_server": { - "enabled": false, - "listen_ip_address": "127.0.0.1", + "enabled": {{ api_server | lower }}, + "listen_ip_address": "{{ api_server_listen_addr | default("127.0.0.1", true) }}", "listen_port": 8080, "verbosity": "error", "enable_openapi": false, - "jwt_secret_key": "somethingrandom", + "jwt_secret_key": "{{ api_server_jwt_key }}", "CORS_origins": [], - "username": "", - "password": "" + "username": "{{ api_server_username }}", + "password": "{{ api_server_password }}" }, "bot_name": "freqtrade", "initial_state": "running", diff --git a/tests/commands/test_build_config.py b/tests/commands/test_build_config.py index 291720f4b..66c750e79 100644 --- a/tests/commands/test_build_config.py +++ b/tests/commands/test_build_config.py @@ -50,6 +50,10 @@ def test_start_new_config(mocker, caplog, exchange): 'telegram': False, 'telegram_token': 'asdf1244', 'telegram_chat_id': '1144444', + 'api_server': False, + 'api_server_listen_addr': '127.0.0.1', + 'api_server_username': 'freqtrader', + 'api_server_password': 'MoneyMachine', } mocker.patch('freqtrade.commands.build_config_commands.ask_user_config', return_value=sample_selections) From 932284574077efca1c6cb1b578e2df48dc93540d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Mar 2021 05:27:22 +0000 Subject: [PATCH 11/30] Bump mkdocs-material from 7.0.6 to 7.0.7 Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 7.0.6 to 7.0.7. - [Release notes](https://github.com/squidfunk/mkdocs-material/releases) - [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/docs/changelog.md) - [Commits](https://github.com/squidfunk/mkdocs-material/compare/7.0.6...7.0.7) Signed-off-by: dependabot[bot] --- docs/requirements-docs.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements-docs.txt b/docs/requirements-docs.txt index 0068dd5d2..711b6ca46 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,3 +1,3 @@ -mkdocs-material==7.0.6 +mkdocs-material==7.0.7 mdx_truly_sane_lists==1.2 pymdown-extensions==8.1.1 From e5789b36cf8d6488abf1a8e0e2b71585c1893e9e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Mar 2021 05:27:57 +0000 Subject: [PATCH 12/30] Bump numpy from 1.20.1 to 1.20.2 Bumps [numpy](https://github.com/numpy/numpy) from 1.20.1 to 1.20.2. - [Release notes](https://github.com/numpy/numpy/releases) - [Changelog](https://github.com/numpy/numpy/blob/main/doc/HOWTO_RELEASE.rst.txt) - [Commits](https://github.com/numpy/numpy/compare/v1.20.1...v1.20.2) Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 56ada691f..201ce22fd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -numpy==1.20.1 +numpy==1.20.2 pandas==1.2.3 ccxt==1.43.89 From 607c05b3cec2523eec63b87639c64adec8bf928f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Mar 2021 05:28:16 +0000 Subject: [PATCH 13/30] Bump sqlalchemy from 1.4.2 to 1.4.3 Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 1.4.2 to 1.4.3. - [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases) - [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/master/CHANGES) - [Commits](https://github.com/sqlalchemy/sqlalchemy/commits) Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 56ada691f..ff5412fb7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,7 @@ ccxt==1.43.89 # Pin cryptography for now due to rust build errors with piwheels cryptography==3.4.6 aiohttp==3.7.4.post0 -SQLAlchemy==1.4.2 +SQLAlchemy==1.4.3 python-telegram-bot==13.4.1 arrow==1.0.3 cachetools==4.2.1 From 8e49271e6f948a37695438e8e57e43053e0c623a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Mar 2021 05:28:30 +0000 Subject: [PATCH 14/30] Bump prompt-toolkit from 3.0.17 to 3.0.18 Bumps [prompt-toolkit](https://github.com/prompt-toolkit/python-prompt-toolkit) from 3.0.17 to 3.0.18. - [Release notes](https://github.com/prompt-toolkit/python-prompt-toolkit/releases) - [Changelog](https://github.com/prompt-toolkit/python-prompt-toolkit/blob/master/CHANGELOG) - [Commits](https://github.com/prompt-toolkit/python-prompt-toolkit/compare/3.0.17...3.0.18) Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 56ada691f..127b9a776 100644 --- a/requirements.txt +++ b/requirements.txt @@ -39,4 +39,4 @@ aiofiles==0.6.0 colorama==0.4.4 # Building config files interactively questionary==1.9.0 -prompt-toolkit==3.0.17 +prompt-toolkit==3.0.18 From 95a9c92769c389fd44693ee8c6fdfa92755e43d5 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 29 Mar 2021 09:13:48 +0200 Subject: [PATCH 15/30] Add permission-check before slack notify --- .github/workflows/ci.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 61ecaa522..dd6af0a06 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -310,9 +310,17 @@ jobs: needs: [ build_linux, build_macos, build_windows, docs_check ] runs-on: ubuntu-20.04 steps: + - name: Check user permission + id: check + uses: scherermichael-oss/action-has-permission@1.0.6 + with: + required-permission: write + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Slack Notification uses: lazy-actions/slatify@v3.0.0 - if: always() && ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false) + if: always() && steps.check.outputs.has-permission && ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false) with: type: ${{ job.status }} job_name: '*Freqtrade CI*' From 8d01767a421113c80870b392175effbfd3300def Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 29 Mar 2021 09:20:34 +0200 Subject: [PATCH 16/30] Fix CI syntax --- .github/workflows/ci.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd6af0a06..8e15a5a89 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -310,13 +310,14 @@ jobs: needs: [ build_linux, build_macos, build_windows, docs_check ] runs-on: ubuntu-20.04 steps: + - name: Check user permission - id: check - uses: scherermichael-oss/action-has-permission@1.0.6 - with: - required-permission: write - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + id: check + uses: scherermichael-oss/action-has-permission@1.0.6 + with: + required-permission: write + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Slack Notification uses: lazy-actions/slatify@v3.0.0 From dacaa4a732a396315eeb21f58301d7cccbef7056 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Mar 2021 09:34:57 +0000 Subject: [PATCH 17/30] Bump ccxt from 1.43.89 to 1.45.44 Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.43.89 to 1.45.44. - [Release notes](https://github.com/ccxt/ccxt/releases) - [Changelog](https://github.com/ccxt/ccxt/blob/master/doc/exchanges-by-country.rst) - [Commits](https://github.com/ccxt/ccxt/compare/1.43.89...1.45.44) Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 10225f910..d3b8acb25 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ numpy==1.20.2 pandas==1.2.3 -ccxt==1.43.89 +ccxt==1.45.44 # Pin cryptography for now due to rust build errors with piwheels cryptography==3.4.6 aiohttp==3.7.4.post0 From 3e864a87ad66b10058df601a4f7759dfe236ff70 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Mar 2021 09:53:50 +0000 Subject: [PATCH 18/30] Bump cryptography from 3.4.6 to 3.4.7 Bumps [cryptography](https://github.com/pyca/cryptography) from 3.4.6 to 3.4.7. - [Release notes](https://github.com/pyca/cryptography/releases) - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/3.4.6...3.4.7) Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 10225f910..a57233823 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ pandas==1.2.3 ccxt==1.43.89 # Pin cryptography for now due to rust build errors with piwheels -cryptography==3.4.6 +cryptography==3.4.7 aiohttp==3.7.4.post0 SQLAlchemy==1.4.3 python-telegram-bot==13.4.1 From 5d5debab667facfb0bed113ed878392d4b52caeb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Mar 2021 10:01:20 +0000 Subject: [PATCH 19/30] Bump scipy from 1.6.1 to 1.6.2 Bumps [scipy](https://github.com/scipy/scipy) from 1.6.1 to 1.6.2. - [Release notes](https://github.com/scipy/scipy/releases) - [Commits](https://github.com/scipy/scipy/compare/v1.6.1...v1.6.2) Signed-off-by: dependabot[bot] --- requirements-hyperopt.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-hyperopt.txt b/requirements-hyperopt.txt index 8cdb6fd28..9eb490f83 100644 --- a/requirements-hyperopt.txt +++ b/requirements-hyperopt.txt @@ -2,7 +2,7 @@ -r requirements.txt # Required for hyperopt -scipy==1.6.1 +scipy==1.6.2 scikit-learn==0.24.1 scikit-optimize==0.8.1 filelock==3.0.12 From 89bbfd2324ebf0974c60f1b8689941a079b14eea Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 29 Mar 2021 20:22:52 +0200 Subject: [PATCH 20/30] Remove candle_count from dataframe before backtesting closes #3754 --- freqtrade/data/converter.py | 16 +++++++++++----- freqtrade/optimize/backtesting.py | 3 ++- freqtrade/optimize/hyperopt.py | 3 ++- tests/data/test_converter.py | 10 ++++++++++ 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/freqtrade/data/converter.py b/freqtrade/data/converter.py index d4053abaa..defc96ef8 100644 --- a/freqtrade/data/converter.py +++ b/freqtrade/data/converter.py @@ -115,17 +115,23 @@ def ohlcv_fill_up_missing_data(dataframe: DataFrame, timeframe: str, pair: str) return df -def trim_dataframe(df: DataFrame, timerange, df_date_col: str = 'date') -> DataFrame: +def trim_dataframe(df: DataFrame, timerange, df_date_col: str = 'date', + startup_candles: int = 0) -> DataFrame: """ Trim dataframe based on given timerange :param df: Dataframe to trim :param timerange: timerange (use start and end date if available) - :param: df_date_col: Column in the dataframe to use as Date column + :param df_date_col: Column in the dataframe to use as Date column + :param startup_candles: When not 0, is used instead the timerange start date :return: trimmed dataframe """ - if timerange.starttype == 'date': - start = datetime.fromtimestamp(timerange.startts, tz=timezone.utc) - df = df.loc[df[df_date_col] >= start, :] + if startup_candles: + # Trim candles instead of timeframe in case of given startup_candle count + df = df.iloc[startup_candles:, :] + else: + if timerange.starttype == 'date': + start = datetime.fromtimestamp(timerange.startts, tz=timezone.utc) + df = df.loc[df[df_date_col] >= start, :] if timerange.stoptype == 'date': stop = datetime.fromtimestamp(timerange.stopts, tz=timezone.utc) df = df.loc[df[df_date_col] <= stop, :] diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 765e2844a..ff1dd934c 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -443,7 +443,8 @@ class Backtesting: # Trim startup period from analyzed dataframe for pair, df in preprocessed.items(): - preprocessed[pair] = trim_dataframe(df, timerange) + preprocessed[pair] = trim_dataframe(df, timerange, + startup_candles=self.required_startup) min_date, max_date = history.get_timerange(preprocessed) logger.info(f'Backtesting with data from {min_date.strftime(DATETIME_PRINT_FORMAT)} ' diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 03f34a511..ee453489d 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -379,7 +379,8 @@ class Hyperopt: # Trim startup period from analyzed dataframe for pair, df in preprocessed.items(): - preprocessed[pair] = trim_dataframe(df, timerange) + preprocessed[pair] = trim_dataframe(df, timerange, + startup_candles=self.backtesting.required_startup) min_date, max_date = get_timerange(preprocessed) logger.info(f'Hyperopting with data from {min_date.strftime(DATETIME_PRINT_FORMAT)} ' diff --git a/tests/data/test_converter.py b/tests/data/test_converter.py index 4fdcce4d2..2420dca8f 100644 --- a/tests/data/test_converter.py +++ b/tests/data/test_converter.py @@ -197,6 +197,16 @@ def test_trim_dataframe(testdatadir) -> None: assert all(data_modify.iloc[-1] == data.iloc[-1]) assert all(data_modify.iloc[0] == data.iloc[30]) + data_modify = data.copy() + tr = TimeRange('date', None, min_date + 1800, 0) + # Remove first 20 candles - ignores min date + data_modify = trim_dataframe(data_modify, tr, startup_candles=20) + assert not data_modify.equals(data) + assert len(data_modify) < len(data) + assert len(data_modify) == len(data) - 20 + assert all(data_modify.iloc[-1] == data.iloc[-1]) + assert all(data_modify.iloc[0] == data.iloc[20]) + data_modify = data.copy() # Remove last 30 minutes (1800 s) tr = TimeRange(None, 'date', 0, max_date - 1800) From 50fcb3f330a16a477e3fdf48243f1d3accad6402 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 30 Mar 2021 07:26:39 +0200 Subject: [PATCH 21/30] Reduce verbosity of missing data if less than 1% of data is missing --- freqtrade/data/converter.py | 9 ++++++++- tests/data/test_converter.py | 10 +++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/freqtrade/data/converter.py b/freqtrade/data/converter.py index defc96ef8..c9d4ef19f 100644 --- a/freqtrade/data/converter.py +++ b/freqtrade/data/converter.py @@ -110,8 +110,15 @@ def ohlcv_fill_up_missing_data(dataframe: DataFrame, timeframe: str, pair: str) df.reset_index(inplace=True) len_before = len(dataframe) len_after = len(df) + pct_missing = (len_after - len_before) / len_before if len_before > 0 else 0 if len_before != len_after: - logger.info(f"Missing data fillup for {pair}: before: {len_before} - after: {len_after}") + message = (f"Missing data fillup for {pair}: before: {len_before} - after: {len_after}" + f" - {round(pct_missing * 100, 2)} %") + if pct_missing > 0.01: + logger.info(message) + else: + # Don't be verbose if only a small amount is missing + logger.debug(message) return df diff --git a/tests/data/test_converter.py b/tests/data/test_converter.py index 2420dca8f..68960af1c 100644 --- a/tests/data/test_converter.py +++ b/tests/data/test_converter.py @@ -10,7 +10,7 @@ from freqtrade.data.converter import (convert_ohlcv_format, convert_trades_forma trades_to_ohlcv, trim_dataframe) from freqtrade.data.history import (get_timerange, load_data, load_pair_history, validate_backtest_data) -from tests.conftest import log_has +from tests.conftest import log_has, log_has_re from tests.data.test_history import _backup_file, _clean_test_file @@ -62,8 +62,8 @@ def test_ohlcv_fill_up_missing_data(testdatadir, caplog): # Column names should not change assert (data.columns == data2.columns).all() - assert log_has(f"Missing data fillup for UNITTEST/BTC: before: " - f"{len(data)} - after: {len(data2)}", caplog) + assert log_has_re(f"Missing data fillup for UNITTEST/BTC: before: " + f"{len(data)} - after: {len(data2)}.*", caplog) # Test fillup actually fixes invalid backtest data min_date, max_date = get_timerange({'UNITTEST/BTC': data}) @@ -125,8 +125,8 @@ def test_ohlcv_fill_up_missing_data2(caplog): # Column names should not change assert (data.columns == data2.columns).all() - assert log_has(f"Missing data fillup for UNITTEST/BTC: before: " - f"{len(data)} - after: {len(data2)}", caplog) + assert log_has_re(f"Missing data fillup for UNITTEST/BTC: before: " + f"{len(data)} - after: {len(data2)}.*", caplog) def test_ohlcv_drop_incomplete(caplog): From 2869d5368de5868b7dfb0c72d402449cf72c2997 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 30 Mar 2021 20:20:24 +0200 Subject: [PATCH 22/30] Allow edge to use dynamic pairlists closes #4298 --- docs/edge.md | 6 +++--- freqtrade/configuration/config_validation.py | 5 ----- freqtrade/edge/edge_positioning.py | 5 ++--- freqtrade/freqtradebot.py | 2 +- freqtrade/optimize/edge_cli.py | 2 +- tests/edge/test_edge.py | 8 ++++---- tests/test_configuration.py | 16 ---------------- 7 files changed, 11 insertions(+), 33 deletions(-) diff --git a/docs/edge.md b/docs/edge.md index 5565ca2f9..0aa76cd12 100644 --- a/docs/edge.md +++ b/docs/edge.md @@ -1,9 +1,9 @@ # Edge positioning -The `Edge Positioning` module uses probability to calculate your win rate and risk reward ratio. It will use these statistics to control your strategy trade entry points, position size and, stoploss. +The `Edge Positioning` module uses probability to calculate your win rate and risk reward ratio. It will use these statistics to control your strategy trade entry points, position size and, stoploss. !!! Warning - `Edge positioning` is not compatible with dynamic (volume-based) whitelist. + WHen using `Edge positioning` with a dynamic whitelist (VolumePairList), make sure to also use `AgeFilter` and set it to at least `calculate_since_number_of_days` to avoid problems with missing data. !!! Note `Edge Positioning` only considers *its own* buy/sell/stoploss signals. It ignores the stoploss, trailing stoploss, and ROI settings in the strategy configuration file. @@ -14,7 +14,7 @@ The `Edge Positioning` module uses probability to calculate your win rate and ri Trading strategies are not perfect. They are frameworks that are susceptible to the market and its indicators. Because the market is not at all predictable, sometimes a strategy will win and sometimes the same strategy will lose. -To obtain an edge in the market, a strategy has to make more money than it loses. Making money in trading is not only about *how often* the strategy makes or loses money. +To obtain an edge in the market, a strategy has to make more money than it loses. Making money in trading is not only about *how often* the strategy makes or loses money. !!! tip "It doesn't matter how often, but how much!" A bad strategy might make 1 penny in *ten* transactions but lose 1 dollar in *one* transaction. If one only checks the number of winning trades, it would be misleading to think that the strategy is actually making a profit. diff --git a/freqtrade/configuration/config_validation.py b/freqtrade/configuration/config_validation.py index c7e49f33d..31e38d572 100644 --- a/freqtrade/configuration/config_validation.py +++ b/freqtrade/configuration/config_validation.py @@ -149,11 +149,6 @@ def _validate_edge(conf: Dict[str, Any]) -> None: if not conf.get('edge', {}).get('enabled'): return - if conf.get('pairlist', {}).get('method') == 'VolumePairList': - raise OperationalException( - "Edge and VolumePairList are incompatible, " - "Edge will override whatever pairs VolumePairlist selects." - ) if not conf.get('ask_strategy', {}).get('use_sell_signal', True): raise OperationalException( "Edge requires `use_sell_signal` to be True, otherwise no sells will happen." diff --git a/freqtrade/edge/edge_positioning.py b/freqtrade/edge/edge_positioning.py index ff86e522e..d1f76c21f 100644 --- a/freqtrade/edge/edge_positioning.py +++ b/freqtrade/edge/edge_positioning.py @@ -84,9 +84,8 @@ class Edge: self.fee = self.exchange.get_fee(symbol=expand_pairlist( self.config['exchange']['pair_whitelist'], list(self.exchange.markets))[0]) - def calculate(self) -> bool: - pairs = expand_pairlist(self.config['exchange']['pair_whitelist'], - list(self.exchange.markets)) + def calculate(self, pairs: List[str]) -> bool: + heartbeat = self.edge_config.get('process_throttle_secs') if (self._last_updated > 0) and ( diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 73f4c91be..dd6966848 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -225,7 +225,7 @@ class FreqtradeBot(LoggingMixin): # Calculating Edge positioning if self.edge: - self.edge.calculate() + self.edge.calculate(_whitelist) _whitelist = self.edge.adjust(_whitelist) if trades: diff --git a/freqtrade/optimize/edge_cli.py b/freqtrade/optimize/edge_cli.py index a5f505bee..aab7def05 100644 --- a/freqtrade/optimize/edge_cli.py +++ b/freqtrade/optimize/edge_cli.py @@ -44,7 +44,7 @@ class EdgeCli: 'timerange') is None else str(self.config.get('timerange'))) def start(self) -> None: - result = self.edge.calculate() + result = self.edge.calculate(self.config['exchange']['pair_whitelist']) if result: print('') # blank line for readability print(generate_edge_table(self.edge._cached_pairs)) diff --git a/tests/edge/test_edge.py b/tests/edge/test_edge.py index c30bce6a4..5142dd985 100644 --- a/tests/edge/test_edge.py +++ b/tests/edge/test_edge.py @@ -266,7 +266,7 @@ def test_edge_heartbeat_calculate(mocker, edge_conf): # should not recalculate if heartbeat not reached edge._last_updated = arrow.utcnow().int_timestamp - heartbeat + 1 - assert edge.calculate() is False + assert edge.calculate(edge_conf['exchange']['pair_whitelist']) is False def mocked_load_data(datadir, pairs=[], timeframe='0m', @@ -310,7 +310,7 @@ def test_edge_process_downloaded_data(mocker, edge_conf): mocker.patch('freqtrade.edge.edge_positioning.load_data', mocked_load_data) edge = Edge(edge_conf, freqtrade.exchange, freqtrade.strategy) - assert edge.calculate() + assert edge.calculate(edge_conf['exchange']['pair_whitelist']) assert len(edge._cached_pairs) == 2 assert edge._last_updated <= arrow.utcnow().int_timestamp + 2 @@ -322,7 +322,7 @@ def test_edge_process_no_data(mocker, edge_conf, caplog): mocker.patch('freqtrade.edge.edge_positioning.load_data', MagicMock(return_value={})) edge = Edge(edge_conf, freqtrade.exchange, freqtrade.strategy) - assert not edge.calculate() + assert not edge.calculate(edge_conf['exchange']['pair_whitelist']) assert len(edge._cached_pairs) == 0 assert log_has("No data found. Edge is stopped ...", caplog) assert edge._last_updated == 0 @@ -337,7 +337,7 @@ def test_edge_process_no_trades(mocker, edge_conf, caplog): mocker.patch('freqtrade.edge.Edge._find_trades_for_stoploss_range', MagicMock(return_value=[])) edge = Edge(edge_conf, freqtrade.exchange, freqtrade.strategy) - assert not edge.calculate() + assert not edge.calculate(edge_conf['exchange']['pair_whitelist']) assert len(edge._cached_pairs) == 0 assert log_has("No trades found.", caplog) diff --git a/tests/test_configuration.py b/tests/test_configuration.py index a0824e65c..15fbab7f8 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -860,22 +860,6 @@ def test_validate_tsl(default_conf): validate_config_consistency(default_conf) -def test_validate_edge(edge_conf): - edge_conf.update({"pairlist": { - "method": "VolumePairList", - }}) - - with pytest.raises(OperationalException, - match="Edge and VolumePairList are incompatible, " - "Edge will override whatever pairs VolumePairlist selects."): - validate_config_consistency(edge_conf) - - edge_conf.update({"pairlist": { - "method": "StaticPairList", - }}) - validate_config_consistency(edge_conf) - - def test_validate_edge2(edge_conf): edge_conf.update({"ask_strategy": { "use_sell_signal": True, From 51f0fcb2cb071ae2753c94a21e23c87b9a57e129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mads=20S=C3=B8rensen?= Date: Fri, 2 Apr 2021 12:20:38 +0200 Subject: [PATCH 23/30] Add profit_fiat to REST API --- freqtrade/rpc/api_server/api_schemas.py | 1 + freqtrade/rpc/rpc.py | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/freqtrade/rpc/api_server/api_schemas.py b/freqtrade/rpc/api_server/api_schemas.py index 32a1c8597..eaca477d7 100644 --- a/freqtrade/rpc/api_server/api_schemas.py +++ b/freqtrade/rpc/api_server/api_schemas.py @@ -168,6 +168,7 @@ class TradeSchema(BaseModel): profit_ratio: Optional[float] profit_pct: Optional[float] profit_abs: Optional[float] + profit_fiat: Optional[float] sell_reason: Optional[str] sell_order_status: Optional[str] stop_loss_abs: Optional[float] diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 62f1c2592..1b2dc5d66 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -173,6 +173,14 @@ class RPC: current_rate = NAN current_profit = trade.calc_profit_ratio(current_rate) current_profit_abs = trade.calc_profit(current_rate) + + # Calculate fiat profit + current_profit_fiat = self._fiat_converter.convert_amount( + current_profit_abs, + self._freqtrade.config['stake_currency'], + self._freqtrade.config['fiat_display_currency'] + ) + # Calculate guaranteed profit (in case of trailing stop) stoploss_entry_dist = trade.calc_profit(trade.stop_loss) stoploss_entry_dist_ratio = trade.calc_profit_ratio(trade.stop_loss) @@ -191,6 +199,7 @@ class RPC: profit_ratio=current_profit, profit_pct=round(current_profit * 100, 2), profit_abs=current_profit_abs, + profit_fiat=current_profit_fiat, stoploss_current_dist=stoploss_current_dist, stoploss_current_dist_ratio=round(stoploss_current_dist_ratio, 8), From 2c0079b00b8902405f487f1c8ffbc1f614de8651 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mads=20S=C3=B8rensen?= Date: Fri, 2 Apr 2021 13:16:52 +0200 Subject: [PATCH 24/30] Add profit_fiat to tests, use ANY, as price changes... --- tests/rpc/test_rpc_apiserver.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index 5a0a04943..3b1ef6a74 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -786,6 +786,7 @@ def test_api_status(botclient, mocker, ticker, fee, markets): 'profit_ratio': -0.00408133, 'profit_pct': -0.41, 'profit_abs': -4.09e-06, + 'profit_fiat': ANY, 'current_rate': 1.099e-05, 'open_date': ANY, 'open_date_hum': 'just now', From f47dc317867ebe5186519d99e4ee5d3b0ffab2d3 Mon Sep 17 00:00:00 2001 From: shubhendra Date: Sun, 21 Mar 2021 17:14:35 +0530 Subject: [PATCH 25/30] Refactor the comparison involving `not` Signed-off-by: shubhendra --- .deepsource.toml | 16 ---------------- freqtrade/exchange/exchange.py | 2 +- freqtrade/plugins/pairlist/PerformanceFilter.py | 2 +- freqtrade/plugins/protections/cooldown_period.py | 1 - freqtrade/resolvers/strategy_resolver.py | 4 ++-- 5 files changed, 4 insertions(+), 21 deletions(-) delete mode 100644 .deepsource.toml diff --git a/.deepsource.toml b/.deepsource.toml deleted file mode 100644 index 7a00ca8d6..000000000 --- a/.deepsource.toml +++ /dev/null @@ -1,16 +0,0 @@ -version = 1 - -test_patterns = ["tests/**/test_*.py"] - -exclude_patterns = [ - "docs/**", - "user_data/**", - "build/helpers/**" -] - -[[analyzers]] -name = "python" -enabled = true - - [analyzers.meta] - runtime_version = "3.x.x" diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 9c868df2b..85c5b4c6d 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -806,7 +806,7 @@ class Exchange: # Gather coroutines to run for pair, timeframe in set(pair_list): - if (not ((pair, timeframe) in self._klines) + if (((pair, timeframe) not in self._klines) or self._now_is_time_to_refresh(pair, timeframe)): input_coroutines.append(self._async_get_candle_history(pair, timeframe, since_ms=since_ms)) diff --git a/freqtrade/plugins/pairlist/PerformanceFilter.py b/freqtrade/plugins/pairlist/PerformanceFilter.py index c1355f655..73a9436fa 100644 --- a/freqtrade/plugins/pairlist/PerformanceFilter.py +++ b/freqtrade/plugins/pairlist/PerformanceFilter.py @@ -2,7 +2,7 @@ Performance pair list filter """ import logging -from typing import Any, Dict, List +from typing import Dict, List import pandas as pd diff --git a/freqtrade/plugins/protections/cooldown_period.py b/freqtrade/plugins/protections/cooldown_period.py index 197d74c2e..a2d8eca34 100644 --- a/freqtrade/plugins/protections/cooldown_period.py +++ b/freqtrade/plugins/protections/cooldown_period.py @@ -1,7 +1,6 @@ import logging from datetime import datetime, timedelta -from typing import Any, Dict from freqtrade.persistence import Trade from freqtrade.plugins.protections import IProtection, ProtectionReturn diff --git a/freqtrade/resolvers/strategy_resolver.py b/freqtrade/resolvers/strategy_resolver.py index 19bd014f9..05fbac10d 100644 --- a/freqtrade/resolvers/strategy_resolver.py +++ b/freqtrade/resolvers/strategy_resolver.py @@ -197,8 +197,8 @@ class StrategyResolver(IResolver): strategy._buy_fun_len = len(getfullargspec(strategy.populate_buy_trend).args) strategy._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]): + strategy._buy_fun_len, + strategy._sell_fun_len]): strategy.INTERFACE_VERSION = 1 return strategy From ede26091b980a22d84bc44ce5e5e3b74119ba76f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mads=20S=C3=B8rensen?= Date: Fri, 2 Apr 2021 14:35:19 +0200 Subject: [PATCH 26/30] Add validation in the right places... --- tests/rpc/test_rpc.py | 2 ++ tests/rpc/test_rpc_apiserver.py | 1 + 2 files changed, 3 insertions(+) diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py index b11470711..64918ed47 100644 --- a/tests/rpc/test_rpc.py +++ b/tests/rpc/test_rpc.py @@ -92,6 +92,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None: 'profit_ratio': -0.00408133, 'profit_pct': -0.41, 'profit_abs': -4.09e-06, + 'profit_fiat': ANY, 'stop_loss_abs': 9.882e-06, 'stop_loss_pct': -10.0, 'stop_loss_ratio': -0.1, @@ -159,6 +160,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None: 'profit_ratio': ANY, 'profit_pct': ANY, 'profit_abs': ANY, + 'profit_fiat': ANY, 'stop_loss_abs': 9.882e-06, 'stop_loss_pct': -10.0, 'stop_loss_ratio': -0.1, diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index 3b1ef6a74..20d32024f 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -966,6 +966,7 @@ def test_api_forcebuy(botclient, mocker, fee): 'profit_ratio': None, 'profit_pct': None, 'profit_abs': None, + 'profit_fiat': None, 'fee_close': 0.0025, 'fee_close_cost': None, 'fee_close_currency': None, From 3691ae8686d9987966956018aa8992b36278ce22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mads=20S=C3=B8rensen?= Date: Fri, 2 Apr 2021 14:50:47 +0200 Subject: [PATCH 27/30] Make sure the fiat converter exists before calling it --- freqtrade/rpc/rpc.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index 1b2dc5d66..1359729b9 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -175,11 +175,12 @@ class RPC: current_profit_abs = trade.calc_profit(current_rate) # Calculate fiat profit - current_profit_fiat = self._fiat_converter.convert_amount( - current_profit_abs, - self._freqtrade.config['stake_currency'], - self._freqtrade.config['fiat_display_currency'] - ) + 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'] + ) # Calculate guaranteed profit (in case of trailing stop) stoploss_entry_dist = trade.calc_profit(trade.stop_loss) From 7728e269fdcae6b078913628a067edb5cbcdfd7d Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 3 Apr 2021 07:17:02 +0200 Subject: [PATCH 28/30] Include Technical in default image --- docker-compose.yml | 2 +- docker/{Dockerfile.technical => Dockerfile.custom} | 3 ++- docs/docker_quickstart.md | 4 ++-- requirements.txt | 1 + setup.py | 1 + 5 files changed, 7 insertions(+), 4 deletions(-) rename docker/{Dockerfile.technical => Dockerfile.custom} (50%) diff --git a/docker-compose.yml b/docker-compose.yml index 1f63059f0..80e194ab2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,7 +9,7 @@ services: # Build step - only needed when additional dependencies are needed # build: # context: . - # dockerfile: "./docker/Dockerfile.technical" + # dockerfile: "./docker/Dockerfile.custom" restart: unless-stopped container_name: freqtrade volumes: diff --git a/docker/Dockerfile.technical b/docker/Dockerfile.custom similarity index 50% rename from docker/Dockerfile.technical rename to docker/Dockerfile.custom index 9431e72d0..10620e6b8 100644 --- a/docker/Dockerfile.technical +++ b/docker/Dockerfile.custom @@ -3,4 +3,5 @@ FROM freqtradeorg/freqtrade:develop RUN apt-get update \ && apt-get -y install git \ && apt-get clean \ - && pip install git+https://github.com/freqtrade/technical + # The below dependency - pyti - serves as an example. Please use whatever you need! + && pip install pyti diff --git a/docs/docker_quickstart.md b/docs/docker_quickstart.md index 017264569..9e74841b4 100644 --- a/docs/docker_quickstart.md +++ b/docs/docker_quickstart.md @@ -156,8 +156,8 @@ Head over to the [Backtesting Documentation](backtesting.md) to learn more. ### Additional dependencies with docker-compose -If your strategy requires dependencies not included in the default image (like [technical](https://github.com/freqtrade/technical)) - it will be necessary to build the image on your host. -For this, please create a Dockerfile containing installation steps for the additional dependencies (have a look at [docker/Dockerfile.technical](https://github.com/freqtrade/freqtrade/blob/develop/docker/Dockerfile.technical) for an example). +If your strategy requires dependencies not included in the default image - it will be necessary to build the image on your host. +For this, please create a Dockerfile containing installation steps for the additional dependencies (have a look at [docker/Dockerfile.custom](https://github.com/freqtrade/freqtrade/blob/develop/docker/Dockerfile.cusotm) for an example). You'll then also need to modify the `docker-compose.yml` file and uncomment the build step, as well as rename the image to avoid naming collisions. diff --git a/requirements.txt b/requirements.txt index 93ed7570e..e4984cf47 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,6 +14,7 @@ urllib3==1.26.4 wrapt==1.12.1 jsonschema==3.2.0 TA-Lib==0.4.19 +technical==1.2.2 tabulate==0.8.9 pycoingecko==1.4.0 jinja2==2.11.3 diff --git a/setup.py b/setup.py index 118bc8485..bf23fb999 100644 --- a/setup.py +++ b/setup.py @@ -77,6 +77,7 @@ setup(name='freqtrade', 'wrapt', 'jsonschema', 'TA-Lib', + 'technical', 'tabulate', 'pycoingecko', 'py_find_1st', From e7a1924aa0e1c9c795516db10690af8fbccffb37 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 3 Apr 2021 08:36:06 +0200 Subject: [PATCH 29/30] Fix typo --- docs/docker_quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docker_quickstart.md b/docs/docker_quickstart.md index 9e74841b4..ca0515281 100644 --- a/docs/docker_quickstart.md +++ b/docs/docker_quickstart.md @@ -157,7 +157,7 @@ Head over to the [Backtesting Documentation](backtesting.md) to learn more. ### Additional dependencies with docker-compose If your strategy requires dependencies not included in the default image - it will be necessary to build the image on your host. -For this, please create a Dockerfile containing installation steps for the additional dependencies (have a look at [docker/Dockerfile.custom](https://github.com/freqtrade/freqtrade/blob/develop/docker/Dockerfile.cusotm) for an example). +For this, please create a Dockerfile containing installation steps for the additional dependencies (have a look at [docker/Dockerfile.custom](https://github.com/freqtrade/freqtrade/blob/develop/docker/Dockerfile.custom) for an example). You'll then also need to modify the `docker-compose.yml` file and uncomment the build step, as well as rename the image to avoid naming collisions. From 6555454bd287a230de64e9686a09f6bf70fd36fe Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 3 Apr 2021 16:54:47 +0200 Subject: [PATCH 30/30] Remove more ticker_interval occurances --- docs/backtesting.md | 3 +-- docs/edge.md | 3 +-- docs/hyperopt.md | 3 +-- docs/plotting.md | 6 ++---- docs/utils.md | 2 +- freqtrade/commands/cli_options.py | 2 +- freqtrade/commands/list_commands.py | 2 +- freqtrade/optimize/hyperopt_interface.py | 6 +++--- freqtrade/templates/sample_strategy.py | 2 +- tests/optimize/test_backtest_detail.py | 2 +- tests/strategy/strats/default_strategy.py | 2 +- tests/strategy/strats/legacy_strategy.py | 2 +- 12 files changed, 15 insertions(+), 20 deletions(-) diff --git a/docs/backtesting.md b/docs/backtesting.md index d02c59f05..c8acfdbe1 100644 --- a/docs/backtesting.md +++ b/docs/backtesting.md @@ -23,8 +23,7 @@ usage: freqtrade backtesting [-h] [-v] [--logfile FILE] [-V] [-c PATH] optional arguments: -h, --help show this help message and exit -i TIMEFRAME, --timeframe TIMEFRAME, --ticker-interval TIMEFRAME - Specify ticker interval (`1m`, `5m`, `30m`, `1h`, - `1d`). + Specify timeframe (`1m`, `5m`, `30m`, `1h`, `1d`). --timerange TIMERANGE Specify what timerange of data to use. --data-format-ohlcv {json,jsongz,hdf5} diff --git a/docs/edge.md b/docs/edge.md index 0aa76cd12..7f0a9cb2d 100644 --- a/docs/edge.md +++ b/docs/edge.md @@ -221,8 +221,7 @@ usage: freqtrade edge [-h] [-v] [--logfile FILE] [-V] [-c PATH] [-d PATH] optional arguments: -h, --help show this help message and exit -i TIMEFRAME, --timeframe TIMEFRAME, --ticker-interval TIMEFRAME - Specify ticker interval (`1m`, `5m`, `30m`, `1h`, - `1d`). + Specify timeframe (`1m`, `5m`, `30m`, `1h`, `1d`). --timerange TIMERANGE Specify what timerange of data to use. --max-open-trades INT diff --git a/docs/hyperopt.md b/docs/hyperopt.md index 96c7354b9..7ae06660b 100644 --- a/docs/hyperopt.md +++ b/docs/hyperopt.md @@ -53,8 +53,7 @@ usage: freqtrade hyperopt [-h] [-v] [--logfile FILE] [-V] [-c PATH] [-d PATH] optional arguments: -h, --help show this help message and exit -i TIMEFRAME, --timeframe TIMEFRAME, --ticker-interval TIMEFRAME - Specify ticker interval (`1m`, `5m`, `30m`, `1h`, - `1d`). + Specify timeframe (`1m`, `5m`, `30m`, `1h`, `1d`). --timerange TIMERANGE Specify what timerange of data to use. --data-format-ohlcv {json,jsongz,hdf5} diff --git a/docs/plotting.md b/docs/plotting.md index d7ed5ab1f..63afa16b6 100644 --- a/docs/plotting.md +++ b/docs/plotting.md @@ -66,8 +66,7 @@ optional arguments: --timerange TIMERANGE Specify what timerange of data to use. -i TIMEFRAME, --timeframe TIMEFRAME, --ticker-interval TIMEFRAME - Specify ticker interval (`1m`, `5m`, `30m`, `1h`, - `1d`). + Specify timeframe (`1m`, `5m`, `30m`, `1h`, `1d`). --no-trades Skip using trades from backtesting file and DB. Common arguments: @@ -264,8 +263,7 @@ optional arguments: Specify the source for trades (Can be DB or file (backtest file)) Default: file -i TIMEFRAME, --timeframe TIMEFRAME, --ticker-interval TIMEFRAME - Specify ticker interval (`1m`, `5m`, `30m`, `1h`, - `1d`). + Specify timeframe (`1m`, `5m`, `30m`, `1h`, `1d`). Common arguments: -v, --verbose Verbose mode (-vv for more, -vvv to get all messages). diff --git a/docs/utils.md b/docs/utils.md index cf7d5f1d1..a84f068e9 100644 --- a/docs/utils.md +++ b/docs/utils.md @@ -264,7 +264,7 @@ All exchanges supported by the ccxt library: _1btcxe, acx, adara, allcoin, anxpr ## List Timeframes -Use the `list-timeframes` subcommand to see the list of timeframes (ticker intervals) available for the exchange. +Use the `list-timeframes` subcommand to see the list of timeframes available for the exchange. ``` usage: freqtrade list-timeframes [-h] [-v] [--logfile FILE] [-V] [-c PATH] [-d PATH] [--userdir PATH] [--exchange EXCHANGE] [-1] diff --git a/freqtrade/commands/cli_options.py b/freqtrade/commands/cli_options.py index 15c13cec9..12c03d824 100644 --- a/freqtrade/commands/cli_options.py +++ b/freqtrade/commands/cli_options.py @@ -118,7 +118,7 @@ AVAILABLE_CLI_OPTIONS = { # Optimize common "timeframe": Arg( '-i', '--timeframe', '--ticker-interval', - help='Specify ticker interval (`1m`, `5m`, `30m`, `1h`, `1d`).', + help='Specify timeframe (`1m`, `5m`, `30m`, `1h`, `1d`).', ), "timerange": Arg( '--timerange', diff --git a/freqtrade/commands/list_commands.py b/freqtrade/commands/list_commands.py index 5f53fc824..d509bfaa5 100644 --- a/freqtrade/commands/list_commands.py +++ b/freqtrade/commands/list_commands.py @@ -99,7 +99,7 @@ def start_list_hyperopts(args: Dict[str, Any]) -> None: def start_list_timeframes(args: Dict[str, Any]) -> None: """ - Print ticker intervals (timeframes) available on Exchange + Print timeframes available on Exchange """ config = setup_utils_configuration(args, RunMode.UTIL_EXCHANGE) # Do not use timeframe set in the config diff --git a/freqtrade/optimize/hyperopt_interface.py b/freqtrade/optimize/hyperopt_interface.py index 561fb8e11..a9bbc021c 100644 --- a/freqtrade/optimize/hyperopt_interface.py +++ b/freqtrade/optimize/hyperopt_interface.py @@ -31,7 +31,7 @@ class IHyperOpt(ABC): Defines the mandatory structure must follow any custom hyperopt Class attributes you can use: - ticker_interval -> int: value of the ticker interval to use for the strategy + timeframe -> int: value of the timeframe to use for the strategy """ ticker_interval: str # DEPRECATED timeframe: str @@ -97,7 +97,7 @@ class IHyperOpt(ABC): This method implements adaptive roi hyperspace with varied ranges for parameters which automatically adapts to the - ticker interval used. + timeframe used. It's used by Freqtrade by default, if no custom roi_space method is defined. """ @@ -119,7 +119,7 @@ class IHyperOpt(ABC): # * 'roi_p' (limits for the ROI value steps) components are scaled logarithmically. # # The scaling is designed so that it maps exactly to the legacy Freqtrade roi_space() - # method for the 5m ticker interval. + # method for the 5m timeframe. roi_t_scale = timeframe_min / 5 roi_p_scale = math.log1p(timeframe_min) / math.log1p(5) roi_limits = { diff --git a/freqtrade/templates/sample_strategy.py b/freqtrade/templates/sample_strategy.py index 5dfa42bcc..904597d21 100644 --- a/freqtrade/templates/sample_strategy.py +++ b/freqtrade/templates/sample_strategy.py @@ -53,7 +53,7 @@ class SampleStrategy(IStrategy): # trailing_stop_positive = 0.01 # trailing_stop_positive_offset = 0.0 # Disabled / not configured - # Optimal ticker interval for the strategy. + # Optimal timeframe for the strategy. timeframe = '5m' # Run "populate_indicators()" only for new candle. diff --git a/tests/optimize/test_backtest_detail.py b/tests/optimize/test_backtest_detail.py index 0ba6f4a7f..3655b941d 100644 --- a/tests/optimize/test_backtest_detail.py +++ b/tests/optimize/test_backtest_detail.py @@ -268,7 +268,7 @@ tc16 = BTContainer(data=[ # Test 17: Buy, hold for 120 mins, then forcesell 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 ticker interval. +# Uses open as sell-rate (special case) - since the roi-time is a multiple of the timeframe. tc17 = BTContainer(data=[ # D O H L C V B S [0, 5000, 5025, 4975, 4987, 6172, 1, 0], diff --git a/tests/strategy/strats/default_strategy.py b/tests/strategy/strats/default_strategy.py index 98842ff7c..7171b93ae 100644 --- a/tests/strategy/strats/default_strategy.py +++ b/tests/strategy/strats/default_strategy.py @@ -28,7 +28,7 @@ class DefaultStrategy(IStrategy): # Optimal stoploss designed for the strategy stoploss = -0.10 - # Optimal ticker interval for the strategy + # Optimal timeframe for the strategy timeframe = '5m' # Optional order type mapping diff --git a/tests/strategy/strats/legacy_strategy.py b/tests/strategy/strats/legacy_strategy.py index 1e7bb5e1e..9ef00b110 100644 --- a/tests/strategy/strats/legacy_strategy.py +++ b/tests/strategy/strats/legacy_strategy.py @@ -31,7 +31,7 @@ class TestStrategyLegacy(IStrategy): # This attribute will be overridden if the config file contains "stoploss" stoploss = -0.10 - # Optimal ticker interval for the strategy + # Optimal timeframe for the strategy # Keep the legacy value here to test compatibility ticker_interval = '5m'