Compare commits

...

70 Commits

Author SHA1 Message Date
Matthias
2db5cc177d Merge pull request #7029 from freqtrade/new_release
New release 2022.6
2022-07-03 19:42:24 +02:00
Matthias
c1d4078518 Version bump to 2022.6 2022-07-03 15:04:38 +02:00
Matthias
d25ec6d0b8 Merge branch 'stable' into new_release 2022-07-03 15:04:16 +02:00
Matthias
07aa372e2a Ensure bot_loop_start is called in hyperopt, too
closes #7001
2022-07-03 14:10:59 +02:00
Matthias
c5e6520fee Reorder methods in freqtradebot 2022-07-03 13:35:26 +02:00
Matthias
f2fdc21374 Only use exit_tag if exit_type i exit_signal
closes #7027
2022-07-03 11:07:05 +02:00
Matthias
906c7b92fe Add enhance testcase to show problematic exit_reason behavior 2022-07-03 11:05:15 +02:00
Matthias
df8c9fc4e1 Merge pull request #7005 from freqtrade/dependabot/pip/develop/uvicorn-0.18.1
Bump uvicorn from 0.17.6 to 0.18.1
2022-07-03 07:52:09 +02:00
Matthias
3c1380fbc6 Merge pull request #7009 from freqtrade/dependabot/pip/develop/types-python-dateutil-2.8.18
Bump types-python-dateutil from 2.8.17 to 2.8.18
2022-06-28 08:02:33 +02:00
Matthias
86f4077024 update dateutil precommit 2022-06-28 07:37:54 +02:00
dependabot[bot]
f2bc35e058 Bump types-python-dateutil from 2.8.17 to 2.8.18
Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.8.17 to 2.8.18.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-python-dateutil
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-27 20:06:56 +00:00
Matthias
0a5225695a Merge pull request #7016 from freqtrade/dependabot/pip/develop/types-tabulate-0.8.11
Bump types-tabulate from 0.8.9 to 0.8.11
2022-06-27 22:05:45 +02:00
Matthias
74471e41db update tabulate precommit types 2022-06-27 18:23:00 +02:00
dependabot[bot]
8b1798522c Bump types-tabulate from 0.8.9 to 0.8.11
Bumps [types-tabulate](https://github.com/python/typeshed) from 0.8.9 to 0.8.11.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-tabulate
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-27 13:18:58 +00:00
Matthias
7de7425e24 Merge pull request #7007 from freqtrade/dependabot/pip/develop/time-machine-2.7.1
Bump time-machine from 2.7.0 to 2.7.1
2022-06-27 15:18:23 +02:00
Matthias
37dff8dc82 Merge pull request #7018 from freqtrade/dependabot/pip/develop/types-requests-2.28.0
Bump types-requests from 2.27.30 to 2.28.0
2022-06-27 15:17:57 +02:00
Matthias
0c69a08863 update requests precommit 2022-06-27 12:09:27 +02:00
dependabot[bot]
f6e058a327 Bump types-requests from 2.27.30 to 2.28.0
Bumps [types-requests](https://github.com/python/typeshed) from 2.27.30 to 2.28.0.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-requests
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-27 09:59:19 +00:00
dependabot[bot]
d60127a6d8 Bump time-machine from 2.7.0 to 2.7.1
Bumps [time-machine](https://github.com/adamchainz/time-machine) from 2.7.0 to 2.7.1.
- [Release notes](https://github.com/adamchainz/time-machine/releases)
- [Changelog](https://github.com/adamchainz/time-machine/blob/main/HISTORY.rst)
- [Commits](https://github.com/adamchainz/time-machine/compare/2.7.0...2.7.1)

---
updated-dependencies:
- dependency-name: time-machine
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-27 09:59:07 +00:00
Matthias
11a8151653 Merge pull request #7012 from freqtrade/dependabot/pip/develop/types-cachetools-5.2.1
Bump types-cachetools from 5.0.2 to 5.2.1
2022-06-27 11:54:43 +02:00
Matthias
e3abaaa1b7 Merge pull request #7019 from freqtrade/dependabot/pip/develop/pandas-1.4.3
Bump pandas from 1.4.2 to 1.4.3
2022-06-27 11:54:06 +02:00
dependabot[bot]
82ef97af7e Bump pandas from 1.4.2 to 1.4.3
Bumps [pandas](https://github.com/pandas-dev/pandas) from 1.4.2 to 1.4.3.
- [Release notes](https://github.com/pandas-dev/pandas/releases)
- [Changelog](https://github.com/pandas-dev/pandas/blob/main/RELEASE.md)
- [Commits](https://github.com/pandas-dev/pandas/compare/v1.4.2...v1.4.3)

---
updated-dependencies:
- dependency-name: pandas
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-27 07:44:33 +00:00
Matthias
74fdda6846 Merge pull request #7017 from freqtrade/dependabot/pip/develop/ccxt-1.89.14
Bump ccxt from 1.88.15 to 1.89.14
2022-06-27 09:43:29 +02:00
Matthias
9eaf0400fa Merge pull request #7020 from freqtrade/dependabot/pip/develop/orjson-3.7.3
Bump orjson from 3.7.2 to 3.7.3
2022-06-27 09:10:46 +02:00
Matthias
01185ab483 update cachetools precommit 2022-06-27 07:59:26 +02:00
Matthias
8405bf767b Merge pull request #7006 from freqtrade/dependabot/pip/develop/pytest-mock-3.8.1
Bump pytest-mock from 3.7.0 to 3.8.1
2022-06-27 07:43:55 +02:00
dependabot[bot]
9a9d1a8974 Bump orjson from 3.7.2 to 3.7.3
Bumps [orjson](https://github.com/ijl/orjson) from 3.7.2 to 3.7.3.
- [Release notes](https://github.com/ijl/orjson/releases)
- [Changelog](https://github.com/ijl/orjson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ijl/orjson/compare/3.7.2...3.7.3)

---
updated-dependencies:
- dependency-name: orjson
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-27 05:39:04 +00:00
dependabot[bot]
0ef2c812db Bump ccxt from 1.88.15 to 1.89.14
Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.88.15 to 1.89.14.
- [Release notes](https://github.com/ccxt/ccxt/releases)
- [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg)
- [Commits](https://github.com/ccxt/ccxt/compare/1.88.15...1.89.14)

---
updated-dependencies:
- dependency-name: ccxt
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-27 05:38:31 +00:00
Matthias
85d1b433bc Merge pull request #7013 from freqtrade/dependabot/pip/develop/tabulate-0.8.10
Bump tabulate from 0.8.9 to 0.8.10
2022-06-27 07:38:20 +02:00
Matthias
d8f616cf35 Merge pull request #7011 from freqtrade/dependabot/pip/develop/plotly-5.9.0
Bump plotly from 5.8.2 to 5.9.0
2022-06-27 07:37:33 +02:00
Matthias
870c25c81f Merge pull request #7010 from freqtrade/dependabot/pip/develop/sqlalchemy-1.4.39
Bump sqlalchemy from 1.4.37 to 1.4.39
2022-06-27 07:37:00 +02:00
Matthias
fb3bc189b5 Merge pull request #7008 from freqtrade/dependabot/pip/develop/mkdocs-material-8.3.8
Bump mkdocs-material from 8.3.6 to 8.3.8
2022-06-27 07:36:08 +02:00
dependabot[bot]
6510c8d330 Bump tabulate from 0.8.9 to 0.8.10
Bumps [tabulate](https://github.com/astanin/python-tabulate) from 0.8.9 to 0.8.10.
- [Release notes](https://github.com/astanin/python-tabulate/releases)
- [Changelog](https://github.com/astanin/python-tabulate/blob/master/CHANGELOG)
- [Commits](https://github.com/astanin/python-tabulate/compare/v0.8.9...v0.8.10)

---
updated-dependencies:
- dependency-name: tabulate
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-27 03:03:00 +00:00
dependabot[bot]
efee148e43 Bump types-cachetools from 5.0.2 to 5.2.1
Bumps [types-cachetools](https://github.com/python/typeshed) from 5.0.2 to 5.2.1.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-cachetools
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-27 03:02:53 +00:00
dependabot[bot]
8b7dc031f7 Bump plotly from 5.8.2 to 5.9.0
Bumps [plotly](https://github.com/plotly/plotly.py) from 5.8.2 to 5.9.0.
- [Release notes](https://github.com/plotly/plotly.py/releases)
- [Changelog](https://github.com/plotly/plotly.py/blob/master/CHANGELOG.md)
- [Commits](https://github.com/plotly/plotly.py/compare/v5.8.2...v5.9.0)

---
updated-dependencies:
- dependency-name: plotly
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-27 03:02:51 +00:00
dependabot[bot]
963f38a690 Bump sqlalchemy from 1.4.37 to 1.4.39
Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 1.4.37 to 1.4.39.
- [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases)
- [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst)
- [Commits](https://github.com/sqlalchemy/sqlalchemy/commits)

---
updated-dependencies:
- dependency-name: sqlalchemy
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-27 03:02:46 +00:00
dependabot[bot]
45db2347dc Bump mkdocs-material from 8.3.6 to 8.3.8
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 8.3.6 to 8.3.8.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/8.3.6...8.3.8)

---
updated-dependencies:
- dependency-name: mkdocs-material
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-27 03:02:29 +00:00
dependabot[bot]
4840c7d2fd Bump pytest-mock from 3.7.0 to 3.8.1
Bumps [pytest-mock](https://github.com/pytest-dev/pytest-mock) from 3.7.0 to 3.8.1.
- [Release notes](https://github.com/pytest-dev/pytest-mock/releases)
- [Changelog](https://github.com/pytest-dev/pytest-mock/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-mock/compare/v3.7.0...v3.8.1)

---
updated-dependencies:
- dependency-name: pytest-mock
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-27 03:02:16 +00:00
dependabot[bot]
92dbb0d366 Bump uvicorn from 0.17.6 to 0.18.1
Bumps [uvicorn](https://github.com/encode/uvicorn) from 0.17.6 to 0.18.1.
- [Release notes](https://github.com/encode/uvicorn/releases)
- [Changelog](https://github.com/encode/uvicorn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/encode/uvicorn/compare/0.17.6...0.18.1)

---
updated-dependencies:
- dependency-name: uvicorn
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-27 03:02:07 +00:00
Matthias
b5d0bc997d Clarify stoploss behavior when not defining offset
closes #6828
2022-06-24 17:25:33 +02:00
Matthias
ca88ea50c5 Merge pull request #6859 from mkavinkumar1/get
Removed None in dict.get()
2022-06-23 21:45:13 +02:00
Matthias
2b07d34611 Revert several undesired changes 2022-06-23 20:47:51 +02:00
Matthias
8bf0bf10c5 Merge branch 'develop' into pr/SmartManoj/6859 2022-06-23 20:43:35 +02:00
Matthias
c57db0a330 Version bump 2022.5.1 2022-06-01 06:34:28 +02:00
Matthias
f5087a82dc Merge branch 'stable' into new_release 2022-06-01 06:33:42 +02:00
Matthias
eed0d67005 Merge pull request #6893 from freqtrade/new_release
New release 2022.5
2022-05-28 13:46:24 +02:00
Matthias
a1d54f5ae0 Version bump 2022.5 2022-05-28 09:49:58 +02:00
Matthias
a4a7c6536d Merge branch 'stable' into new_release 2022-05-28 09:49:46 +02:00
மனோஜ்குமார் பழனிச்சாமி
2b61aa282a Removed None in dict.get()
https://stackoverflow.com/a/12631641

Extra Changes: freqtrade\freqtradebot.py:70
freqtrade\plugins\pairlistmanager.py:31
2022-05-18 03:41:10 +05:30
Matthias
340a97d1df Merge pull request #6811 from DJCrashdummy/patch-1
corrected minor "typo" in formatting
2022-05-10 19:16:40 +02:00
DJCrashdummy
fab197edf2 corrected minor "typo" in formatting 2022-05-10 10:33:04 +00:00
Matthias
851c5dad30 Version bump 2022.4.2 2022-05-03 20:37:29 +02:00
Matthias
5b76ae452f Fix fee handling for futures trades 2022-05-03 20:35:30 +02:00
Matthias
2c750fdb09 Reduce no stake amount verbosity
closes #6768
2022-05-03 20:35:22 +02:00
Matthias
e7f5252074 Version bump 2022.4.1 2022-05-01 16:49:11 +02:00
Matthias
dfbd1c34c4 Merge pull request #6755 from freqtrade/new_release
New release 2022.4
2022-05-01 14:51:39 +02:00
Matthias
7615c4e904 Version bump 2022.4 2022-05-01 11:19:32 +02:00
Matthias
e9b78bf3ae Merge branch 'stable' into new_release 2022-05-01 11:19:17 +02:00
Matthias
2e397a88e1 Merge pull request #6592 from freqtrade/new_release
New release 2022.3
2022-03-27 15:51:58 +02:00
Matthias
fe6c62e144 Version bump 2022.3 2022-03-27 15:27:16 +02:00
Matthias
f0db721f05 Merge branch 'stable' into new_release 2022-03-27 15:09:06 +02:00
Matthias
4d8d30ea39 Version bump to 2022.2.2 2022-03-21 06:34:33 +01:00
Matthias
e90e3cead0 Map usdt fiat to correct coingecko fiat 2022-03-21 06:34:20 +01:00
Matthias
a568548192 Merge pull request #6464 from freqtrade/new_release
New release 2022.2.1
2022-02-26 08:57:42 +01:00
Matthias
f9d10a7fad Version bump 2022.2.1 2022-02-26 08:35:50 +01:00
Matthias
cbc2b00ee6 Merge branch 'stable' into new_release 2022-02-26 08:35:31 +01:00
Matthias
8f7b857ae9 Merge pull request #6459 from freqtrade/new_release
New release 2022.2
2022-02-25 15:14:27 +01:00
Matthias
e88b022cd4 Version bump 2022.2 2022-02-25 12:07:09 +01:00
Matthias
bfb738f69f Merge branch 'stable' into new_release 2022-02-25 12:06:11 +01:00
Matthias
00dd8e76ee Merge pull request #6416 from froggleston/patch-2
Update windows_installation.md
2022-02-25 11:44:40 +01:00
27 changed files with 121 additions and 91 deletions

View File

@@ -13,11 +13,11 @@ repos:
- id: mypy
exclude: build_helpers
additional_dependencies:
- types-cachetools==5.0.2
- types-cachetools==5.2.1
- types-filelock==3.2.7
- types-requests==2.27.30
- types-tabulate==0.8.9
- types-python-dateutil==2.8.17
- types-requests==2.28.0
- types-tabulate==0.8.11
- types-python-dateutil==2.8.18
# stages: [push]
- repo: https://github.com/pycqa/isort

View File

@@ -20,7 +20,9 @@ All profit calculations of Freqtrade include fees. For Backtesting / Hyperopt /
## Bot execution logic
Starting freqtrade in dry-run or live mode (using `freqtrade trade`) will start the bot and start the bot iteration loop.
By default, loop runs every few seconds (`internals.process_throttle_secs`) and does roughly the following in the following sequence:
This will also run the `bot_start()` callback.
By default, the bot loop runs every few seconds (`internals.process_throttle_secs`) and performs the following actions:
* Fetch open trades from persistence.
* Calculate current list of tradable pairs.
@@ -54,6 +56,7 @@ This loop will be repeated again and again until the bot is stopped.
[backtesting](backtesting.md) or [hyperopt](hyperopt.md) do only part of the above logic, since most of the trading operations are fully simulated.
* Load historic data for configured pairlist.
* Calls `bot_start()` once.
* Calls `bot_loop_start()` once.
* Calculate indicators (calls `populate_indicators()` once per pair).
* Calculate entry / exit signals (calls `populate_entry_trend()` and `populate_exit_trend()` once per pair).

View File

@@ -1,5 +1,5 @@
mkdocs==1.3.0
mkdocs-material==8.3.6
mkdocs-material==8.3.8
mdx_truly_sane_lists==1.2
pymdown-extensions==9.5
jinja2==3.1.2

View File

@@ -130,7 +130,7 @@ In summary: The stoploss will be adjusted to be always be -10% of the highest ob
### Trailing stop loss, custom positive loss
It is also possible to have a default stop loss, when you are in the red with your buy (buy - fee), but once you hit positive result the system will utilize a new stop loss, which can have a different value.
You could also have a default stop loss when you are in the red with your buy (buy - fee), but once you hit a positive result (or an offset you define) the system will utilize a new stop loss, which can have a different value.
For example, your default stop loss is -10%, but once you have more than 0% profit (example 0.1%) a different trailing stoploss will be used.
!!! Note
@@ -142,6 +142,8 @@ Both values require `trailing_stop` to be set to true and `trailing_stop_positiv
stoploss = -0.10
trailing_stop = True
trailing_stop_positive = 0.02
trailing_stop_positive_offset = 0.0
trailing_only_offset_is_reached = False # Default - not necessary for this example
```
For example, simplified math:
@@ -156,11 +158,31 @@ For example, simplified math:
The 0.02 would translate to a -2% stop loss.
Before this, `stoploss` is used for the trailing stoploss.
!!! Tip "Use an offset to change your stoploss"
Use `trailing_stop_positive_offset` to ensure that your new trailing stoploss will be in profit by setting `trailing_stop_positive_offset` higher than `trailing_stop_positive`. Your first new stoploss value will then already have locked in profits.
Example with simplified math:
``` python
stoploss = -0.10
trailing_stop = True
trailing_stop_positive = 0.02
trailing_stop_positive_offset = 0.03
```
* the bot buys an asset at a price of 100$
* the stop loss is defined at -10%, so the stop loss would get triggered once the asset drops below 90$
* assuming the asset now increases to 102$
* the stoploss will now be at 91.8$ - 10% below the highest observed rate
* assuming the asset now increases to 103.5$ (above the offset configured)
* the stop loss will now be -2% of 103$ = 101.42$
* now the asset drops in value to 102\$, the stop loss will still be 101.42$ and would trigger once price breaks below 101.42$
### Trailing stop loss only once the trade has reached a certain offset
It is also possible to use a static stoploss until the offset is reached, and then trail the trade to take profits once the market turns.
You can also keep a static stoploss until the offset is reached, and then trail the trade to take profits once the market turns.
If `"trailing_only_offset_is_reached": true` then the trailing stoploss is only activated once the offset is reached. Until then, the stoploss remains at the configured `stoploss`.
If `trailing_only_offset_is_reached = True` then the trailing stoploss is only activated once the offset is reached. Until then, the stoploss remains at the configured `stoploss`.
This option can be used with or without `trailing_stop_positive`, but uses `trailing_stop_positive_offset` as offset.
``` python
@@ -203,7 +225,6 @@ If price moves 1% - you've lost 10$ of your own capital - therfore stoploss will
Make sure to be aware of this, and avoid using too tight stoploss (at 10x leverage, 10% risk may be too little to allow the trade to "breath" a little).
## Changing stoploss on open trades
A stoploss on an open trade can be changed by changing the value in the configuration or strategy and use the `/reload_config` command (alternatively, completely stopping and restarting the bot also works).

View File

@@ -1,5 +1,5 @@
""" Freqtrade bot """
__version__ = 'develop'
__version__ = '2022.6'
if 'dev' in __version__:
try:

View File

@@ -24,7 +24,7 @@ def start_hyperopt_list(args: Dict[str, Any]) -> None:
print_colorized = config.get('print_colorized', False)
print_json = config.get('print_json', False)
export_csv = config.get('export_csv', None)
export_csv = config.get('export_csv')
no_details = config.get('hyperopt_list_no_details', False)
no_header = False

View File

@@ -129,7 +129,7 @@ class Configuration:
# Default to in-memory db for dry_run if not specified
config['db_url'] = constants.DEFAULT_DB_DRYRUN_URL
else:
if not config.get('db_url', None):
if not config.get('db_url'):
config['db_url'] = constants.DEFAULT_DB_PROD_URL
logger.info('Dry run is disabled')
@@ -182,7 +182,7 @@ class Configuration:
config['user_data_dir'] = create_userdata_dir(config['user_data_dir'], create_dir=False)
logger.info('Using user-data directory: %s ...', config['user_data_dir'])
config.update({'datadir': create_datadir(config, self.args.get('datadir', None))})
config.update({'datadir': create_datadir(config, self.args.get('datadir'))})
logger.info('Using data directory: %s ...', config.get('datadir'))
if self.args.get('exportfilename'):
@@ -221,7 +221,7 @@ class Configuration:
if config.get('max_open_trades') == -1:
config['max_open_trades'] = float('inf')
if self.args.get('stake_amount', None):
if self.args.get('stake_amount'):
# Convert explicitly to float to support CLI argument for both unlimited and value
try:
self.args['stake_amount'] = float(self.args['stake_amount'])

View File

@@ -387,7 +387,7 @@ class Exchange:
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)
or market.get('precision', {}).get('price') > 1e-11)
and ((self.trading_mode == TradingMode.SPOT and self.market_is_spot(market))
or (self.trading_mode == TradingMode.MARGIN and self.market_is_margin(market))
or (self.trading_mode == TradingMode.FUTURES and self.market_is_future(market)))
@@ -537,7 +537,7 @@ class Exchange:
# The internal info array is different for each particular market,
# its contents depend on the exchange.
# It can also be a string or similar ... so we need to verify that first.
elif (isinstance(self.markets[pair].get('info', None), dict)
elif (isinstance(self.markets[pair].get('info'), dict)
and self.markets[pair].get('info', {}).get('prohibitedIn', False)):
# Warn users about restricted pairs in whitelist.
# We cannot determine reliably if Users are affected.

View File

@@ -67,7 +67,7 @@ class FreqtradeBot(LoggingMixin):
self.exchange = ExchangeResolver.load_exchange(self.config['exchange']['name'], self.config)
init_db(self.config.get('db_url', None))
init_db(self.config['db_url'])
self.wallets = Wallets(self.config, self.exchange)
@@ -648,7 +648,7 @@ class FreqtradeBot(LoggingMixin):
)
order_obj = Order.parse_from_ccxt_object(order, pair, side)
order_id = order['id']
order_status = order.get('status', None)
order_status = order.get('status')
logger.info(f"Order #{order_id} was created for {pair} and status is {order_status}.")
# we assume the order is executed at the price requested
@@ -959,6 +959,29 @@ class FreqtradeBot(LoggingMixin):
logger.debug(f'Found no {exit_signal_type} signal for %s.', trade)
return False
def _check_and_execute_exit(self, trade: Trade, exit_rate: float,
enter: bool, exit_: bool, exit_tag: Optional[str]) -> bool:
"""
Check and execute trade exit
"""
exits: List[ExitCheckTuple] = self.strategy.should_exit(
trade,
exit_rate,
datetime.now(timezone.utc),
enter=enter,
exit_=exit_,
force_stoploss=self.edge.stoploss(trade.pair) if self.edge else 0
)
for should_exit in exits:
if should_exit.exit_flag:
exit_tag1 = exit_tag if should_exit.exit_type == ExitType.EXIT_SIGNAL else None
logger.info(f'Exit for {trade.pair} detected. Reason: {should_exit.exit_type}'
f'{f" Tag: {exit_tag1}" if exit_tag1 is not None else ""}')
exited = self.execute_trade_exit(trade, exit_rate, should_exit, exit_tag=exit_tag1)
if exited:
return True
return False
def create_stoploss_order(self, trade: Trade, stop_price: float) -> bool:
"""
Abstracts creating stoploss orders from the logic.
@@ -1110,28 +1133,6 @@ class FreqtradeBot(LoggingMixin):
logger.warning(f"Could not create trailing stoploss order "
f"for pair {trade.pair}.")
def _check_and_execute_exit(self, trade: Trade, exit_rate: float,
enter: bool, exit_: bool, exit_tag: Optional[str]) -> bool:
"""
Check and execute trade exit
"""
exits: List[ExitCheckTuple] = self.strategy.should_exit(
trade,
exit_rate,
datetime.now(timezone.utc),
enter=enter,
exit_=exit_,
force_stoploss=self.edge.stoploss(trade.pair) if self.edge else 0
)
for should_exit in exits:
if should_exit.exit_flag:
logger.info(f'Exit for {trade.pair} detected. Reason: {should_exit.exit_type}'
f'{f" Tag: {exit_tag}" if exit_tag is not None else ""}')
exited = self.execute_trade_exit(trade, exit_rate, should_exit, exit_tag=exit_tag)
if exited:
return True
return False
def manage_open_orders(self) -> None:
"""
Management of open orders on exchange. Unfilled orders might be cancelled if timeout
@@ -1541,7 +1542,7 @@ class FreqtradeBot(LoggingMixin):
'open_date': trade.open_date,
'close_date': trade.close_date or datetime.utcnow(),
'stake_currency': self.config['stake_currency'],
'fiat_currency': self.config.get('fiat_display_currency', None),
'fiat_currency': self.config.get('fiat_display_currency'),
}
if 'fiat_display_currency' in self.config:
@@ -1652,7 +1653,7 @@ class FreqtradeBot(LoggingMixin):
if order['status'] in constants.NON_OPEN_EXCHANGE_STATES:
# If a entry order was closed, force update on stoploss on exchange
if order.get('side', None) == trade.entry_side:
if order.get('side') == trade.entry_side:
trade = self.cancel_stoploss_on_exchange(trade)
# TODO: Margin will need to use interest_rate as well.
# interest_rate = self.exchange.get_interest_rate()

View File

@@ -87,7 +87,7 @@ class Backtesting:
self.exchange = ExchangeResolver.load_exchange(self._exchange_name, self.config)
self.dataprovider = DataProvider(self.config, self.exchange)
if self.config.get('strategy_list', None):
if self.config.get('strategy_list'):
for strat in list(self.config['strategy_list']):
stratconf = deepcopy(self.config)
stratconf['strategy'] = strat
@@ -189,6 +189,7 @@ class Backtesting:
self.strategy.order_types['stoploss_on_exchange'] = False
self.strategy.ft_bot_start()
strategy_safe_wrapper(self.strategy.bot_loop_start, supress_error=True)()
def _load_protections(self, strategy: IStrategy):
if self.config.get('enable_protections', False):
@@ -1140,8 +1141,6 @@ class Backtesting:
backtest_start_time = datetime.now(timezone.utc)
self._set_strategy(strat)
strategy_safe_wrapper(self.strategy.bot_loop_start, supress_error=True)()
# Use max_open_trades in backtesting, except --disable-max-market-positions is set
if self.config.get('use_max_market_positions', True):
# Must come from strategy config, as the strategy may modify this setting.

View File

@@ -455,7 +455,7 @@ class Hyperopt:
return self.opt.ask(n_points=n_points), [False for _ in range(n_points)]
def start(self) -> None:
self.random_state = self._set_random_state(self.config.get('hyperopt_random_state', None))
self.random_state = self._set_random_state(self.config.get('hyperopt_random_state'))
logger.info(f"Using optimizer random state: {self.random_state}")
self.hyperopt_table_header = -1
# Initialize spaces ...

View File

@@ -127,14 +127,14 @@ class HyperoptTools():
'only_profitable': config.get('hyperopt_list_profitable', False),
'filter_min_trades': config.get('hyperopt_list_min_trades', 0),
'filter_max_trades': config.get('hyperopt_list_max_trades', 0),
'filter_min_avg_time': config.get('hyperopt_list_min_avg_time', None),
'filter_max_avg_time': config.get('hyperopt_list_max_avg_time', None),
'filter_min_avg_profit': config.get('hyperopt_list_min_avg_profit', None),
'filter_max_avg_profit': config.get('hyperopt_list_max_avg_profit', None),
'filter_min_total_profit': config.get('hyperopt_list_min_total_profit', None),
'filter_max_total_profit': config.get('hyperopt_list_max_total_profit', None),
'filter_min_objective': config.get('hyperopt_list_min_objective', None),
'filter_max_objective': config.get('hyperopt_list_max_objective', None),
'filter_min_avg_time': config.get('hyperopt_list_min_avg_time'),
'filter_max_avg_time': config.get('hyperopt_list_max_avg_time'),
'filter_min_avg_profit': config.get('hyperopt_list_min_avg_profit'),
'filter_max_avg_profit': config.get('hyperopt_list_max_avg_profit'),
'filter_min_total_profit': config.get('hyperopt_list_min_total_profit'),
'filter_max_total_profit': config.get('hyperopt_list_max_total_profit'),
'filter_min_objective': config.get('hyperopt_list_min_objective'),
'filter_max_objective': config.get('hyperopt_list_max_objective'),
}
if not HyperoptTools._test_hyperopt_results_exist(results_file):
# No file found.

View File

@@ -30,7 +30,7 @@ class AgeFilter(IPairList):
self._symbolsCheckFailed = PeriodicCache(maxsize=1000, ttl=86_400)
self._min_days_listed = pairlistconfig.get('min_days_listed', 10)
self._max_days_listed = pairlistconfig.get('max_days_listed', None)
self._max_days_listed = pairlistconfig.get('max_days_listed')
candle_limit = exchange.ohlcv_candle_limit('1d', self._config['candle_type_def'])
if self._min_days_listed < 1:

View File

@@ -21,7 +21,7 @@ class PerformanceFilter(IPairList):
super().__init__(exchange, pairlistmanager, config, pairlistconfig, pairlist_pos)
self._minutes = pairlistconfig.get('minutes', 0)
self._min_profit = pairlistconfig.get('min_profit', None)
self._min_profit = pairlistconfig.get('min_profit')
@property
def needstickers(self) -> bool:

View File

@@ -27,7 +27,7 @@ class RangeStabilityFilter(IPairList):
self._days = pairlistconfig.get('lookback_days', 10)
self._min_rate_of_change = pairlistconfig.get('min_rate_of_change', 0.01)
self._max_rate_of_change = pairlistconfig.get('max_rate_of_change', None)
self._max_rate_of_change = pairlistconfig.get('max_rate_of_change')
self._refresh_period = pairlistconfig.get('refresh_period', 1440)
self._def_candletype = self._config['candle_type_def']

View File

@@ -28,7 +28,7 @@ class PairListManager(LoggingMixin):
self._blacklist = self._config['exchange'].get('pair_blacklist', [])
self._pairlist_handlers: List[IPairList] = []
self._tickers_needed = False
for pairlist_handler_config in self._config.get('pairlists', None):
for pairlist_handler_config in self._config.get('pairlists', []):
pairlist_handler = PairListResolver.load_pairlist(
pairlist_handler_config['method'],
exchange=exchange,

View File

@@ -282,7 +282,7 @@ def get_strategy(strategy: str, config=Depends(get_config)):
def list_available_pairs(timeframe: Optional[str] = None, stake_currency: Optional[str] = None,
candletype: Optional[CandleType] = None, config=Depends(get_config)):
dh = get_datahandler(config['datadir'], config.get('dataformat_ohlcv', None))
dh = get_datahandler(config['datadir'], config.get('dataformat_ohlcv'))
trading_mode: TradingMode = config.get('trading_mode', TradingMode.SPOT)
pair_interval = dh.ohlcv_get_available_data(config['datadir'], trading_mode)

View File

@@ -97,7 +97,7 @@ class RPC:
"""
self._freqtrade = freqtrade
self._config: Dict[str, Any] = freqtrade.config
if self._config.get('fiat_display_currency', None):
if self._config.get('fiat_display_currency'):
self._fiat_converter = CryptoToFiatConverter()
@staticmethod
@@ -566,7 +566,7 @@ class RPC:
else:
try:
pair = self._freqtrade.exchange.get_valid_pair_combination(coin, stake_currency)
rate = tickers.get(pair, {}).get('last', None)
rate = tickers.get(pair, {}).get('last')
if rate:
if pair.startswith(stake_currency) and not pair.endswith(stake_currency):
rate = 1.0 / rate

View File

@@ -259,7 +259,7 @@ class Telegram(RPCHandler):
f" {entry_side['entered'] if is_fill else entry_side['enter']} {msg['pair']}"
f" (#{msg['trade_id']})\n"
)
message += f"*Enter Tag:* `{msg['enter_tag']}`\n" if msg.get('enter_tag', None) else ""
message += f"*Enter Tag:* `{msg['enter_tag']}`\n" if msg.get('enter_tag') else ""
message += f"*Amount:* `{msg['amount']:.8f}`\n"
if msg.get('leverage') and msg.get('leverage', 1.0) != 1.0:
message += f"*Leverage:* `{msg['leverage']}`\n"
@@ -272,7 +272,7 @@ class Telegram(RPCHandler):
message += f"*Total:* `({round_coin_value(msg['stake_amount'], msg['stake_currency'])}"
if msg.get('fiat_currency', None):
if msg.get('fiat_currency'):
message += f", {round_coin_value(msg['stake_amount_fiat'], msg['fiat_currency'])}"
message += ")`"
@@ -288,7 +288,7 @@ class Telegram(RPCHandler):
msg['enter_tag'] = msg['enter_tag'] if "enter_tag" in msg.keys() else None
msg['emoji'] = self._get_sell_emoji(msg)
msg['leverage_text'] = (f"*Leverage:* `{msg['leverage']:.1f}`\n"
if msg.get('leverage', None) and msg.get('leverage', 1.0) != 1.0
if msg.get('leverage') and msg.get('leverage', 1.0) != 1.0
else "")
# Check if all sell properties are available.

View File

@@ -45,21 +45,21 @@ class Webhook(RPCHandler):
try:
whconfig = self._config['webhook']
if msg['type'] in [RPCMessageType.ENTRY]:
valuedict = whconfig.get('webhookentry', None)
valuedict = whconfig.get('webhookentry')
elif msg['type'] in [RPCMessageType.ENTRY_CANCEL]:
valuedict = whconfig.get('webhookentrycancel', None)
valuedict = whconfig.get('webhookentrycancel')
elif msg['type'] in [RPCMessageType.ENTRY_FILL]:
valuedict = whconfig.get('webhookentryfill', None)
valuedict = whconfig.get('webhookentryfill')
elif msg['type'] == RPCMessageType.EXIT:
valuedict = whconfig.get('webhookexit', None)
valuedict = whconfig.get('webhookexit')
elif msg['type'] == RPCMessageType.EXIT_FILL:
valuedict = whconfig.get('webhookexitfill', None)
valuedict = whconfig.get('webhookexitfill')
elif msg['type'] == RPCMessageType.EXIT_CANCEL:
valuedict = whconfig.get('webhookexitcancel', None)
valuedict = whconfig.get('webhookexitcancel')
elif msg['type'] in (RPCMessageType.STATUS,
RPCMessageType.STARTUP,
RPCMessageType.WARNING):
valuedict = whconfig.get('webhookstatus', None)
valuedict = whconfig.get('webhookstatus')
else:
raise NotImplementedError('Unknown message type: {}'.format(msg['type']))
if not valuedict:

View File

@@ -131,9 +131,9 @@ class Wallets:
if isinstance(balances[currency], dict):
self._wallets[currency] = Wallet(
currency,
balances[currency].get('free', None),
balances[currency].get('used', None),
balances[currency].get('total', None)
balances[currency].get('free'),
balances[currency].get('used'),
balances[currency].get('total')
)
# Remove currencies no longer in get_balances output
for currency in deepcopy(self._wallets):

View File

@@ -12,18 +12,18 @@ pre-commit==2.19.0
pytest==7.1.2
pytest-asyncio==0.18.3
pytest-cov==3.0.0
pytest-mock==3.7.0
pytest-mock==3.8.1
pytest-random-order==1.0.4
isort==5.10.1
# For datetime mocking
time-machine==2.7.0
time-machine==2.7.1
# Convert jupyter notebooks to markdown documents
nbconvert==6.5.0
# mypy types
types-cachetools==5.0.2
types-cachetools==5.2.1
types-filelock==3.2.7
types-requests==2.27.30
types-tabulate==0.8.9
types-python-dateutil==2.8.17
types-requests==2.28.0
types-tabulate==0.8.11
types-python-dateutil==2.8.18

View File

@@ -1,4 +1,4 @@
# Include all requirements to run the bot.
-r requirements.txt
plotly==5.8.2
plotly==5.9.0

View File

@@ -1,12 +1,12 @@
numpy==1.23.0
pandas==1.4.2
pandas==1.4.3
pandas-ta==0.3.14b
ccxt==1.88.15
ccxt==1.89.14
# Pin cryptography for now due to rust build errors with piwheels
cryptography==37.0.2
aiohttp==3.8.1
SQLAlchemy==1.4.37
SQLAlchemy==1.4.39
python-telegram-bot==13.12
arrow==1.2.2
cachetools==4.2.2
@@ -15,7 +15,7 @@ urllib3==1.26.9
jsonschema==4.6.0
TA-Lib==0.4.24
technical==1.3.0
tabulate==0.8.9
tabulate==0.8.10
pycoingecko==2.2.0
jinja2==3.1.2
tables==3.7.0
@@ -28,14 +28,14 @@ py_find_1st==1.1.5
# Load ticker files 30% faster
python-rapidjson==1.6
# Properly format api responses
orjson==3.7.2
orjson==3.7.3
# Notify systemd
sdnotify==0.3.2
# API Server
fastapi==0.78.0
uvicorn==0.17.6
uvicorn==0.18.1
pyjwt==2.4.0
aiofiles==0.8.0
psutil==5.9.1

View File

@@ -861,6 +861,7 @@ def test_in_strategy_auto_hyperopt(mocker, hyperopt_conf, tmpdir, fee) -> None:
hyperopt.backtesting.exchange.get_max_leverage = MagicMock(return_value=1.0)
assert isinstance(hyperopt.custom_hyperopt, HyperOptAuto)
assert isinstance(hyperopt.backtesting.strategy.buy_rsi, IntParameter)
assert hyperopt.backtesting.strategy.bot_loop_started is True
assert hyperopt.backtesting.strategy.buy_rsi.in_space is True
assert hyperopt.backtesting.strategy.buy_rsi.value == 35

View File

@@ -44,6 +44,11 @@ class HyperoptableStrategy(StrategyTestV2):
})
return prot
bot_loop_started = False
def bot_loop_start(self):
self.bot_loop_started = True
def bot_start(self, **kwargs) -> None:
"""
Parameters can also be defined here ...

View File

@@ -3951,9 +3951,9 @@ def test_ignore_roi_if_entry_signal(default_conf_usdt, limit_order, limit_order_
# Test if entry-signal is absent (should sell due to roi = true)
if is_short:
patch_get_signal(freqtrade, enter_long=False, exit_short=False)
patch_get_signal(freqtrade, enter_long=False, exit_short=False, exit_tag='something')
else:
patch_get_signal(freqtrade, enter_long=False, exit_long=False)
patch_get_signal(freqtrade, enter_long=False, exit_long=False, exit_tag='something')
assert freqtrade.handle_trade(trade) is True
assert trade.exit_reason == ExitType.ROI.value