Compare commits

..

1057 Commits

Author SHA1 Message Date
Matthias
a31045874e Merge pull request #8224 from freqtrade/new_release
New release 2023.2
2023-02-26 14:53:52 +01:00
Matthias
25724ef729 Version bump 2023.2 2023-02-25 16:02:36 +01:00
Matthias
46458bf5eb Merge branch 'stable' into new_release 2023-02-25 16:02:26 +01:00
Matthias
dc2cfee056 Don't request sorted candles from HitBTC.
Apparently hitBTC cannot properly handle this anymore.

closes #8214
2023-02-25 13:49:16 +01:00
Matthias
c6455c4131 Pin scikit-learn to <1.2.0 for conda as well
closes #8223
2023-02-25 13:39:48 +01:00
Matthias
3471f5204b Don't reuse variable 2023-02-24 14:34:41 +01:00
Matthias
521025037d Merge pull request #8203 from freqtrade/add-bufer-train-data-candles
Add buffer_train_data_candles feature
2023-02-24 13:25:18 +01:00
Matthias
ac2a2512ef Merge pull request #8210 from freqtrade/clean-data-drawer
Allow user to control number of historical model files
2023-02-24 13:19:38 +01:00
Robert Caulk
607d90ca5d Merge pull request #8215 from freqtrade/fix-freqai-index
fix link in freqai index.md
2023-02-24 12:38:56 +01:00
robcaulk
c283e22325 fix purge_old_models description in parameter table 2023-02-24 10:54:43 +01:00
robcaulk
5ac4b81a5d fix link in freqai index.md 2023-02-24 10:50:39 +01:00
Matthias
34c42be74f Fix minor stylistic errors 2023-02-23 20:06:10 +01:00
Matthias
659140e190 Add bt-error to UI backtest method. 2023-02-23 20:06:10 +01:00
Matthias
63e5d33028 Better handle backtest errors 2023-02-23 20:06:10 +01:00
Matthias
2fed924a0d Merge pull request #8211 from TheJoeSchr/refactor-1
refactor(if-gate): use temp variable instead of if-gate
2023-02-23 18:14:21 +01:00
Joe Schr
7d906fd4c2 refactor(if-gate): use temp variable instead of if-gate 2023-02-23 10:58:43 +01:00
Matthias
cdc96136bc Merge pull request #8207 from freqtrade/add-freqai-disclaimer
add imposter disclaimer to FreqAI front page
2023-02-23 06:49:18 +01:00
Matthias
23a71680de Update Doc-box typo 2023-02-23 06:29:58 +01:00
robcaulk
150b7f9c87 lighten the disclaimer message 2023-02-22 22:33:41 +01:00
robcaulk
b8f011a2ab give users ability to decide how many models to keep in dry/live 2023-02-22 22:27:56 +01:00
robcaulk
9633081c31 remove remnants of follower, clean data-drawer, improve doc 2023-02-22 22:01:41 +01:00
Matthias
0f878daa98 Remove some too generic noqa statements 2023-02-22 19:56:32 +01:00
Matthias
01d51aa979 Add necesary noqa statements 2023-02-22 19:56:32 +01:00
Matthias
f8fa5bd969 Fix gone wrong noqa ... 2023-02-22 19:56:32 +01:00
Matthias
18bbfa10e5 Reduce amount of variables for API backtesting 2023-02-22 19:56:32 +01:00
Matthias
ff1258fd20 Better handle random UI backtest errors 2023-02-22 19:56:32 +01:00
Matthias
e56bf067c4 Merge pull request #8205 from amalysh/develop
* fixed filename in model_exists
2023-02-22 17:43:57 +01:00
robcaulk
3fbbc57a37 add imposter disclaimer to FreqAI front page 2023-02-22 17:08:30 +01:00
Alexander Malysh
070a7efd73 * fixed filename in model_exists 2023-02-22 14:52:20 +01:00
robcaulk
2b5c11c7b4 allow users to buffer train data with buffer_train_data_candles parameter 2023-02-21 21:08:34 +01:00
Matthias
62e120a602 Remove special treatment of cryptography for raspberries 2023-02-21 20:34:55 +01:00
Matthias
48ecc7f6dc Update freqai-reinforcement-learning docs
closes #8199
2023-02-21 19:55:32 +01:00
Matthias
43962476aa Remove non-working links, update links to https 2023-02-21 19:53:09 +01:00
Matthias
a4a3d27ac6 Improve FAQ page 2023-02-21 19:52:22 +01:00
Matthias
f4bd424226 Remove deprecated ubuntu image
Follows anouncement in https://github.blog/changelog/2022-08-09-github-actions-the-ubuntu-18-04-actions-runner-image-is-being-deprecated-and-will-be-removed-by-12-1-22/
2023-02-21 18:29:00 +01:00
Matthias
af137188f4 Update wrong FAQ entry 2023-02-21 18:05:20 +01:00
Matthias
352f4962da Merge pull request #8198 from AchmadFathoni/develop
Fix outdated systemd related exception text.
2023-02-20 11:05:42 +01:00
Achmad Fathoni
789c867c8f Fix outdated systemd related exception text. 2023-02-20 16:30:23 +07:00
Matthias
4f794aae61 Merge pull request #8191 from freqtrade/dependabot/pip/develop/mkdocs-material-9.0.13
Bump mkdocs-material from 9.0.12 to 9.0.13
2023-02-20 08:06:53 +01:00
Matthias
bf6560e45b Merge pull request #8194 from freqtrade/dependabot/pip/develop/types-requests-2.28.11.13
Bump types-requests from 2.28.11.12 to 2.28.11.13
2023-02-20 08:06:37 +01:00
Matthias
ccf4fbed60 Merge pull request #8192 from freqtrade/dependabot/pip/develop/ccxt-2.8.17
Bump ccxt from 2.7.93 to 2.8.17
2023-02-20 07:11:49 +01:00
Matthias
250faf012d Bump types-requests for pre-commit 2023-02-20 06:55:58 +01:00
Matthias
3a9ffdf135 Merge pull request #8190 from freqtrade/dependabot/pip/develop/fastapi-0.92.0
Bump fastapi from 0.91.0 to 0.92.0
2023-02-20 06:55:17 +01:00
Matthias
ec1991d165 Merge pull request #8189 from freqtrade/dependabot/pip/develop/scipy-1.10.1
Bump scipy from 1.10.0 to 1.10.1
2023-02-20 06:54:16 +01:00
Matthias
4e1f5354fe Merge pull request #8196 from freqtrade/dependabot/pip/develop/mypy-1.0.1
Bump mypy from 1.0.0 to 1.0.1
2023-02-20 06:53:28 +01:00
dependabot[bot]
0cd28e2cab Bump mypy from 1.0.0 to 1.0.1
Bumps [mypy](https://github.com/python/mypy) from 1.0.0 to 1.0.1.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v1.0.0...v1.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-20 03:58:03 +00:00
dependabot[bot]
eb08ef6ced Bump types-requests from 2.28.11.12 to 2.28.11.13
Bumps [types-requests](https://github.com/python/typeshed) from 2.28.11.12 to 2.28.11.13.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-20 03:57:41 +00:00
dependabot[bot]
a4e69574d3 Bump ccxt from 2.7.93 to 2.8.17
Bumps [ccxt](https://github.com/ccxt/ccxt) from 2.7.93 to 2.8.17.
- [Release notes](https://github.com/ccxt/ccxt/releases)
- [Changelog](https://github.com/ccxt/ccxt/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ccxt/ccxt/compare/2.7.93...2.8.17)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-20 03:57:17 +00:00
dependabot[bot]
c85fc6c8ca Bump mkdocs-material from 9.0.12 to 9.0.13
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.0.12 to 9.0.13.
- [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/9.0.12...9.0.13)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-20 03:57:10 +00:00
dependabot[bot]
f19128ad21 Bump fastapi from 0.91.0 to 0.92.0
Bumps [fastapi](https://github.com/tiangolo/fastapi) from 0.91.0 to 0.92.0.
- [Release notes](https://github.com/tiangolo/fastapi/releases)
- [Commits](https://github.com/tiangolo/fastapi/compare/0.91.0...0.92.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-20 03:56:55 +00:00
dependabot[bot]
2ef656fac0 Bump scipy from 1.10.0 to 1.10.1
Bumps [scipy](https://github.com/scipy/scipy) from 1.10.0 to 1.10.1.
- [Release notes](https://github.com/scipy/scipy/releases)
- [Commits](https://github.com/scipy/scipy/compare/v1.10.0...v1.10.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-20 03:56:50 +00:00
Matthias
e9c64c5839 Update dependency to cysystemd
closes #8187
2023-02-19 19:30:27 +01:00
Matthias
b0ec35d526 Merge pull request #7904 from freqtrade/feat/shuffle_after_split
add shuffle_after_split option
2023-02-19 15:03:04 +01:00
Matthias
f89b63b0c5 Fix dry-run stoploss orders filling "in place" after restart. 2023-02-18 19:25:11 +01:00
Matthias
2c0fbd8500 Simplify test slightly 2023-02-18 18:07:35 +01:00
Matthias
c4ec4db050 Merge pull request #8183 from th0rntwig/improve-freqai-docs
fix minor typos
2023-02-17 07:14:39 +01:00
Matthias
31c7b3e136 Update binance leverage tiers 2023-02-17 06:37:03 +01:00
Matthias
22700527ac Convert limit orders to market orders if they cross a threshold
closes #7786
2023-02-17 06:37:03 +01:00
Matthias
9600039686 Update dry-run fill method naming 2023-02-17 06:37:03 +01:00
thorntwig
35fe37199d fix minor typos 2023-02-16 20:04:42 +01:00
robcaulk
351c5fbf7f add shuffle_after_split to conftest 2023-02-16 19:48:22 +01:00
Robert Caulk
f68543b151 Merge pull request #8182 from freqtrade/generalize-model-exists
generalize model_exists() for RL and Keras
2023-02-16 19:41:07 +01:00
robcaulk
be85ef2707 add documentation for shuffle_after_split, add to constants 2023-02-16 18:50:11 +01:00
robcaulk
b6a741b421 merge develop into feat/shuffle_after_split 2023-02-16 18:46:01 +01:00
robcaulk
36d65e00f9 generalize model_exists() for RL and Keras 2023-02-16 18:33:40 +01:00
Matthias
a2e1389943 Update Binance leverage code 2023-02-16 18:06:34 +01:00
Matthias
8ef110cc5f Rename ob variable to orderbook 2023-02-16 06:38:58 +01:00
Matthias
de7d274fcf Pass orderbook to dry-run fill logic 2023-02-16 06:38:58 +01:00
Matthias
7c10921564 Improve Orderbook typing to align for diff. exchanges 2023-02-16 06:38:58 +01:00
Matthias
a11f081d2d Merge pull request #8176 from freqtrade/robcaulk-patch-1
Update freqai.md
2023-02-16 06:14:56 +01:00
Robert Caulk
020c9a5cec Update freqai.md 2023-02-15 21:54:45 +01:00
Matthias
ecff21ac21 type Orderbook 2023-02-15 07:01:36 +01:00
Matthias
3397e47ccf Rename stoploss() to create_stoploss() 2023-02-14 20:42:08 +01:00
Matthias
6e55a873b3 Rename edge.stoploss to get_stoploss
this will make it clear that it's different from
2023-02-14 07:18:11 +01:00
Matthias
bddec476f9 Fix missing typehint in hyper.py 2023-02-13 20:13:26 +01:00
Matthias
cdd324d0a9 Rename stoploss_reached to ft_stoploss_reached 2023-02-13 20:08:54 +01:00
Matthias
ce7d24f529 Extract ft_stoploss_adjust to seperate method 2023-02-13 19:53:04 +01:00
Matthias
a0e2f98086 Merge pull request #8164 from freqtrade/dependabot/pip/develop/tensorboard-2.12.0
Bump tensorboard from 2.11.2 to 2.12.0
2023-02-13 19:34:14 +01:00
Matthias
69d5459460 Improve stop behavior in SIGTERM cases (docker). 2023-02-13 18:25:15 +01:00
Matthias
aafaff877b Merge pull request #8170 from freqtrade/dependabot/pip/develop/ccxt-2.7.93
Bump ccxt from 2.7.80 to 2.7.93
2023-02-13 18:17:29 +01:00
dependabot[bot]
9061c04f1d Bump ccxt from 2.7.80 to 2.7.93
Bumps [ccxt](https://github.com/ccxt/ccxt) from 2.7.80 to 2.7.93.
- [Release notes](https://github.com/ccxt/ccxt/releases)
- [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg)
- [Commits](https://github.com/ccxt/ccxt/compare/2.7.80...2.7.93)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 16:09:57 +00:00
Matthias
9a2f6d2416 Merge pull request #8165 from freqtrade/dependabot/pip/develop/aiofiles-23.1.0
Bump aiofiles from 22.1.0 to 23.1.0
2023-02-13 09:50:11 +01:00
Matthias
b5121d3f4c Merge pull request #8166 from freqtrade/dependabot/pip/develop/aiohttp-3.8.4
Bump aiohttp from 3.8.3 to 3.8.4
2023-02-13 09:49:56 +01:00
Matthias
f3a6897870 Bump Docker images to latest minor version 2023-02-13 07:12:46 +01:00
Matthias
f16fd0ad23 Reenable binanceus active test 2023-02-13 07:12:46 +01:00
dependabot[bot]
f681ee7942 Bump aiohttp from 3.8.3 to 3.8.4
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.8.3 to 3.8.4.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.8.3...v3.8.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 06:11:49 +00:00
dependabot[bot]
50a9df9b29 Bump aiofiles from 22.1.0 to 23.1.0
Bumps [aiofiles](https://github.com/Tinche/aiofiles) from 22.1.0 to 23.1.0.
- [Release notes](https://github.com/Tinche/aiofiles/releases)
- [Commits](https://github.com/Tinche/aiofiles/compare/v22.1.0...v23.1.0)

---
updated-dependencies:
- dependency-name: aiofiles
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 06:11:37 +00:00
dependabot[bot]
2a87ad044d Bump tensorboard from 2.11.2 to 2.12.0
Bumps [tensorboard](https://github.com/tensorflow/tensorboard) from 2.11.2 to 2.12.0.
- [Release notes](https://github.com/tensorflow/tensorboard/releases)
- [Changelog](https://github.com/tensorflow/tensorboard/blob/master/RELEASE.md)
- [Commits](https://github.com/tensorflow/tensorboard/compare/2.11.2...2.12.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 06:11:33 +00:00
Matthias
a573976406 Merge pull request #8158 from freqtrade/dependabot/pip/develop/types-requests-2.28.11.12
Bump types-requests from 2.28.11.8 to 2.28.11.12
2023-02-13 07:09:58 +01:00
Matthias
0b5b8e4c97 Merge pull request #8163 from freqtrade/dependabot/pip/develop/fastapi-0.91.0
Bump fastapi from 0.89.1 to 0.91.0
2023-02-13 07:09:44 +01:00
Matthias
ee158c1f55 Merge pull request #8162 from freqtrade/dependabot/pip/develop/mypy-1.0.0
Bump mypy from 0.991 to 1.0.0
2023-02-13 07:08:53 +01:00
Matthias
bf242ac4a2 Merge pull request #8156 from freqtrade/dependabot/pip/develop/mkdocs-material-9.0.12
Bump mkdocs-material from 9.0.11 to 9.0.12
2023-02-13 06:39:34 +01:00
Matthias
a800c19c14 Merge pull request #8157 from freqtrade/dependabot/pip/develop/orjson-3.8.6
Bump orjson from 3.8.5 to 3.8.6
2023-02-13 06:37:39 +01:00
Matthias
d14283b0e7 types-requests - precommit 2023-02-13 06:22:13 +01:00
dependabot[bot]
9faa926803 Bump fastapi from 0.89.1 to 0.91.0
Bumps [fastapi](https://github.com/tiangolo/fastapi) from 0.89.1 to 0.91.0.
- [Release notes](https://github.com/tiangolo/fastapi/releases)
- [Commits](https://github.com/tiangolo/fastapi/compare/0.89.1...0.91.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 03:58:55 +00:00
dependabot[bot]
48c331785c Bump mypy from 0.991 to 1.0.0
Bumps [mypy](https://github.com/python/mypy) from 0.991 to 1.0.0.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.991...v1.0.0)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 03:58:34 +00:00
dependabot[bot]
bbb62c8a4b Bump types-requests from 2.28.11.8 to 2.28.11.12
Bumps [types-requests](https://github.com/python/typeshed) from 2.28.11.8 to 2.28.11.12.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 03:57:16 +00:00
dependabot[bot]
b05999f6d5 Bump orjson from 3.8.5 to 3.8.6
Bumps [orjson](https://github.com/ijl/orjson) from 3.8.5 to 3.8.6.
- [Release notes](https://github.com/ijl/orjson/releases)
- [Changelog](https://github.com/ijl/orjson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ijl/orjson/compare/3.8.5...3.8.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 03:57:11 +00:00
dependabot[bot]
ee209e3b44 Bump mkdocs-material from 9.0.11 to 9.0.12
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.0.11 to 9.0.12.
- [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/9.0.11...9.0.12)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 03:56:56 +00:00
Matthias
b3fbb263ce Merge pull request #8152 from Shadyzpop/patch-1
Typo on freqai docs
2023-02-11 20:22:16 +01:00
Shadyzpop
b95ff827d3 Typo on freqai docs
1. `a the` - there is an extra "a" before `the features`
2. `historic` - it should be "historical" to match the correct adjective form.
2023-02-11 17:12:57 +03:00
Matthias
a3b4678ad6 stoploss_price_type for gate 2023-02-11 13:02:55 +01:00
Matthias
a2759b495b Merge pull request #8149 from freqtrade/gate_rename
Update gateio terminology to Gate
2023-02-11 12:40:58 +01:00
Matthias
bedd3688d0 Properly format proxy configuration 2023-02-11 12:37:40 +01:00
Matthias
c229ba97a9 Update gateio terminology to Gate 2023-02-11 08:15:11 +01:00
Matthias
07e6932a17 Reenable longrun test mark 2023-02-11 08:14:55 +01:00
Matthias
0713fc6a6a Merge pull request #8148 from stash86/bt-metrics
Add explicit warning that supported price types gonna differ
2023-02-11 08:14:23 +01:00
Stefano Ariestasia
73992dde8d Add explicit warning that supported price types gonna differ on each exchanges 2023-02-11 11:15:31 +09:00
Matthias
42c76d9e0c Merge pull request #8147 from freqtrade/add-pair-to-env
Add pair to environment for access inside calculate_reward
2023-02-10 19:38:10 +01:00
Matthias
45e24d21d3 Bump ccxt to 2.7.78
closes #8141
2023-02-10 19:35:45 +01:00
Matthias
f440d66210 Add sample_order for gate 2023-02-10 18:12:21 +01:00
robcaulk
8873a565ee expose raw features to the environment for use in calculate_reward 2023-02-10 15:48:18 +01:00
robcaulk
154b6711b3 use function level noqa ignore 2023-02-10 15:26:17 +01:00
robcaulk
4fc0edb8b7 add pair to environment for access inside calculate_reward 2023-02-10 14:45:50 +01:00
Matthias
d47d8c135b Add windows wheel for ta-lib on python 3.11 2023-02-10 07:17:12 +01:00
Matthias
22cbc16238 Merge pull request #8120 from freqtrade/fut/stop_price_type
stoploss price type
2023-02-10 07:02:25 +01:00
Matthias
eab724fe54 Merge branch 'develop' into fut/stop_price_type 2023-02-09 20:02:59 +01:00
Matthias
8d156b2770 Bump ccxt to 2.7.66
closes  #8132
2023-02-08 20:35:24 +01:00
Matthias
3d22ad36b8 Show Config should contain stoploss-on-exchange status 2023-02-08 07:08:42 +01:00
Matthias
102c1e799c realign binance set_leverage override 2023-02-08 07:08:42 +01:00
Matthias
980ffa6bfb Add test for binance rounding leverage 2023-02-08 07:08:42 +01:00
Matthias
997df2032e Add response_log for set_leverage 2023-02-08 07:08:42 +01:00
Matthias
d19ee9c95f Update okx position mode terminology 2023-02-08 07:08:42 +01:00
Matthias
e2d81b0ce0 Skip binanceus ccxt test 2023-02-08 07:08:42 +01:00
Matthias
c15e10fe1f Improve logic for initially placed stoploss 2023-02-08 07:08:42 +01:00
Matthias
2b0e281113 Merge pull request #8136 from freqtrade/dependabot/pip/cryptography-39.0.1
Bump cryptography from 38.0.1 to 39.0.1
2023-02-08 06:33:49 +01:00
dependabot[bot]
67a2cd7086 Bump cryptography from 38.0.1 to 39.0.1
Bumps [cryptography](https://github.com/pyca/cryptography) from 38.0.1 to 39.0.1.
- [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/38.0.1...39.0.1)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-08 04:07:21 +00:00
Matthias
5a61e076d7 Remove unused import 2023-02-07 19:19:59 +01:00
Matthias
953be8a7f8 Split validate_order_types to 2 functions to allow selective application 2023-02-07 18:00:44 +01:00
Matthias
8c0c2496c2 Temporarily disable gate advanced stop orders 2023-02-07 07:13:57 +01:00
Matthias
e8dc3dd59a Merge pull request #8126 from freqtrade/dependabot/pip/develop/types-cachetools-5.3.0.0
Bump types-cachetools from 5.2.1 to 5.3.0.0
2023-02-07 06:21:03 +01:00
Matthias
81619fb4a0 Properly use sqlalchemy column types 2023-02-06 19:51:51 +01:00
Matthias
82dad7ab17 Merge pull request #8086 from freqtrade/feat/cancel_order
Cancel open orders through UI/telegram
2023-02-06 19:43:21 +01:00
Matthias
a6adcb485e Bump several pre-commit hooks versions 2023-02-06 19:34:30 +01:00
Matthias
be335c401d Merge pull request #8125 from freqtrade/dependabot/pip/develop/ccxt-2.7.45
Bump ccxt from 2.7.12 to 2.7.45
2023-02-06 19:24:23 +01:00
Matthias
b6eb1f9395 Bump pre-commit 2023-02-06 07:09:59 +01:00
Matthias
7f5a624cfd Merge pull request #8127 from freqtrade/dependabot/pip/develop/numpy-1.24.2
Bump numpy from 1.24.1 to 1.24.2
2023-02-06 07:08:27 +01:00
Matthias
b215329456 Merge pull request #8128 from freqtrade/dependabot/pip/develop/pymdown-extensions-9.9.2
Bump pymdown-extensions from 9.9.1 to 9.9.2
2023-02-06 07:07:47 +01:00
dependabot[bot]
c6601cbd89 Bump pymdown-extensions from 9.9.1 to 9.9.2
Bumps [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions) from 9.9.1 to 9.9.2.
- [Release notes](https://github.com/facelessuser/pymdown-extensions/releases)
- [Commits](https://github.com/facelessuser/pymdown-extensions/compare/9.9.1...9.9.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-06 03:01:25 +00:00
dependabot[bot]
f96cb47727 Bump numpy from 1.24.1 to 1.24.2
Bumps [numpy](https://github.com/numpy/numpy) from 1.24.1 to 1.24.2.
- [Release notes](https://github.com/numpy/numpy/releases)
- [Changelog](https://github.com/numpy/numpy/blob/main/doc/RELEASE_WALKTHROUGH.rst)
- [Commits](https://github.com/numpy/numpy/compare/v1.24.1...v1.24.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-06 03:01:17 +00:00
dependabot[bot]
365522f5c8 Bump types-cachetools from 5.2.1 to 5.3.0.0
Bumps [types-cachetools](https://github.com/python/typeshed) from 5.2.1 to 5.3.0.0.
- [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>
2023-02-06 03:00:52 +00:00
dependabot[bot]
8dde7ab6b8 Bump ccxt from 2.7.12 to 2.7.45
Bumps [ccxt](https://github.com/ccxt/ccxt) from 2.7.12 to 2.7.45.
- [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/2.7.12...2.7.45)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-06 03:00:49 +00:00
Matthias
e964377edf Add new field to full config 2023-02-05 14:58:12 +01:00
Matthias
d904e91663 Add documentation for new setting 2023-02-05 14:55:11 +01:00
Matthias
61ba1a0dc7 Pin telegram in conda environment to <20
closes #8111
2023-02-05 14:39:20 +01:00
Matthias
48d78d8df9 Merge pull request #8116 from freqtrade/dependabot/pip/develop/technical-1.4.0
Bump technical from 1.3.0 to 1.4.0
2023-02-05 13:16:23 +01:00
Matthias
797993d0b7 Merge pull request #8118 from freqtrade/dependabot/pip/develop/isort-5.12.0
Bump isort from 5.11.4 to 5.12.0
2023-02-05 13:15:37 +01:00
Matthias
79d279b99b Merge pull request #8114 from freqtrade/dependabot/pip/develop/plotly-5.13.0
Bump plotly from 5.11.0 to 5.13.0
2023-02-05 12:43:46 +01:00
Matthias
a577d6ab36 Merge pull request #8112 from freqtrade/dependabot/pip/develop/mkdocs-material-9.0.11
Bump mkdocs-material from 9.0.8 to 9.0.11
2023-02-05 12:42:58 +01:00
Matthias
389e576b3e Merge pull request #8113 from freqtrade/dependabot/pip/develop/nbconvert-7.2.9
Bump nbconvert from 7.2.8 to 7.2.9
2023-02-05 12:42:17 +01:00
Matthias
47f47a33e3 Merge pull request #8115 from freqtrade/dependabot/pip/develop/pre-commit-3.0.4
Bump pre-commit from 2.21.0 to 3.0.4
2023-02-05 12:41:47 +01:00
Matthias
b8a527e4a0 Add gateio price type field 2023-02-05 10:46:24 +01:00
Matthias
3497de3dd5 Add more validation 2023-02-05 10:38:58 +01:00
Matthias
cf9e99b8e1 Add tests for ordertype validation 2023-02-05 10:38:58 +01:00
Matthias
2738c37845 Test stoploss validation ... 2023-02-05 10:38:58 +01:00
Matthias
c4fc811619 Add stop_price_type support (futures only!). 2023-02-05 10:38:58 +01:00
Matthias
a9241f61f9 Add Price Type Enum 2023-02-05 10:38:58 +01:00
dependabot[bot]
e38e41ab97 Bump isort from 5.11.4 to 5.12.0
Bumps [isort](https://github.com/pycqa/isort) from 5.11.4 to 5.12.0.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.11.4...5.12.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-05 09:20:10 +00:00
dependabot[bot]
e3f0e66b9a Bump technical from 1.3.0 to 1.4.0
Bumps [technical](https://github.com/freqtrade/technical) from 1.3.0 to 1.4.0.
- [Release notes](https://github.com/freqtrade/technical/releases)
- [Commits](https://github.com/freqtrade/technical/compare/1.3.0...1.4.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-05 09:19:44 +00:00
dependabot[bot]
b80d196d56 Bump pre-commit from 2.21.0 to 3.0.4
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.21.0 to 3.0.4.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v2.21.0...v3.0.4)

---
updated-dependencies:
- dependency-name: pre-commit
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-05 09:19:39 +00:00
dependabot[bot]
c61995aad9 Bump plotly from 5.11.0 to 5.13.0
Bumps [plotly](https://github.com/plotly/plotly.py) from 5.11.0 to 5.13.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.11.0...v5.13.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-05 09:19:31 +00:00
dependabot[bot]
34711eb683 Bump nbconvert from 7.2.8 to 7.2.9
Bumps [nbconvert](https://github.com/jupyter/nbconvert) from 7.2.8 to 7.2.9.
- [Release notes](https://github.com/jupyter/nbconvert/releases)
- [Changelog](https://github.com/jupyter/nbconvert/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jupyter/nbconvert/compare/v7.2.8...v7.2.9)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-05 09:19:25 +00:00
dependabot[bot]
5ed06cd79b Bump mkdocs-material from 9.0.8 to 9.0.11
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.0.8 to 9.0.11.
- [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/9.0.8...9.0.11)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-05 09:19:18 +00:00
Matthias
a7fec1f871 Merge pull request #8109 from freqtrade/add-metadata-to-feature-engineering
Pass metadata dictionary to feature_engineering_* and set_freqai_targets()
2023-02-05 09:56:21 +01:00
Matthias
801714a588 Update function signatures in all templates
add typehints to help the user's editor suggest the right things.
2023-02-04 20:04:16 +01:00
robcaulk
0dd2472385 add metadata param to docstrings 2023-02-04 16:56:36 +01:00
robcaulk
e569f6f6df add explicit metadata argument to example strat, include it with backtesting 2023-02-04 16:53:17 +01:00
robcaulk
5da60b718d pass metadata dictionary to feature_engineering_* and set_freqai_targets functions. Add doc 2023-02-04 13:47:11 +01:00
Matthias
55850a5ccd Skip orders when correlated trade was deleted.
closes #8107
2023-02-04 08:39:25 +01:00
Matthias
7991124794 Merge pull request #8102 from TheJoeSchr/develop
setup.sh: checks if git directory is dirty before bothering user with…
2023-02-03 16:56:52 +01:00
Joe Schr
02c0f91f4d fix: removes duplicated if branch 2023-02-03 16:16:30 +01:00
Joe Schr
3fd6d72984 setup.sh: fix truty/falsy return of check_git_changes() 2023-02-03 08:52:26 +01:00
Matthias
3c4ff2e037 Merge pull request #8095 from freqtrade/remove-follow-mode
remove follow mode in favor of producer consumer
2023-02-03 07:02:56 +01:00
Matthias
ef1738fbf6 Remove follow_mode from docs 2023-02-02 19:30:59 +01:00
Matthias
618eb951d3 Add ft_bot_start to notebook docs
part of #8066
2023-02-02 19:26:48 +01:00
Joe Schr
330461cf1e setup.sh: checks if git directory is dirty before bothering user with potentially scary question 2023-02-02 17:00:07 +01:00
Matthias
e95eb220c5 Merge pull request #8101 from obseries/develop
[kucoin] manage kucoin numeric password passed as environment variabl…
2023-02-02 16:58:29 +01:00
Matthias
c093934c24 Merge pull request #8099 from raphaelstar/raphaelstar-patch-2
`order.amount` -> `order.safe_amount`
2023-02-02 16:28:04 +01:00
Luca Forni
b7787a9846 [kucoin] manage kucoin numeric password passed as environment variable as a string 2023-02-02 16:15:23 +01:00
raphaelstar
b4c3e1fd58 order.amount -> order.safe_amount 2023-02-02 15:52:27 +01:00
Matthias
300e9acd37 Merge pull request #8096 from raphaelstar/raphaelstar-patch-1
Make test for `None` explicit
2023-02-02 14:53:46 +01:00
raphaelstar
36f95fb35d Make test for None explicit
Make test for `None` explicit
2023-02-02 13:29:37 +01:00
robcaulk
ccb4efbe88 remove follow mode in favor of producer consumer 2023-02-02 11:40:23 +01:00
Matthias
1d6738778b Merge pull request #8088 from Ezrahel/patch-1
Update README.md
2023-02-02 10:22:09 +01:00
Ezrahel
ba7883f549 Update README.md 2023-02-02 03:02:52 +01:00
Matthias
ceaaac6c3a Improve install sequence to install ta-lib after user interactivity 2023-02-01 18:36:48 +00:00
Matthias
21618594b2 Update setup.sh queries to not ask redundant questions 2023-02-01 17:16:11 +00:00
Matthias
8c9de445e7 Merge pull request #8089 from freqtrade/dependabot/pip/setuptools-65.5.1
Bump setuptools from 65.5.0 to 65.5.1
2023-02-01 12:32:43 +01:00
Matthias
d8583ab6e6 Bump setuptools in setup.sh 2023-02-01 11:06:30 +00:00
dependabot[bot]
7569e72f55 Bump setuptools from 65.5.0 to 65.5.1
Bumps [setuptools](https://github.com/pypa/setuptools) from 65.5.0 to 65.5.1.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/CHANGES.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v65.5.0...v65.5.1)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-01 10:11:12 +00:00
Ezrahel
1e12e888d1 Update README.md 2023-02-01 11:06:32 +01:00
Matthias
fb742361e9 Merge pull request #8083 from leonardocustodio/patch-1
Gym aid
2023-02-01 11:05:38 +01:00
Matthias
322d4b5351 improve fix for setup.sh 2023-02-01 09:20:40 +00:00
Matthias
c1a34396d0 Merge branch 'develop' into feat/cancel_order 2023-02-01 07:06:17 +00:00
Matthias
72a98943b1 bybit: Add correct funding_fee_timeframe 2023-02-01 06:58:45 +01:00
Matthias
9bb376296d Update parse_order test 2023-01-31 20:59:55 +01:00
Matthias
839215c437 Fix Doc box error 2023-01-31 20:58:20 +01:00
Matthias
8a0fabed0e Ensure we don't overwrite valid values by invalid exchange responses 2023-01-31 20:55:11 +01:00
Matthias
680136f57d Add workaround patch for kucoin create_order returning empty
While the actual problem is caused by a ccxt change, the change itself makes sense.
once ccxt starts returning the correct status (open) for create-orders, we can remove the fix.

closes #8079
2023-01-31 20:46:34 +01:00
Matthias
448505fbfb Fix minor issue where amount could be empty in rest calls 2023-01-31 20:38:18 +01:00
Matthias
50d3b7bdef Add bybit sample order 2023-01-31 20:00:05 +01:00
Matthias
42f07e6ec2 Improve order_parse tests 2023-01-31 19:45:27 +01:00
Matthias
6012a55828 Improve test 2023-01-31 19:40:42 +01:00
Matthias
9cfbb21cd7 Improve error messages 2023-01-31 19:38:43 +01:00
Matthias
bbc663fce1 Add telegram test 2023-01-31 19:26:26 +01:00
Matthias
1c47c118d6 Add cancel-order api test 2023-01-31 19:26:21 +01:00
Matthias
daafc1c90f Update test and help 2023-01-31 18:16:59 +01:00
Matthias
bd2839fa40 Reorder documentation 2023-01-31 18:13:42 +01:00
Matthias
e291d1bb17 Document telegram /coo command 2023-01-31 18:12:18 +01:00
Matthias
1bdc0e3917 Add coo command to telegram 2023-01-31 18:09:40 +01:00
Leonardo Custodio
152aa994a6 Fix test 2023-01-31 12:46:21 -03:00
Leonardo Custodio
baf2090f9e Just change the docs 2023-01-31 12:42:39 -03:00
Leonardo Custodio
592eebe516 Add to setup 2023-01-31 12:10:41 -03:00
Leonardo Custodio
8b307357f3 Add to setup 2023-01-31 12:09:14 -03:00
Leonardo Custodio
d27d5624e0 Merge branch 'freqtrade:develop' into patch-1 2023-01-31 12:00:00 -03:00
Matthias
5073c780d8 .agg would like strings, not the sum function. 2023-01-31 11:22:04 +00:00
Matthias
2c1457fb95 Ensure limit is integer (on server) 2023-01-31 11:06:23 +00:00
Matthias
1dc3c58775 Convert missing candle count to int
closes #8082
2023-01-31 11:04:56 +00:00
Matthias
410324ac19 time-jump detection should happen on the trimmed dataframe
Fixes comment in #7615
2023-01-31 10:13:21 +00:00
Matthias
9e619ecc50 Update rest api documentation 2023-01-31 07:26:12 +01:00
Matthias
03302fa0b0 Add cancel_open_order to rest script 2023-01-31 07:24:19 +01:00
Matthias
c43e857cbc Bump API version 2023-01-31 07:09:07 +01:00
Matthias
c855e2d79c Add delete open order endpoint 2023-01-31 07:09:03 +01:00
Matthias
a704c43402 provide cancel-reason to handle_cancel_order 2023-01-31 07:08:12 +01:00
Leonardo Custodio
2b09f01293 Fixes gym issue
https://github.com/freqtrade/freqtrade/issues/8078
2023-01-30 18:52:56 -03:00
Matthias
5a7008f377 rename handle_timedout to handle_cancel_order 2023-01-30 20:02:01 +01:00
Matthias
cd6602882c Merge pull request #8076 from freqtrade/new_release
New release 2023.1
2023-01-30 18:11:08 +01:00
Matthias
c3ef8ebb10 Merge pull request #8059 from freqtrade/bybit
Bybit futures support 🎉
2023-01-30 18:10:46 +01:00
Matthias
b5c0daa069 Merge pull request #8028 from freqtrade/dependabot/pip/develop/sb3-contrib-1.7.0
Bump sb3-contrib from 1.6.2 to 1.7.0
2023-01-30 11:42:24 +01:00
Matthias
da0ac8190f Merge pull request #8075 from freqtrade/dependabot/pip/develop/pyarrow-11.0.0
Bump pyarrow from 10.0.1 to 11.0.0
2023-01-30 11:33:23 +01:00
Matthias
3cb9cc63b3 add pyarrow-11 rpi wheel file 2023-01-30 10:04:10 +00:00
Matthias
e77c16d510 Merge pull request #8073 from freqtrade/dependabot/pip/develop/lightgbm-3.3.5
Bump lightgbm from 3.3.4 to 3.3.5
2023-01-30 09:42:14 +01:00
Matthias
f57394c1ce Merge branch 'develop' into bybit 2023-01-30 07:23:41 +01:00
Matthias
f22f613b24 Merge pull request #8074 from freqtrade/dependabot/pip/develop/mkdocs-material-9.0.8
Bump mkdocs-material from 9.0.5 to 9.0.8
2023-01-30 07:22:46 +01:00
Matthias
2593a929d4 Bump version to 2023.2.dev 2023-01-30 07:19:35 +01:00
Matthias
786f746958 Version bump to 2023.1 2023-01-30 07:16:16 +01:00
Matthias
c4482d56ab Merge branch 'stable' into new_release 2023-01-30 07:10:32 +01:00
dependabot[bot]
411ad5641a Bump pyarrow from 10.0.1 to 11.0.0
Bumps [pyarrow](https://github.com/apache/arrow) from 10.0.1 to 11.0.0.
- [Release notes](https://github.com/apache/arrow/releases)
- [Commits](https://github.com/apache/arrow/compare/go/v10.0.1...apache-arrow-11.0.0)

---
updated-dependencies:
- dependency-name: pyarrow
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-30 03:02:06 +00:00
dependabot[bot]
0dd852516a Bump mkdocs-material from 9.0.5 to 9.0.8
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.0.5 to 9.0.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/9.0.5...9.0.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>
2023-01-30 03:01:33 +00:00
dependabot[bot]
2fea23d31a Bump lightgbm from 3.3.4 to 3.3.5
Bumps [lightgbm](https://github.com/microsoft/LightGBM) from 3.3.4 to 3.3.5.
- [Release notes](https://github.com/microsoft/LightGBM/releases)
- [Commits](https://github.com/microsoft/LightGBM/compare/v3.3.4...v3.3.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-30 03:01:12 +00:00
Matthias
ede79590da Update ccxt compat tests with kucoin order 2023-01-29 19:56:13 +01:00
Matthias
fee7b792e1 Bump ccxt 2023-01-29 19:33:13 +01:00
Matthias
507d3d6d9b Add ci for binance.us 2023-01-29 15:14:55 +01:00
Matthias
25dfbb5a08 Compare stake amout >= in backtesting
closes #8067
2023-01-29 12:47:16 +01:00
Matthias
9286cbed86 add partial Docstring to backtesting enter_trade 2023-01-29 11:02:31 +01:00
Matthias
c1e528e116 Version bump ccxt
closes #8010
2023-01-28 19:54:28 +01:00
Matthias
f6ba0fe6ae bybit: fix broken ccxt tests 2023-01-28 18:23:23 +01:00
Matthias
7294db81e2 Bump ccxt to 2.7.7 2023-01-28 18:17:09 +01:00
Matthias
adf29fe1d7 Merge pull request #8065 from Shadyzpop/patch-1
Docs typo fix
2023-01-28 18:11:36 +01:00
Shadyzpop
f7f936c14f Typo fix 2023-01-28 03:43:18 +03:00
Matthias
d1b069abfb bybit: Update test to align with defaultType change 2023-01-27 20:33:34 +01:00
Matthias
7029b9602c Merge branch 'develop' into bybit 2023-01-27 20:30:05 +01:00
Matthias
020dc3c6e1 filled-date shouldn't update again 2023-01-27 20:21:29 +01:00
Matthias
aa15837589 Add test for filled_date not updating if it's already set 2023-01-27 20:20:15 +01:00
Matthias
fa033965c8 use "swap" for bybit 2023-01-27 19:34:29 +01:00
Matthias
08ede37795 Add documentation note about stoploss on exchange 2023-01-26 19:58:58 +01:00
Matthias
8665d0866d Add test for bybit startup magic 2023-01-26 19:58:42 +01:00
Matthias
1431f7cc3e Set position mode to one-way on startup 2023-01-26 19:54:35 +01:00
Matthias
73ef1d5191 Improve exception wording on binance 2023-01-26 19:53:14 +01:00
Matthias
8647c0192c Fix typo 2023-01-26 07:08:38 +01:00
Matthias
2333dbae40 Update reinforcement learning docs to use correct naming 2023-01-26 07:07:49 +01:00
Matthias
bd913bc24d Disable provenance in buildx config for pi image 2023-01-25 14:34:52 +01:00
Matthias
9652c00acb Don't amend docker manifest 2023-01-25 12:20:10 +01:00
Matthias
c12fb1a49c bybit: Some final cleanup 2023-01-24 20:12:50 +01:00
Matthias
25fa6bee74 Override get_funding_fees for bybit 2023-01-24 07:21:56 +01:00
Matthias
051c3be99e add test case for bybit 2023-01-24 07:21:56 +01:00
Matthias
3a83427f92 Add Bybit stoploss support 2023-01-24 07:21:56 +01:00
Matthias
c14553bacb Add bybit to supported Futures exchanges 2023-01-24 07:21:56 +01:00
Matthias
c2b33a0f58 Fix set-leverage function sig 2023-01-24 07:21:56 +01:00
Matthias
7a18e96042 bybit: hot-fix funding fees (temporary - must be changed) 2023-01-24 07:21:56 +01:00
Matthias
f681ce9139 Allow margin and leverage setting failures
(this is important when an exchange "fails" a request if the setting didn't change).
2023-01-24 07:21:56 +01:00
Matthias
31745a9dc2 bybit: Initial implementation liquidation calculation 2023-01-24 07:21:56 +01:00
Matthias
93ce963e9b Update test name 2023-01-24 07:21:56 +01:00
Matthias
752110a268 Add online tests for bybit 2023-01-24 07:21:56 +01:00
Matthias
d05ecd630f Update tests for new liquidation parameter 2023-01-24 07:21:56 +01:00
Matthias
34e7433844 Add leverage to dry-run liquidation price calculation 2023-01-24 07:21:56 +01:00
Matthias
a7b030fff9 Add note about bybit futures 2023-01-24 07:21:56 +01:00
Matthias
3192af8df8 Limit bybit futures markets to USDT 2023-01-24 07:21:56 +01:00
Matthias
63c732a560 Bybit futures data download 2023-01-24 07:21:56 +01:00
Matthias
6c0fa0dc1f Fix typo in docstring 2023-01-24 07:21:43 +01:00
Matthias
078b430828 Add ccxt compat tests for order parsing 2023-01-23 18:22:07 +01:00
Matthias
b0720fdcf5 Bump ccxt to latest version to fix timestamp parsing issues 2023-01-23 18:10:56 +01:00
Matthias
1e43154bc5 Merge pull request #8049 from freqtrade/dependabot/pip/develop/types-python-dateutil-2.8.19.6
Bump types-python-dateutil from 2.8.19.5 to 2.8.19.6
2023-01-23 09:31:34 +01:00
Matthias
228fc757e9 Merge pull request #8050 from freqtrade/dependabot/pip/develop/ccxt-2.6.58
Bump ccxt from 2.6.39 to 2.6.58
2023-01-23 09:31:18 +01:00
dependabot[bot]
7fc39eafbd Bump ccxt from 2.6.39 to 2.6.58
Bumps [ccxt](https://github.com/ccxt/ccxt) from 2.6.39 to 2.6.58.
- [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/2.6.39...2.6.58)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-23 07:36:53 +00:00
Matthias
3397225df2 Merge pull request #8051 from freqtrade/dependabot/pip/develop/pandas-1.5.3
Bump pandas from 1.5.2 to 1.5.3
2023-01-23 08:10:48 +01:00
Matthias
14d9789f1e Bump types-dateutil for precommit 2023-01-23 08:04:45 +01:00
dependabot[bot]
d3fbd41f59 Bump types-python-dateutil from 2.8.19.5 to 2.8.19.6
Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.8.19.5 to 2.8.19.6.
- [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>
2023-01-23 06:18:40 +00:00
Matthias
b80c9dfd1e Merge pull request #8052 from freqtrade/dependabot/pip/develop/types-requests-2.28.11.8
Bump types-requests from 2.28.11.7 to 2.28.11.8
2023-01-23 07:16:41 +01:00
Matthias
5ef6ea4d91 Merge pull request #8048 from freqtrade/dependabot/pip/develop/nbconvert-7.2.8
Bump nbconvert from 7.2.7 to 7.2.8
2023-01-23 06:48:15 +01:00
Matthias
73414e0fbd Bump types-requests in pre-commit 2023-01-23 06:47:27 +01:00
dependabot[bot]
673f5c325c Bump types-requests from 2.28.11.7 to 2.28.11.8
Bumps [types-requests](https://github.com/python/typeshed) from 2.28.11.7 to 2.28.11.8.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-23 03:08:24 +00:00
dependabot[bot]
b104b54e6a Bump pandas from 1.5.2 to 1.5.3
Bumps [pandas](https://github.com/pandas-dev/pandas) from 1.5.2 to 1.5.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.5.2...v1.5.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-23 03:08:20 +00:00
dependabot[bot]
13f6529cca Bump nbconvert from 7.2.7 to 7.2.8
Bumps [nbconvert](https://github.com/jupyter/nbconvert) from 7.2.7 to 7.2.8.
- [Release notes](https://github.com/jupyter/nbconvert/releases)
- [Changelog](https://github.com/jupyter/nbconvert/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jupyter/nbconvert/compare/v7.2.7...v7.2.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-23 03:07:48 +00:00
Matthias
95987663f4 Merge pull request #8040 from xmatthias/mypy_fixes
Enable mypy defaults for Optional typechecking
2023-01-22 11:18:53 +01:00
Matthias
0642a2768e Add missing bracket
closes #8041
2023-01-22 11:17:31 +01:00
Matthias
58ad5a683a Fix wrong import order in script 2023-01-21 22:48:30 +01:00
Matthias
79d0fd937c Update pyright config to align with mypy 2023-01-21 20:05:33 +01:00
Matthias
741d2db334 Enable implicit_optional for telegram 2023-01-21 20:02:16 +01:00
Matthias
795934116d Remove optional_untyped from config 2023-01-21 20:02:12 +01:00
Matthias
2bf4cf7d5a Update scripts to PEP484 2023-01-21 20:02:07 +01:00
Matthias
8108a48f39 Follow PEP 484 - no implicit optionals 2023-01-21 20:01:56 +01:00
Matthias
bb355cfac5 improve naming of backtest function 2023-01-21 19:46:27 +01:00
Matthias
80bb120026 Simplify backtesting by removing now unnecessary private function 2023-01-21 18:01:01 +01:00
Matthias
89eb1b0084 funding-fees need to be recalculated for detailed timeframes, too.
closes #7978
2023-01-21 17:47:37 +01:00
Matthias
1211b72255 Add test to show behavior reported in #7978 2023-01-21 16:23:32 +01:00
Matthias
772800bf74 Fix bug in stake_amount adjustment
This was preventing a DCA order to take the remaining stake
2023-01-21 08:52:10 +01:00
Matthias
865d678304 Add backtest_detail test for futures 2023-01-20 09:45:02 +00:00
Matthias
28e51e2dfb Simplify some test setups 2023-01-20 08:28:50 +00:00
Matthias
58d48e79da Convert tests/datadir to path object - better mirroring an initialized configuration 2023-01-20 08:07:02 +00:00
Matthias
a5d87859dc Refactor test to reuse variable 2023-01-20 07:27:35 +00:00
Matthias
6e22607387 Add 5m futures testdata to support detail-backtest tests 2023-01-20 07:08:38 +00:00
Matthias
dbddc4c8aa Improve wording on adjust_trade_position callback warning 2023-01-20 07:08:15 +01:00
Matthias
20093ea090 Add warning about callback call frequency in backtesting 2023-01-20 07:06:54 +01:00
Matthias
81349c2a03 Remove edge section from config template 2023-01-19 19:57:34 +01:00
Matthias
07c391322e Remove edge from sample configs (except full).
Edge is barely used, but everyone drags it's config around.
2023-01-19 18:26:22 +01:00
Matthias
a398f4730b Add documentation note about RSA exchange keys
part of #8034
2023-01-19 18:15:50 +01:00
Matthias
a27e63a547 Bump ccxt to 2.6.39
closes #8034
2023-01-19 18:15:50 +01:00
Matthias
cd2a41e76e Merge pull request #8035 from freqtrade/enable_plotconfig_wsmode
Enable plotconfig wsmode
2023-01-19 06:55:49 +01:00
Matthias
892fb77ec3 Update mypy pre-commit hook 2023-01-18 19:31:20 +01:00
Matthias
634b80f0e7 Add tests for plotconfig in ws mode 2023-01-18 18:15:35 +01:00
Matthias
2298656e45 Bump api_version to 2.23 2023-01-18 18:15:14 +01:00
Matthias
3216a05a9e Enable plot_config to work in webserver mode
(requires strategy argument)
2023-01-18 18:15:07 +01:00
Matthias
da0992f859 add Config typehint in rpc 2023-01-18 06:45:31 +01:00
Matthias
25f89ac194 Merge pull request #8033 from stash86/bt-metrics
update config-freqai-example to match latest binance futures pair syntax
2023-01-18 06:33:37 +01:00
Stefano Ariestasia
00fa904422 update config-freqai-example to match latest binance futures pair syntax 2023-01-18 09:56:15 +09:00
Matthias
4aaa439221 Merge pull request #7976 from adarkforce/max-open-trades
Hyperopt Max open trades
2023-01-17 20:41:48 +01:00
Matthias
c8ecedf6d5 Clarify a variable via typehint 2023-01-17 20:05:18 +01:00
Matthias
6a4fc33c30 Remove <3.8 bandaid 2023-01-17 19:46:56 +01:00
Matthias
7092212ed5 re-add futures tickers quoteVolume assert 2023-01-17 06:57:48 +01:00
Matthias
7713f343a9 Bump ccxt to 2.6.26
closes #8032
2023-01-17 06:46:49 +01:00
Matthias
98dcab49ab Add fetch_tickers test for futures 2023-01-16 23:06:18 +01:00
Matthias
b4fcda2c11 add aiohttp proxy 2023-01-16 22:37:21 +01:00
Matthias
92a5efad0e Fix set_test_proxy usage 2023-01-16 22:09:53 +01:00
Matthias
b193d8418d Deepcopy config before adding proxies 2023-01-16 21:31:01 +01:00
Matthias
f46b62f1a7 Attempt to use and setup a proxy for CI 2023-01-16 21:15:05 +01:00
Matthias
394a973bbb Revert "Attempt to use and setup a proxy for CI"
This reverts commit 48ae248d2d.
2023-01-16 21:14:46 +01:00
Matthias
48ae248d2d Attempt to use and setup a proxy for CI 2023-01-16 21:14:19 +01:00
Antonio Della Fortuna
5e10bb2cca Merge branch 'develop' of https://github.com/freqtrade/freqtrade into max-open-trades 2023-01-16 20:19:46 +01:00
Matthias
75804a7f85 Bump stable-baselines3 alongside with sb3-contrib. 2023-01-16 15:53:44 +01:00
Matthias
81eb9ebc6e Merge pull request #8031 from froggleston/eea_grp5
Add a new analysis group to output stats grouped by exit_tag
2023-01-16 15:50:47 +01:00
Matthias
8cfa5934db Catch AttributeError when importing modules
closes #8023
2023-01-16 13:54:25 +00:00
froggleston
813724bd82 Add a new analysis group to output stats grouped by exit_tag 2023-01-16 13:28:40 +00:00
Matthias
05dc29e60b Merge pull request #8021 from freqtrade/dependabot/pip/develop/mkdocs-material-9.0.5
Bump mkdocs-material from 9.0.3 to 9.0.5
2023-01-16 13:31:30 +01:00
Matthias
41d4e516f1 Merge pull request #8024 from freqtrade/dependabot/pip/develop/cryptography-39.0.0
Bump cryptography from 38.0.1 to 39.0.0
2023-01-16 13:31:06 +01:00
Matthias
3ab40358a2 Merge pull request #8026 from freqtrade/dependabot/pip/develop/tensorboard-2.11.2
Bump tensorboard from 2.11.0 to 2.11.2
2023-01-16 13:29:04 +01:00
dependabot[bot]
8de10e3746 Bump mkdocs-material from 9.0.3 to 9.0.5
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.0.3 to 9.0.5.
- [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/9.0.3...9.0.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-16 11:34:02 +00:00
Matthias
d7bd9de60e Merge pull request #8025 from freqtrade/dependabot/pip/develop/fastapi-0.89.1
Bump fastapi from 0.89.0 to 0.89.1
2023-01-16 12:28:08 +01:00
Matthias
d0ad822034 Merge pull request #8029 from freqtrade/dependabot/pip/develop/pymdown-extensions-9.9.1
Bump pymdown-extensions from 9.9 to 9.9.1
2023-01-16 12:27:44 +01:00
dependabot[bot]
7f4883008f Bump pymdown-extensions from 9.9 to 9.9.1
Bumps [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions) from 9.9 to 9.9.1.
- [Release notes](https://github.com/facelessuser/pymdown-extensions/releases)
- [Commits](https://github.com/facelessuser/pymdown-extensions/compare/9.9...9.9.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-16 08:53:34 +00:00
dependabot[bot]
a77fdb1594 Bump sb3-contrib from 1.6.2 to 1.7.0
Bumps [sb3-contrib](https://github.com/Stable-Baselines-Team/stable-baselines3-contrib) from 1.6.2 to 1.7.0.
- [Release notes](https://github.com/Stable-Baselines-Team/stable-baselines3-contrib/releases)
- [Commits](https://github.com/Stable-Baselines-Team/stable-baselines3-contrib/compare/v1.6.2...v1.7.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-16 08:53:21 +00:00
dependabot[bot]
a4b2dc30b4 Bump tensorboard from 2.11.0 to 2.11.2
Bumps [tensorboard](https://github.com/tensorflow/tensorboard) from 2.11.0 to 2.11.2.
- [Release notes](https://github.com/tensorflow/tensorboard/releases)
- [Changelog](https://github.com/tensorflow/tensorboard/blob/2.11.2/RELEASE.md)
- [Commits](https://github.com/tensorflow/tensorboard/compare/2.11.0...2.11.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-16 08:53:12 +00:00
dependabot[bot]
8dce617ada Bump fastapi from 0.89.0 to 0.89.1
Bumps [fastapi](https://github.com/tiangolo/fastapi) from 0.89.0 to 0.89.1.
- [Release notes](https://github.com/tiangolo/fastapi/releases)
- [Commits](https://github.com/tiangolo/fastapi/compare/0.89.0...0.89.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-16 08:53:06 +00:00
dependabot[bot]
283c1968bf Bump cryptography from 38.0.1 to 39.0.0
Bumps [cryptography](https://github.com/pyca/cryptography) from 38.0.1 to 39.0.0.
- [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/38.0.1...39.0.0)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-16 08:52:52 +00:00
Matthias
76c4b2a975 Merge pull request #8019 from freqtrade/dependabot/pip/develop/requests-2.28.2
Bump requests from 2.28.1 to 2.28.2
2023-01-16 09:50:37 +01:00
Matthias
7c2bfae92e Merge pull request #8018 from freqtrade/dependabot/pip/develop/ccxt-2.6.24
Bump ccxt from 2.6.6 to 2.6.24
2023-01-16 08:13:47 +01:00
Matthias
0296061e49 Fix version comparison to use packaging.version 2023-01-16 06:54:29 +01:00
Matthias
d226f9706b Merge pull request #8020 from freqtrade/dependabot/pip/develop/xgboost-1.7.3
Bump xgboost from 1.7.2 to 1.7.3
2023-01-16 06:49:47 +01:00
Matthias
7f61fdd9a3 Merge pull request #8022 from freqtrade/dependabot/pip/develop/pytest-7.2.1
Bump pytest from 7.2.0 to 7.2.1
2023-01-16 06:48:49 +01:00
Matthias
77bb6561d5 Merge pull request #8017 from freqtrade/dependabot/pip/develop/orjson-3.8.5
Bump orjson from 3.8.4 to 3.8.5
2023-01-16 06:46:22 +01:00
dependabot[bot]
178a4c8867 Bump requests from 2.28.1 to 2.28.2
Bumps [requests](https://github.com/psf/requests) from 2.28.1 to 2.28.2.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.28.1...v2.28.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-16 05:32:39 +00:00
Matthias
6fd9690477 Merge pull request #8015 from freqtrade/dependabot/pip/develop/urllib3-1.26.14
Bump urllib3 from 1.26.13 to 1.26.14
2023-01-16 06:31:39 +01:00
dependabot[bot]
7785809f4a Bump pytest from 7.2.0 to 7.2.1
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.2.0 to 7.2.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.2.0...7.2.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-16 03:02:08 +00:00
dependabot[bot]
59e6f19dd8 Bump xgboost from 1.7.2 to 1.7.3
Bumps [xgboost](https://github.com/dmlc/xgboost) from 1.7.2 to 1.7.3.
- [Release notes](https://github.com/dmlc/xgboost/releases)
- [Changelog](https://github.com/dmlc/xgboost/blob/master/NEWS.md)
- [Commits](https://github.com/dmlc/xgboost/compare/v1.7.2...v1.7.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-16 03:01:28 +00:00
dependabot[bot]
dc7b8ac7ba Bump ccxt from 2.6.6 to 2.6.24
Bumps [ccxt](https://github.com/ccxt/ccxt) from 2.6.6 to 2.6.24.
- [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/2.6.6...2.6.24)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-16 03:01:13 +00:00
dependabot[bot]
d24fce83d2 Bump orjson from 3.8.4 to 3.8.5
Bumps [orjson](https://github.com/ijl/orjson) from 3.8.4 to 3.8.5.
- [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.8.4...3.8.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-16 03:01:03 +00:00
dependabot[bot]
9b97ddd0f7 Bump urllib3 from 1.26.13 to 1.26.14
Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.13 to 1.26.14.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/1.26.13...1.26.14)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-16 03:00:47 +00:00
Matthias
fc9e0ede0b Merge pull request #8014 from freqtrade/binance_mig
Binance futures naming migration
2023-01-15 21:57:21 +01:00
Matthias
270eed7e14 Fail if detecting invalid ccxt version for binance futures 2023-01-15 19:38:50 +01:00
Antonio Della Fortuna
ab12aace5f changed trades_space to max_open_trades_space 2023-01-15 11:50:40 +01:00
Antonio Della Fortuna
5e64980319 Merge branch 'develop' of https://github.com/freqtrade/freqtrade into max-open-trades 2023-01-15 11:44:35 +01:00
Antonio Della Fortuna
b0f1d914c8 Changed max_open_trades type to int or inf 2023-01-15 11:44:10 +01:00
Matthias
ce323e66ac Remove note about binance futures naming 2023-01-14 21:40:48 +01:00
Matthias
e14f2cc275 Add db migration test 2023-01-14 21:26:00 +01:00
Matthias
5d4a247fa0 Add test for binance data migration 2023-01-14 20:34:04 +01:00
Matthias
cbcee02ded call data migration from backtesting 2023-01-14 20:07:33 +01:00
Matthias
1fc97a8008 use Unified futures naming for futures throughout tests 2023-01-13 21:16:19 +01:00
Matthias
9d1cf040f0 Update test leverage tiers 2023-01-13 20:44:45 +01:00
Matthias
4ea8962ca2 Rename futures test data 2023-01-13 20:44:32 +01:00
Matthias
47b50a8a29 Udpate binance leverage tiers to new pair format 2023-01-13 20:32:25 +01:00
Matthias
c93b265ec8 Run migration commands on certain data commands 2023-01-13 07:27:18 +01:00
Matthias
0be0ef9e77 Remove duplicate binance test
The same test exists in test_exchange, but for most exchanges.
2023-01-13 07:11:44 +01:00
Matthias
0d1172ca43 Update binance future test 2023-01-13 07:04:29 +01:00
Matthias
e43b9b65fa increase minimium ccxt version to 2.6.6 2023-01-13 07:00:13 +01:00
Matthias
b024fafaf8 Use futures_pair in ccxt test correctly 2023-01-12 23:39:02 +01:00
Matthias
5b3304189c trading_mode is not necessarily mandatory 2023-01-12 23:38:53 +01:00
Matthias
183bf6819f Update binance pair naming in ccxt test 2023-01-12 23:35:32 +01:00
Matthias
5ad664aaca Update binance futures name to swap 2023-01-12 23:35:16 +01:00
Matthias
9cb7d6c26e Run binance futures migrations on startup 2023-01-12 23:35:06 +01:00
Matthias
5d45adb37d Merge pull request #8009 from freqtrade/robcaulk-patch-1
Update freqai-reinforcement-learning.md
2023-01-12 23:33:54 +01:00
Robert Caulk
bfd7803fd8 Update freqai-reinforcement-learning.md 2023-01-12 22:18:22 +01:00
Matthias
ee7b505dcb Add data migration method 2023-01-12 20:59:43 +01:00
Matthias
b1bfd76741 Add binance futures db migration 2023-01-12 20:36:06 +01:00
Matthias
518e8d24dc Merge pull request #8007 from TheJoeSchr/fix/version-cwd
fix "--version": needs to change working directory
2023-01-12 20:24:28 +01:00
Joe Schr
1cf69f139c refactor "--version" to use "pathlib" instead of "os" 2023-01-12 19:27:41 +01:00
Matthias
1a533668b5 Merge pull request #8008 from freqtrade/fix/NaT_ser_deser
Fix websockets for dataframes with NaT entries
2023-01-12 08:10:14 +01:00
Antonio Della Fortuna
192f75254f Merge branch 'develop' of https://github.com/freqtrade/freqtrade into max-open-trades 2023-01-11 22:21:46 +01:00
Matthias
9d647fd193 Fix websockets for dataframes with NaT entreis 2023-01-11 22:07:20 +01:00
Matthias
ec5d464ff2 Merge pull request #8005 from TheJoeSchr/develop
docs: fix broken link to quickstart
2023-01-11 21:37:34 +01:00
Matthias
684de1937a Fix link syntax to actually work 2023-01-11 21:35:18 +01:00
Joe Schr
08748dd021 fix "--version": needs to change working directory
before calling `git`. otherwise it would display git commit id from the
directory where you are calling `freqtrade` from instead of freqtrade's
current commit id
2023-01-11 21:12:06 +01:00
Joe Schr
4abf06119b docs: fix broken link to quickstart 2023-01-11 20:29:40 +01:00
Antonio Della Fortuna
534aa8f7ff Merge branch 'develop' of https://github.com/freqtrade/freqtrade into max-open-trades
# Conflicts:
#	freqtrade/optimize/backtesting.py
2023-01-11 18:55:57 +01:00
Matthias
00dbc195ac Update huobi ci to use BTC markets 2023-01-11 08:43:07 +00:00
Matthias
f677dea6a4 Merge pull request #7950 from freqtrade/freqai_feature_engineering_functions
FreqAI Strategy - Improve user experience
2023-01-10 20:04:53 +01:00
Wagner Costa
2241f24290 moved deprecated warning to start function 2023-01-10 09:10:30 -03:00
Matthias
a261ee327d Merge pull request #7994 from freqtrade/dependabot/pip/develop/scipy-1.10.0
Bump scipy from 1.9.3 to 1.10.0
2023-01-10 08:07:24 +01:00
Matthias
67495530b7 Add FreqAI migration documentation 2023-01-10 07:22:28 +01:00
Matthias
6fc3d0e5e1 Merge pull request #7995 from freqtrade/dependabot/pip/develop/httpx-0.23.3
Bump httpx from 0.23.1 to 0.23.3
2023-01-09 20:47:32 +01:00
robcaulk
93aff9325e improve deprecation note 2023-01-09 20:15:03 +01:00
robcaulk
a61274ae18 ensure cached corr-pairs works with new framework 2023-01-09 20:04:36 +01:00
Matthias
811f13e09a Merge pull request #7981 from freqtrade/backtest_detail_speed
Improve backtest detail speed
2023-01-09 18:21:54 +01:00
Matthias
30bc45a1ba Merge pull request #7991 from freqtrade/order_amount_price
Separately store Order amount price
2023-01-09 18:15:55 +01:00
Matthias
fbdda8cd15 Always pass Dictionaries to testclient post requests 2023-01-09 18:12:20 +01:00
Matthias
3e5ca0438f Merge pull request #8000 from freqtrade/dependabot/pip/develop/mkdocs-material-9.0.3
Bump mkdocs-material from 8.5.11 to 9.0.3
2023-01-09 13:37:04 +01:00
dependabot[bot]
3ca2dfc079 Bump httpx from 0.23.1 to 0.23.3
Bumps [httpx](https://github.com/encode/httpx) from 0.23.1 to 0.23.3.
- [Release notes](https://github.com/encode/httpx/releases)
- [Changelog](https://github.com/encode/httpx/blob/master/CHANGELOG.md)
- [Commits](https://github.com/encode/httpx/compare/0.23.1...0.23.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-09 09:10:30 +00:00
Matthias
d59c48c638 Merge pull request #7996 from freqtrade/dependabot/pip/develop/sqlalchemy-1.4.46
Bump sqlalchemy from 1.4.45 to 1.4.46
2023-01-09 09:33:26 +01:00
Matthias
0aca0d20d9 Add some feature flags for mkdocs migration 2023-01-09 07:24:18 +01:00
Matthias
8abe1e1c2e Merge pull request #8001 from freqtrade/dependabot/pip/develop/orjson-3.8.4
Bump orjson from 3.8.3 to 3.8.4
2023-01-09 06:52:02 +01:00
Matthias
bd7eeb8701 Merge pull request #7998 from freqtrade/dependabot/pip/develop/fastapi-0.89.0
Bump fastapi from 0.88.0 to 0.89.0
2023-01-09 06:51:12 +01:00
Matthias
8a5aef20aa Merge pull request #7999 from freqtrade/dependabot/pip/develop/ccxt-2.5.56
Bump ccxt from 2.5.46 to 2.5.56
2023-01-09 06:49:29 +01:00
Matthias
7de72a2425 Merge pull request #7993 from freqtrade/dependabot/pip/develop/lightgbm-3.3.4
Bump lightgbm from 3.3.3 to 3.3.4
2023-01-09 06:47:37 +01:00
dependabot[bot]
43b49fef4f Bump orjson from 3.8.3 to 3.8.4
Bumps [orjson](https://github.com/ijl/orjson) from 3.8.3 to 3.8.4.
- [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.8.3...3.8.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-09 03:01:33 +00:00
dependabot[bot]
25fd1ea639 Bump mkdocs-material from 8.5.11 to 9.0.3
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 8.5.11 to 9.0.3.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Upgrade guide](https://github.com/squidfunk/mkdocs-material/blob/master/docs/upgrade.md)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/8.5.11...9.0.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-09 03:01:26 +00:00
dependabot[bot]
3b69745c3b Bump ccxt from 2.5.46 to 2.5.56
Bumps [ccxt](https://github.com/ccxt/ccxt) from 2.5.46 to 2.5.56.
- [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/2.5.46...2.5.56)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-09 03:01:18 +00:00
dependabot[bot]
79fe8fd85b Bump fastapi from 0.88.0 to 0.89.0
Bumps [fastapi](https://github.com/tiangolo/fastapi) from 0.88.0 to 0.89.0.
- [Release notes](https://github.com/tiangolo/fastapi/releases)
- [Commits](https://github.com/tiangolo/fastapi/compare/0.88.0...0.89.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-09 03:01:07 +00:00
dependabot[bot]
d32d70d2ea Bump sqlalchemy from 1.4.45 to 1.4.46
Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 1.4.45 to 1.4.46.
- [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>
2023-01-09 03:00:58 +00:00
dependabot[bot]
c198ca2967 Bump scipy from 1.9.3 to 1.10.0
Bumps [scipy](https://github.com/scipy/scipy) from 1.9.3 to 1.10.0.
- [Release notes](https://github.com/scipy/scipy/releases)
- [Commits](https://github.com/scipy/scipy/compare/v1.9.3...v1.10.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-09 03:00:45 +00:00
dependabot[bot]
2f0eb95d03 Bump lightgbm from 3.3.3 to 3.3.4
Bumps [lightgbm](https://github.com/microsoft/LightGBM) from 3.3.3 to 3.3.4.
- [Release notes](https://github.com/microsoft/LightGBM/releases)
- [Commits](https://github.com/microsoft/LightGBM/compare/v3.3.3...v3.3.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-09 03:00:38 +00:00
Antonio Della Fortuna
7d27afd4b8 Fixed test broken due to change in trades_space range 2023-01-08 16:11:41 +01:00
Matthias
ad49541947 Adapt Tests for new mandatory columns 2023-01-08 13:55:52 +01:00
Matthias
305b067e48 Support having no Amount/Price available from the exchange initially 2023-01-08 13:55:09 +01:00
Matthias
fd694f14c2 Add new order columns, ft_amount and ft_price 2023-01-08 13:53:08 +01:00
Antonio Della Fortuna
10d8b016e4 Changed max_open_trades default range for optimization 2023-01-08 12:48:36 +01:00
Antonio Della Fortuna
f77dffc951 align to develop 2023-01-08 12:46:27 +01:00
Antonio Della Fortuna
24ace646c3 Merge branch 'develop' of https://github.com/freqtrade/freqtrade into max-open-trades 2023-01-08 12:40:01 +01:00
Antonio Della Fortuna
464cb4761c Fixed max_open_trades update from hyperopt
Fixed max_open_trades update from hyperopt + removed max_open_trades as a param to backtesting + refactoring
2023-01-08 12:39:39 +01:00
Matthias
550ab2b8e8 Improve select_order to only consider filled where needed. 2023-01-08 11:24:04 +01:00
Matthias
8d4f7341c9 Merge pull request #7987 from stash86/bt-metrics
update calmar, sharpe, and sortino hyperopt losses to use latest formula
2023-01-08 10:37:24 +01:00
Matthias
34dbe9deaa Improve fixture fake results 2023-01-08 10:08:54 +01:00
Matthias
f958459a84 Merge pull request #7989 from freqtrade/dependabot/pip/develop/ccxt-2.5.46
Bump ccxt from 2.4.60 to 2.5.46
2023-01-07 16:32:11 +01:00
dependabot[bot]
1d5440ff71 Bump ccxt from 2.4.60 to 2.5.46
Bumps [ccxt](https://github.com/ccxt/ccxt) from 2.4.60 to 2.5.46.
- [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/2.4.60...2.5.46)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-07 14:19:48 +00:00
Matthias
c7f485687f Fix ccxt test failure
as identified and analyzed https://github.com/ccxt/ccxt/issues/16335
2023-01-07 15:13:22 +01:00
Antonio Della Fortuna
8c3ac56bc5 Merge branch 'develop' of https://github.com/freqtrade/freqtrade into max-open-trades 2023-01-07 11:11:59 +01:00
root
7bf531c8b8 isort fix 2023-01-07 09:50:05 +09:00
Stefano Ariestasia
c1042996db flake8 fix 2023-01-07 09:46:46 +09:00
Stefano Ariestasia
6198b21001 update calmar loss 2023-01-07 09:30:16 +09:00
Stefano Ariestasia
d3b1aa7f01 update sortino calc 2023-01-07 09:19:06 +09:00
Stefano Ariestasia
157bf962f7 add missing imports 2023-01-07 09:14:56 +09:00
Stefano Ariestasia
86ba7dae92 change sharpe hyperopt loss 2023-01-07 08:56:40 +09:00
Matthias
8b456441a9 Merge pull request #7971 from paranoidandy/patch-1
Update FreqaiExampleStrategy.py
2023-01-06 15:16:31 +01:00
Matthias
349d67f582 Merge pull request #7983 from stash86/bt-metrics
Fix typo in calculate_expectancy's description
2023-01-06 07:30:09 +01:00
Stefano Ariestasia
329d95366a Merge branch 'freqtrade:develop' into bt-metrics 2023-01-06 08:04:00 +08:00
Matthias
787d292ba0 Move "drop_candle" decision to coroutine 2023-01-05 22:31:32 +01:00
Wagner Costa
d82264ced9 Merge branch 'develop' into freqai_feature_engineering_functions 2023-01-05 17:55:35 -03:00
Wagner Costa
abdeb72eb0 fix tests 2023-01-05 17:54:56 -03:00
robcaulk
d91ac8b669 improve wording in freqai doc 2023-01-05 20:13:48 +01:00
Matthias
bdf6537c60 Remove unused (and pointless) exchange method 2023-01-05 11:45:15 +01:00
Matthias
4bac66ff0e Type ohlcv coroutine 2023-01-05 11:33:47 +01:00
Matthias
75b0a3e63d Use dedicated type for OHLCV response 2023-01-05 11:30:15 +01:00
Matthias
92800930e9 Improve backtest detail speed 2023-01-05 10:14:58 +01:00
Matthias
5257e8b3ed Fix random test failures on 3.8 2023-01-05 09:12:09 +01:00
Wagner Costa
ed99e7f857 fix corr_pairs startup candle count bug 2023-01-04 14:21:37 -03:00
Matthias
8e5b4750d6 Continue in "regular backtest" case (no detail-data available).
link to #7967
2023-01-04 18:08:45 +01:00
Matthias
6470635753 In cases of no losing trade, sortino ratio can't be calculated.
closes #7977
2023-01-04 17:55:24 +01:00
Matthias
7a43f37eb7 Merge pull request #7972 from Undertoned/develop
Fix Backtesting  Analysis Column Wrong
2023-01-04 16:38:29 +01:00
Antonio Della Fortuna
f2fa476dc6 max_open_trades should be an integer
Max open trades will be always an integer in the strategy (-1 for infinity), but in the config -1 will be parsed as infinity
2023-01-04 16:09:27 +01:00
Wagner Costa
ed2b1b1ed1 Merge branch 'develop' into freqai_feature_engineering_functions 2023-01-04 10:40:20 -03:00
Wagner Costa
801ab39a24 fix get dataframe data to include startup_candle 2023-01-04 10:36:19 -03:00
Antonio Della Fortuna
1c5e172683 docs update 2023-01-04 12:54:35 +01:00
Matthias
38a780ef63 Merge pull request #7973 from freqtrade/robcaulk-patch-1
Fix file name in FreqaiExampleStrategy.py
2023-01-04 12:51:14 +01:00
Antonio Della Fortuna
ce661cb58b Merge branch 'develop' of https://github.com/freqtrade/freqtrade into max-open-trades 2023-01-04 10:35:09 +01:00
Antonio Della Fortuna
5fd85368a9 Added support for max_open_trades hyperopting 2023-01-04 10:34:44 +01:00
Robert Caulk
c384d1357e Update FreqaiExampleStrategy.py 2023-01-03 21:52:16 +01:00
Matthias
6f031f005d Fix flake error 2023-01-03 20:29:08 +01:00
zhanglei14
63db1fd894 Fix Backtesting Analysis Column Wrong 2023-01-04 01:38:07 +08:00
Wagner Costa
314c0925bf fix get dataframe data to include startup_candle 2023-01-03 14:02:42 -03:00
paranoidandy
73114b93c2 Update FreqaiExampleStrategy.py
Change can_short to True to enable shorting
2023-01-03 15:11:46 +00:00
Matthias
91d8370909 Merge pull request #7966 from freqtrade/frog-hyper-docs
Fix ROI table comma and spacing
2023-01-02 20:35:05 +01:00
Robert Davey
2c430c806c Fix ROI table comma and spacing
THanks to `@topdollar` in discord for noticing the typos.
2023-01-02 15:54:49 +00:00
Robert Caulk
52dfb0452c Update freqai-feature-engineering.md 2023-01-02 16:06:54 +01:00
Matthias
72f9c248f5 Merge pull request #7961 from freqtrade/dependabot/pip/develop/time-machine-2.9.0
Bump time-machine from 2.8.2 to 2.9.0
2023-01-02 09:21:55 +01:00
Matthias
5bb1f4a845 Merge pull request #7962 from freqtrade/dependabot/pip/develop/pydantic-1.10.4
Bump pydantic from 1.10.2 to 1.10.4
2023-01-02 08:26:14 +01:00
Matthias
d1a0ae45e8 Merge pull request #7960 from freqtrade/dependabot/pip/develop/filelock-3.9.0
Bump filelock from 3.8.2 to 3.9.0
2023-01-02 08:25:11 +01:00
dependabot[bot]
724465c798 Bump pydantic from 1.10.2 to 1.10.4
Bumps [pydantic](https://github.com/pydantic/pydantic) from 1.10.2 to 1.10.4.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/v1.10.4/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v1.10.2...v1.10.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-02 03:01:07 +00:00
dependabot[bot]
488b4512e0 Bump time-machine from 2.8.2 to 2.9.0
Bumps [time-machine](https://github.com/adamchainz/time-machine) from 2.8.2 to 2.9.0.
- [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.8.2...2.9.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-02 03:01:00 +00:00
dependabot[bot]
d304f95c13 Bump filelock from 3.8.2 to 3.9.0
Bumps [filelock](https://github.com/tox-dev/py-filelock) from 3.8.2 to 3.9.0.
- [Release notes](https://github.com/tox-dev/py-filelock/releases)
- [Changelog](https://github.com/tox-dev/py-filelock/blob/main/docs/changelog.rst)
- [Commits](https://github.com/tox-dev/py-filelock/compare/3.8.2...3.9.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-02 03:00:55 +00:00
Matthias
74b924471a type ccxt_compat tests 2022-12-31 10:59:42 +01:00
Matthias
cd7bd9bf9a Update gate liquidation price link 2022-12-31 10:25:21 +01:00
Matthias
6498e352c1 Remove pointless default 2022-12-31 10:23:39 +01:00
Matthias
97e8bb09e8 Update exchange documentation with note about leverage 2022-12-31 10:17:30 +01:00
Stefano Ariestasia
5188464fc0 fix typo 2022-12-31 02:03:02 +09:00
Wagner Costa
c8aa7720a2 added again feature check in BT from pred files 2022-12-30 11:16:35 -03:00
Wagner Costa
b39fc6b924 remove add pair to column from docs, fix keyerror bug and adjust hybrid strategy example 2022-12-30 10:42:31 -03:00
robcaulk
b2bab68fba move price assignment to feature_engineering_standard() to reduce un-requested feature additions in RL. Ensure old method of price assignment still works, add deprecation warning to help users migrate their strategies 2022-12-30 13:02:39 +01:00
Matthias
798438df9d Extract funding-rate call to separate method
this will allow overwriting in subclasses.
2022-12-30 07:32:59 +01:00
Matthias
499cc5bae1 Better visualize downloaded candletype in debug mode 2022-12-30 07:15:24 +01:00
Wagner Costa
2e30bdb9b2 freqai bt - fix tests 2022-12-29 16:35:11 -03:00
Matthias
9a46613975 Merge pull request #7954 from freqtrade/new_release
New release 2022.12
2022-12-29 17:45:08 +01:00
Wagner Costa
2b89f643b7 adjust backtest to new feature engineering functions 2022-12-28 19:03:41 -03:00
Matthias
c78b2080cc Add exception test for interest function 2022-12-28 17:42:35 +01:00
Matthias
6ef15802eb make tables an optional dependency
requirements will still install this though.
2022-12-28 16:04:21 +01:00
Matthias
973cfd0182 Merge pull request #7810 from stash86/bt-metrics
Add more calculations for backtest metrics
2022-12-28 15:57:07 +01:00
Matthias
f0bd6b9589 Merge pull request #7939 from freqtrade/dependabot/pip/develop/tables-3.8.0
Bump tables from 3.7.0 to 3.8.0
2022-12-28 15:55:43 +01:00
Matthias
2805e83c9f Bump Develop version to 2023.1 2022-12-28 15:53:43 +01:00
Matthias
8e8f71ade5 Version bump 2022.12 2022-12-28 15:42:38 +01:00
Matthias
149539d3f9 Merge branch 'stable' into new_release 2022-12-28 15:42:29 +01:00
Matthias
5cb8fe1a50 Add JOSS badge to freqtrade docs and readme.md 2022-12-28 15:40:12 +01:00
Matthias
c52910f28b Improve resiliance against invalid data
closes #7947
2022-12-28 15:30:57 +01:00
Matthias
6434bf6745 Document new backtesting metrics 2022-12-28 15:29:55 +01:00
Matthias
32bbe603cb Fix sortino std calculation 2022-12-28 14:59:49 +01:00
robcaulk
6f7eb71bbb ensure RL works with new naming scheme 2022-12-28 14:52:33 +01:00
Matthias
d5b516842c Fix 2 docstrings 2022-12-28 14:44:23 +01:00
Matthias
f21185d1c4 Add tests for new metrics 2022-12-28 14:05:04 +01:00
Matthias
02eb00fa33 Merge branch 'develop' into pr/stash86/7810 2022-12-28 14:04:54 +01:00
robcaulk
c2936d551b improve doc, update test strats, change function names 2022-12-28 13:25:40 +01:00
Matthias
4d112def17 Remove binance AD from docs page
fixes #7921
2022-12-28 07:10:11 +01:00
Matthias
cd4faa9c59 keep max_stake_amount through backtests 2022-12-27 18:08:20 +01:00
Wagner Costa
8227b4aafe freqAI Strategy - improve user experience 2022-12-27 11:37:01 -03:00
Matthias
62c4675e29 Remove some deprecated fields from the API 2022-12-27 14:28:07 +01:00
Matthias
cb66663fd2 show max_stake_amount in API 2022-12-27 14:28:07 +01:00
Matthias
55001bf321 Keep max_stake_amount (only relevant for DCA orders). 2022-12-27 14:28:07 +01:00
Matthias
6f2c3e2528 Split migration and persistence tests 2022-12-27 14:28:07 +01:00
Matthias
2d6ca5c8bf Merge pull request #7949 from freqtrade/freqai-doc-update
Improve `purge_old_models` explanation
2022-12-27 13:25:58 +01:00
Robert Caulk
20901c833a Improve purge_old_models explanation 2022-12-27 10:08:09 +01:00
Matthias
8a37eba0d9 Merge pull request #7946 from freqtrade/dependabot/pip/develop/numpy-1.24.1
Bump numpy from 1.23.5 to 1.24.1
2022-12-26 20:50:26 +01:00
Matthias
882e68c68b Rename backtest-result from new to "not new". 2022-12-26 15:33:14 +01:00
Matthias
6a15a9b412 Update backtest-result_new
fixing the calculation of profit_abs - which was incorrect previously.
2022-12-26 15:33:14 +01:00
dependabot[bot]
1cef40a134 Bump numpy from 1.23.5 to 1.24.1
Bumps [numpy](https://github.com/numpy/numpy) from 1.23.5 to 1.24.1.
- [Release notes](https://github.com/numpy/numpy/releases)
- [Changelog](https://github.com/numpy/numpy/blob/main/doc/RELEASE_WALKTHROUGH.rst)
- [Commits](https://github.com/numpy/numpy/compare/v1.23.5...v1.24.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-26 14:31:47 +00:00
Matthias
e881175cc4 Merge pull request #7945 from freqtrade/dependabot/pip/develop/ccxt-2.4.60
Bump ccxt from 2.4.27 to 2.4.60
2022-12-26 15:30:51 +01:00
Matthias
63f114395a is_short should be a boolean 2022-12-26 14:02:47 +01:00
dependabot[bot]
aaeeb86622 Bump ccxt from 2.4.27 to 2.4.60
Bumps [ccxt](https://github.com/ccxt/ccxt) from 2.4.27 to 2.4.60.
- [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/2.4.27...2.4.60)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-26 12:40:26 +00:00
Matthias
19913e8dc5 Merge pull request #7940 from freqtrade/dependabot/pip/develop/isort-5.11.4
Bump isort from 5.11.3 to 5.11.4
2022-12-26 13:39:39 +01:00
dependabot[bot]
d60b38dad2 Bump tables from 3.7.0 to 3.8.0
Bumps [tables](https://github.com/PyTables/PyTables) from 3.7.0 to 3.8.0.
- [Release notes](https://github.com/PyTables/PyTables/releases)
- [Changelog](https://github.com/PyTables/PyTables/blob/master/RELEASE_NOTES.rst)
- [Commits](https://github.com/PyTables/PyTables/compare/v3.7.0...v3.8.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-26 09:04:53 +00:00
Matthias
d01def3c61 Merge pull request #7941 from freqtrade/dependabot/pip/develop/pre-commit-2.21.0
Bump pre-commit from 2.20.0 to 2.21.0
2022-12-26 10:03:25 +01:00
Matthias
faab4b2342 Merge pull request #7943 from freqtrade/dependabot/pip/develop/types-requests-2.28.11.7
Bump types-requests from 2.28.11.5 to 2.28.11.7
2022-12-26 10:02:49 +01:00
dependabot[bot]
c5b246af80 Bump isort from 5.11.3 to 5.11.4
Bumps [isort](https://github.com/pycqa/isort) from 5.11.3 to 5.11.4.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.11.3...5.11.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-26 08:24:40 +00:00
Matthias
9296ad23d9 Merge pull request #7938 from freqtrade/dependabot/pip/develop/nbconvert-7.2.7
Bump nbconvert from 7.2.6 to 7.2.7
2022-12-26 09:21:43 +01:00
Matthias
00112d81d2 Bump types-requests pre-commit 2022-12-26 09:21:18 +01:00
Matthias
9a556d2639 Remove all mac conflicts 2022-12-26 08:57:01 +01:00
Matthias
18709406c5 use link overwrite 2022-12-26 08:50:55 +01:00
Matthias
9ea8792d3c Attempt brew fix 2022-12-26 08:45:02 +01:00
dependabot[bot]
3993bd7c1c Bump types-requests from 2.28.11.5 to 2.28.11.7
Bumps [types-requests](https://github.com/python/typeshed) from 2.28.11.5 to 2.28.11.7.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-26 03:01:11 +00:00
dependabot[bot]
e0f60e175f Bump pre-commit from 2.20.0 to 2.21.0
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.20.0 to 2.21.0.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v2.20.0...v2.21.0)

---
updated-dependencies:
- dependency-name: pre-commit
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-26 03:01:00 +00:00
dependabot[bot]
b1bf6d8dc9 Bump nbconvert from 7.2.6 to 7.2.7
Bumps [nbconvert](https://github.com/jupyter/nbconvert) from 7.2.6 to 7.2.7.
- [Release notes](https://github.com/jupyter/nbconvert/releases)
- [Changelog](https://github.com/jupyter/nbconvert/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jupyter/nbconvert/compare/v7.2.6...v7.2.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-26 03:00:41 +00:00
Stefano Ariestasia
6353f3ac1a fix formulas and implement new metrics 2022-12-26 08:19:51 +09:00
Matthias
7a5439321c Show new metrics in backtesting 2022-12-25 21:29:37 +01:00
Matthias
ce13ce4b10 Update binance stoploss order types
closes #7927
an update to the most recent ccxt version (>2.4.55) would have the same effect.
2022-12-25 09:05:53 +01:00
Matthias
4601705814 Merge pull request #7923 from freqtrade/freqai_backtest
Freqai backtest
2022-12-23 19:17:12 +01:00
Matthias
524da3c7ab Don't actually load models to avoid random failures 2022-12-23 16:19:12 +01:00
Matthias
ad0d7c9a9e Don't allow DCA trades to go beyond max order size
closes  #7924
2022-12-23 16:09:35 +01:00
Matthias
2a7369b56a fix macos CI 2022-12-23 07:38:33 +01:00
Matthias
73792fd6ce Don't attempt to convert None to dict 2022-12-21 06:28:55 +01:00
Matthias
70531224e6 Allow setting identifier via UI 2022-12-20 19:44:01 +01:00
Matthias
07606a9e23 Simplify APi backtest config merging 2022-12-20 19:32:29 +01:00
Matthias
6d9f1fafb7 allow backtest_cache to be provided via backtest API 2022-12-20 19:20:39 +01:00
Matthias
256fac2a2b Add test for freqaimodels endpoint 2022-12-20 07:24:54 +01:00
Matthias
5dbd5c235a Add endpoint for freqAI models 2022-12-20 07:24:54 +01:00
Matthias
3012c55ec5 Merge pull request #7867 from Bloodhunter4rc/remotepairlist
Add Remotepairlist
2022-12-19 19:28:49 +01:00
Matthias
a119fbd895 Small error-message finetuning 2022-12-19 18:19:55 +01:00
Bloodhunter4rc
ebf60d85da self._init_done placed wrong. fixed 2022-12-19 16:25:22 +01:00
Bloodhunter4rc
43f5a16006 parse exception handling, remove info, cache change 2022-12-19 15:36:28 +01:00
Robert Caulk
cc30210b3f Merge pull request #7908 from freqtrade/add-3action-rl-env
Add 3 Action RL Env
2022-12-19 14:47:57 +01:00
Matthias
095bedf54e Merge pull request #7915 from freqtrade/dependabot/pip/develop/blosc-1.11.1
Bump blosc from 1.10.6 to 1.11.1
2022-12-19 14:12:00 +01:00
Matthias
4bad2b5c04 Apply suggestions from code review
Co-authored-by: Emre <aemr3@users.noreply.github.com>
2022-12-19 13:27:07 +01:00
robcaulk
5b9e3af276 improve wording 2022-12-19 12:22:15 +01:00
robcaulk
5405d8fa6f add discussion and tips for Base3ActionRLEnvironment 2022-12-19 12:14:53 +01:00
robcaulk
a276ef4b06 ensure long only RL is tested 2022-12-19 11:49:31 +01:00
Matthias
ec3d49ce4c Merge pull request #7916 from freqtrade/dependabot/pip/develop/types-python-dateutil-2.8.19.5
Bump types-python-dateutil from 2.8.19.4 to 2.8.19.5
2022-12-19 11:20:21 +01:00
Matthias
86b30d2d66 Improve emc test resiliancy 2022-12-19 07:01:32 +01:00
Matthias
2711605df6 Merge pull request #7914 from freqtrade/dependabot/pip/develop/isort-5.11.3
Bump isort from 5.10.1 to 5.11.3
2022-12-19 06:59:28 +01:00
Matthias
daf7653988 Merge pull request #7918 from freqtrade/dependabot/pip/develop/torch-1.13.1
Bump torch from 1.13.0 to 1.13.1
2022-12-19 06:40:27 +01:00
Matthias
cc0d8fa590 Merge pull request #7920 from freqtrade/dependabot/pip/develop/ccxt-2.4.27
Bump ccxt from 2.2.92 to 2.4.27
2022-12-19 06:36:46 +01:00
Matthias
0c8d657d92 update types-dateutil precommit 2022-12-19 06:27:38 +01:00
dependabot[bot]
fa87e08071 Bump ccxt from 2.2.92 to 2.4.27
Bumps [ccxt](https://github.com/ccxt/ccxt) from 2.2.92 to 2.4.27.
- [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/2.2.92...2.4.27)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-19 03:01:26 +00:00
dependabot[bot]
7216d140de Bump torch from 1.13.0 to 1.13.1
Bumps [torch](https://github.com/pytorch/pytorch) from 1.13.0 to 1.13.1.
- [Release notes](https://github.com/pytorch/pytorch/releases)
- [Changelog](https://github.com/pytorch/pytorch/blob/master/RELEASE.md)
- [Commits](https://github.com/pytorch/pytorch/compare/v1.13.0...v1.13.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-19 03:01:09 +00:00
dependabot[bot]
06225b9501 Bump types-python-dateutil from 2.8.19.4 to 2.8.19.5
Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.8.19.4 to 2.8.19.5.
- [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-12-19 03:00:54 +00:00
dependabot[bot]
d86885c7f9 Bump blosc from 1.10.6 to 1.11.1
Bumps [blosc](https://github.com/blosc/python-blosc) from 1.10.6 to 1.11.1.
- [Release notes](https://github.com/blosc/python-blosc/releases)
- [Changelog](https://github.com/Blosc/python-blosc/blob/main/RELEASE_NOTES.rst)
- [Commits](https://github.com/blosc/python-blosc/compare/v1.10.6...v1.11.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-19 03:00:46 +00:00
dependabot[bot]
b61fc161bf Bump isort from 5.10.1 to 5.11.3
Bumps [isort](https://github.com/pycqa/isort) from 5.10.1 to 5.11.3.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.10.1...5.11.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-19 03:00:43 +00:00
Bloodhunter4rc
6380c3d462 reduce duplicate code, fix cache check 2022-12-18 23:37:18 +01:00
Bloodhunter4rc
bb33b96ba7 init cache on first iteration, init checks, limit length and charmap to info replace if invalid, move filter logic 2022-12-18 22:28:12 +01:00
Matthias
1f4cc145c4 Move trade docs to advanced section 2022-12-18 20:02:38 +01:00
Matthias
eda72ef26c Add documentation for Order object 2022-12-18 19:40:49 +01:00
Matthias
a439488b74 Add initial trade_object documentation 2022-12-18 17:42:05 +01:00
Matthias
bad6fe77d3 Remove deprecated trade property 2022-12-18 17:21:50 +01:00
Matthias
cb81613aa5 Merge pull request #7907 from freqtrade/add-joss-citation
Add JOSS citation to freqai doc
2022-12-17 19:22:35 +01:00
Robert Caulk
329a0a3f45 Update docs/freqai.md
Co-authored-by: Matthias <xmatthias@outlook.com>
2022-12-17 18:43:20 +01:00
Emre
c293401b22 Add can_short to freqai base model 2022-12-16 23:19:08 +03:00
Emre
e604047158 Enable RL tests on arm mac 2022-12-16 22:57:55 +03:00
Emre
a8c9aa01fb Add 3ac test 2022-12-16 22:31:44 +03:00
Emre
7727f31507 Add 3 Action RL env 2022-12-16 22:18:49 +03:00
Emre
dde363343c Add can_short param to base env 2022-12-16 22:16:19 +03:00
Robert Caulk
439914caef Merge pull request #7906 from initrv/fix-base-env-done-condition
fix base4 env done condition
2022-12-16 15:25:58 +01:00
robcaulk
e4284f4e7b add citation to freqai doc. Update credits 2022-12-16 15:20:46 +01:00
initrv
36948e2a74 fix base4 env done condition 2022-12-16 14:14:05 +03:00
robcaulk
c9bc91c75b add shuffle_after_split option 2022-12-16 11:20:37 +01:00
Matthias
935275010f Remove some unused fixtures 2022-12-16 06:46:54 +01:00
Matthias
bc10bcaf61 Merge pull request #7901 from samgermain/delist-bibox
delisted bibox following ccxt PR https://github.com/ccxt/ccxt/pull/16067
2022-12-15 23:16:33 +01:00
Sam Germain
32d57f624e delisted bibox following ccxt PR https://github.com/ccxt/ccxt/pull/16067 2022-12-15 15:00:27 -05:00
Matthias
2828255435 Merge pull request #7842 from wizrds/feat/refactor-emc
Change to broadcasting single candles in Producer/Consumer
2022-12-15 19:47:29 +01:00
Matthias
6fa3db3a1d Fix failing tests 2022-12-15 19:36:21 +01:00
Matthias
b915872f66 Merge pull request #7899 from freqtrade/fix/multiproc-dp
Ensure data provider is passed to multiproc envs
2022-12-15 19:31:23 +01:00
Bloodhunter4rc
cd1b8b9cee single space removed for the unit test to pass.. 2022-12-15 18:14:37 +01:00
Bloodhunter4rc
9e20d13e50 Merge branch 'freqtrade:develop' into remotepairlist 2022-12-15 17:38:56 +01:00
Bloodhunter4rc
1d5c66da3b + Unit Tests 2022-12-15 17:38:21 +01:00
robcaulk
581a5296cc fix docstrings to reflect new env_info changes 2022-12-15 16:50:08 +01:00
robcaulk
7b4abd5ef5 use a dictionary to make code more readable 2022-12-15 12:25:33 +01:00
Matthias
7a0eadbdf5 Don't recalc profit on closed trades 2022-12-15 07:05:07 +01:00
Matthias
33dce5cf10 Clarify partial exit calculation messaging 2022-12-15 07:05:07 +01:00
Matthias
ca2a878b86 Update test naming 2022-12-14 20:06:55 +01:00
Emre
d3ad5cb722 Merge branch 'fix/multiproc-dp' of https://github.com/freqtrade/freqtrade into fix/multiproc-dp 2022-12-14 22:04:43 +03:00
Emre
3af2251ce8 Fix add_state_info backtesting bug 2022-12-14 22:03:23 +03:00
Emre
2018da0767 Add env_info dict to base environment 2022-12-14 22:03:05 +03:00
Matthias
fa260e6560 Move "replace or append" decision to dataprovider 2022-12-14 19:56:54 +01:00
robcaulk
dac1c8ab89 fix isort 2022-12-14 18:28:52 +01:00
robcaulk
2285ca7d2a add dp to multiproc 2022-12-14 18:22:20 +01:00
Matthias
350cebb0a8 Merge pull request #7898 from initrv/patch-1
fix doc minimal_roi
2022-12-14 12:56:51 +01:00
initrv
de19d1cfbb fix doc minimal_roi 2022-12-14 13:36:07 +03:00
Matthias
97fee37072 Improve emc test 2022-12-14 07:22:51 +01:00
Bloodhunter4rc
7f3524949c - print 2022-12-13 21:00:23 +01:00
Bloodhunter4rc
d52c1c7554 Add unit tests 2022-12-13 20:21:06 +01:00
Matthias
1d92db7805 Change CI to actually run one 2 randomized point. 2022-12-13 19:23:40 +01:00
Matthias
3c2a802ec0 Merge pull request #7897 from freqtrade/revert-7884-dependabot/pip/develop/scikit-learn-1.2.0
Revert "Bump scikit-learn from 1.1.3 to 1.2.0"
2022-12-13 19:23:19 +01:00
Matthias
fed46d330f Revert "Bump scikit-learn from 1.1.3 to 1.2.0" 2022-12-13 18:14:56 +01:00
Matthias
c042d0146e Don't run gc_setup during tests 2022-12-13 17:14:28 +00:00
Robert Caulk
e6da646e2f Merge pull request #7866 from initrv/cleanup-tensorboard-callback
Cleanup tensorboard callback
2022-12-13 09:05:46 +01:00
Timothy Pogue
0dd3836cc7 fix rpc method docstring 2022-12-12 22:47:35 -07:00
Matthias
1c0c4fd420 Improve test 2022-12-12 22:47:35 -07:00
Matthias
a693495a6d Improve external_candle aggregation 2022-12-12 22:47:35 -07:00
Matthias
96edd31458 Test add_external_candle 2022-12-12 22:47:35 -07:00
Timothy Pogue
414c0ce050 change unused var 2022-12-12 22:47:35 -07:00
Timothy Pogue
6717dff19b update overlapping candle handling, move append to misc 2022-12-12 22:47:35 -07:00
Timothy Pogue
0602479f7d minor changes, update candle appending to support overlaps 2022-12-12 22:47:35 -07:00
Timothy Pogue
f1ebaf4730 fix tests 2022-12-12 22:47:35 -07:00
Timothy Pogue
49f6f40662 remove comment 2022-12-12 22:47:35 -07:00
Timothy Pogue
0d5b2eed94 fix same candle handling 2022-12-12 22:47:35 -07:00
Timothy Pogue
d376bf4052 fix indefinite reconnecting 2022-12-12 22:47:35 -07:00
Timothy Pogue
ccd1aa70a2 change log calls to debug, handle already received candle 2022-12-12 22:47:35 -07:00
Timothy Pogue
c050eb8b8b add candle difference calculation to dataprovider 2022-12-12 22:47:35 -07:00
Timothy Pogue
89338fa677 allow specifying channel send throttle 2022-12-12 22:47:35 -07:00
Timothy Pogue
d2c8487ecf update add_external_candle, fix breaking on ping error, handle empty dataframes 2022-12-12 22:47:35 -07:00
Timothy Pogue
fce1e9d6d0 update analyzed df request to allow specifying a single pair 2022-12-12 22:47:35 -07:00
Timothy Pogue
36a00e8de0 update add_external_candle returns 2022-12-12 22:47:35 -07:00
Timothy Pogue
4cbb3341d7 change how missing candles will be handled 2022-12-12 22:47:35 -07:00
Timothy Pogue
9660e445b8 use new channel apis in emc, extend analyzed df to include list of dates for candles 2022-12-12 22:47:35 -07:00
Matthias
3e4e6bb114 Merge pull request #7895 from freqtrade/fix-blosc-error-arm64
Temporarily downgrade blosc for arm64
2022-12-12 20:03:43 +01:00
Matthias
abc3badfb5 Improve shutdown behavior
closes #7882
2022-12-12 20:01:54 +01:00
Emre
5c984bf5c2 Temporarily downgrade blosc for arm64 2022-12-12 21:33:12 +03:00
Matthias
b328a18a97 Merge pull request #7890 from freqtrade/dependabot/pip/develop/xgboost-1.7.2
Bump xgboost from 1.7.1 to 1.7.2
2022-12-12 18:18:45 +01:00
Matthias
ff0577445e Merge pull request #7886 from freqtrade/dependabot/pip/develop/prompt-toolkit-3.0.36
Bump prompt-toolkit from 3.0.33 to 3.0.36
2022-12-12 14:52:39 +01:00
Bloodhunter4rc
6f92c58e33 add docs, add bearer token. 2022-12-12 13:24:33 +01:00
initrv
f940280d5e Fix tensorboard_log incrementing note 2022-12-12 14:35:44 +03:00
initrv
f9b7d35900 add increment param for tensorboard_log 2022-12-12 14:14:23 +03:00
Bloodhunter4rc
f6b90595fa remove html. change var names. 2022-12-12 11:05:03 +01:00
Matthias
b53b3f435c Merge pull request #7888 from freqtrade/dependabot/pip/develop/ccxt-2.2.92
Bump ccxt from 2.2.67 to 2.2.92
2022-12-12 09:03:26 +01:00
Matthias
a55d0c0d81 Merge pull request #7891 from freqtrade/dependabot/pip/develop/python-telegram-bot-13.15
Bump python-telegram-bot from 13.14 to 13.15
2022-12-12 08:27:50 +01:00
Matthias
dee5b72835 Merge pull request #7892 from freqtrade/dependabot/pip/develop/filelock-3.8.2
Bump filelock from 3.8.0 to 3.8.2
2022-12-12 08:27:29 +01:00
Matthias
39bd6fb2d3 Merge pull request #7894 from freqtrade/dependabot/github_actions/develop/pypa/gh-action-pypi-publish-1.6.4
Bump pypa/gh-action-pypi-publish from 1.6.1 to 1.6.4
2022-12-12 07:11:34 +01:00
dependabot[bot]
de9784267a Bump filelock from 3.8.0 to 3.8.2
Bumps [filelock](https://github.com/tox-dev/py-filelock) from 3.8.0 to 3.8.2.
- [Release notes](https://github.com/tox-dev/py-filelock/releases)
- [Changelog](https://github.com/tox-dev/py-filelock/blob/main/docs/changelog.rst)
- [Commits](https://github.com/tox-dev/py-filelock/compare/3.8.0...3.8.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-12 05:39:16 +00:00
Matthias
61592e76b0 Merge pull request #7884 from freqtrade/dependabot/pip/develop/scikit-learn-1.2.0
Bump scikit-learn from 1.1.3 to 1.2.0
2022-12-12 06:38:29 +01:00
Matthias
dc8f68d410 Merge pull request #7885 from freqtrade/dependabot/pip/develop/blosc-1.11.0
Bump blosc from 1.10.6 to 1.11.0
2022-12-12 06:31:39 +01:00
dependabot[bot]
915e0ac62f Bump ccxt from 2.2.67 to 2.2.92
Bumps [ccxt](https://github.com/ccxt/ccxt) from 2.2.67 to 2.2.92.
- [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/2.2.67...2.2.92)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-12 05:31:01 +00:00
dependabot[bot]
bc2b9981d3 Bump python-telegram-bot from 13.14 to 13.15
Bumps [python-telegram-bot](https://github.com/python-telegram-bot/python-telegram-bot) from 13.14 to 13.15.
- [Release notes](https://github.com/python-telegram-bot/python-telegram-bot/releases)
- [Changelog](https://github.com/python-telegram-bot/python-telegram-bot/blob/v13.15/CHANGES.rst)
- [Commits](https://github.com/python-telegram-bot/python-telegram-bot/compare/v13.14...v13.15)

---
updated-dependencies:
- dependency-name: python-telegram-bot
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-12 05:30:55 +00:00
Matthias
686253e7cd Merge pull request #7887 from freqtrade/dependabot/pip/develop/nbconvert-7.2.6
Bump nbconvert from 7.2.5 to 7.2.6
2022-12-12 06:30:37 +01:00
Matthias
2d68b0f6f6 Merge pull request #7889 from freqtrade/dependabot/pip/develop/pytest-asyncio-0.20.3
Bump pytest-asyncio from 0.20.2 to 0.20.3
2022-12-12 06:30:14 +01:00
Matthias
f7a099f878 Merge pull request #7893 from freqtrade/dependabot/pip/develop/sqlalchemy-1.4.45
Bump sqlalchemy from 1.4.44 to 1.4.45
2022-12-12 06:29:49 +01:00
dependabot[bot]
2647c35f48 Bump pypa/gh-action-pypi-publish from 1.6.1 to 1.6.4
Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.6.1 to 1.6.4.
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.6.1...v1.6.4)

---
updated-dependencies:
- dependency-name: pypa/gh-action-pypi-publish
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-12 03:02:53 +00:00
dependabot[bot]
0344203372 Bump sqlalchemy from 1.4.44 to 1.4.45
Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 1.4.44 to 1.4.45.
- [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-12-12 03:01:32 +00:00
dependabot[bot]
5a7b493d3e Bump xgboost from 1.7.1 to 1.7.2
Bumps [xgboost](https://github.com/dmlc/xgboost) from 1.7.1 to 1.7.2.
- [Release notes](https://github.com/dmlc/xgboost/releases)
- [Changelog](https://github.com/dmlc/xgboost/blob/master/NEWS.md)
- [Commits](https://github.com/dmlc/xgboost/compare/v1.7.1...v1.7.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-12 03:01:11 +00:00
dependabot[bot]
5625648011 Bump pytest-asyncio from 0.20.2 to 0.20.3
Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.20.2 to 0.20.3.
- [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases)
- [Changelog](https://github.com/pytest-dev/pytest-asyncio/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.20.2...v0.20.3)

---
updated-dependencies:
- dependency-name: pytest-asyncio
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-12 03:01:07 +00:00
dependabot[bot]
a35111e55e Bump nbconvert from 7.2.5 to 7.2.6
Bumps [nbconvert](https://github.com/jupyter/nbconvert) from 7.2.5 to 7.2.6.
- [Release notes](https://github.com/jupyter/nbconvert/releases)
- [Changelog](https://github.com/jupyter/nbconvert/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jupyter/nbconvert/compare/v7.2.5...v7.2.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-12 03:00:54 +00:00
dependabot[bot]
63d3a9ced6 Bump prompt-toolkit from 3.0.33 to 3.0.36
Bumps [prompt-toolkit](https://github.com/prompt-toolkit/python-prompt-toolkit) from 3.0.33 to 3.0.36.
- [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.33...3.0.36)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-12 03:00:49 +00:00
dependabot[bot]
434eec7334 Bump blosc from 1.10.6 to 1.11.0
Bumps [blosc](https://github.com/blosc/python-blosc) from 1.10.6 to 1.11.0.
- [Release notes](https://github.com/blosc/python-blosc/releases)
- [Changelog](https://github.com/Blosc/python-blosc/blob/main/RELEASE_NOTES.rst)
- [Commits](https://github.com/blosc/python-blosc/compare/v1.10.6...v1.11.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-12 03:00:46 +00:00
dependabot[bot]
78c40f0535 Bump scikit-learn from 1.1.3 to 1.2.0
Bumps [scikit-learn](https://github.com/scikit-learn/scikit-learn) from 1.1.3 to 1.2.0.
- [Release notes](https://github.com/scikit-learn/scikit-learn/releases)
- [Commits](https://github.com/scikit-learn/scikit-learn/compare/1.1.3...1.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-12 03:00:40 +00:00
Matthias
42afdbb0e5 Merge pull request #7883 from freqtrade/fix/multioutput-bug
fix bug in MultiOutput* with conv_width = 1
2022-12-11 15:52:10 +01:00
robcaulk
0f6b98b69a merge develop into tensorboard cleanup 2022-12-11 15:38:32 +01:00
robcaulk
0fd8e214e4 add documentation for tensorboard_log, change how users interact with tensorboard_log 2022-12-11 15:31:29 +01:00
Matthias
888ba65367 Merge branch 'develop' into fix/multioutput-bug 2022-12-11 15:23:53 +01:00
initrv
cb8fc3c8c7 custom info to tensorboard_metrics 2022-12-11 15:37:45 +03:00
Robert Caulk
0f75ec9c97 Merge pull request #7860 from freqtrade/update-freqai-tf-handling
Ensure base tf to be include_timeframes
2022-12-11 12:50:07 +01:00
robcaulk
8c7ec07951 ensure predict_proba follows suit. Remove all lib specific params from example config 2022-12-11 12:39:31 +01:00
robcaulk
85f22b5c30 fix bug in MultiOutput* with conv_width = 1 2022-12-11 12:15:19 +01:00
Emre
6b9f3f2795 Fix test validation 2022-12-11 13:24:24 +03:00
Emre
272c3302e3 Merge remote-tracking branch 'origin/develop' into update-freqai-tf-handling 2022-12-11 13:12:45 +03:00
Matthias
980a5a9b52 Fix docs typo 2022-12-10 19:54:04 +01:00
Matthias
1da8ad69d9 improve more tests by freezing time 2022-12-08 14:33:16 +01:00
Matthias
da4914513a Merge pull request #7835 from rzhb/patch-1
update strategy_analysis_example.ipynb
2022-12-08 14:17:50 +01:00
Matthias
bbedc4b63e Stop clock to avoid random failures on slow CI runs 2022-12-08 14:15:29 +01:00
Matthias
39e19bd0c9 Merge pull request #7607 from matteoettam09/develop
Docker compose now in docker
2022-12-08 13:34:06 +01:00
Matthias
3d3a7033ed Improve Docker documentation wording 2022-12-08 08:46:16 +01:00
Matthias
fcbc1a8a07 Merge pull request #7868 from freqtrade/fix-add-state-info-bt
Fix add state info bt
2022-12-08 08:34:11 +01:00
Matthias
74e623fe5b Improve kraken test resiliance 2022-12-08 08:33:07 +01:00
Bloodhunter4rc
66412bfa58 Remove unnecessary loop 2022-12-08 01:51:12 +01:00
Bloodhunter4rc
7efcbbb457 Local File Loading 2022-12-08 01:09:17 +01:00
Bloodhunter4rc
da2747d487 Add Local .json file Loading 2022-12-08 00:52:54 +01:00
robcaulk
7b3406914c flip add_state_info 2022-12-07 19:49:39 +01:00
robcaulk
9b4364ddc3 ensure that add_state_info is deactivated during backtesting 2022-12-07 19:49:14 +01:00
Bloodhunter4rc
b144a6357d Remove Duplicate 2022-12-07 18:24:55 +01:00
Bloodhunter4rc
547a75d9c1 Fix Info 2022-12-07 17:49:21 +01:00
Bloodhunter4rc
607d5b2f8f Split to fetch_pairlist function, Info Message 2022-12-07 17:47:38 +01:00
Bloodhunter4rc
48160f3fe9 Flake 8 fix, Json Fetching 2022-12-07 17:01:45 +01:00
Bloodhunter4rc
199fd2d074 +Remote Pairlist 2022-12-07 15:08:33 +01:00
initrv
58604c747e cleanup tensorboard callback 2022-12-07 14:37:55 +03:00
Stefano Ariestasia
89c7c2fec6 isort fix 2022-12-07 18:09:57 +09:00
Stefano Ariestasia
611e35ed81 flake8 fix 2022-12-07 15:47:58 +09:00
Robert Caulk
b9f6911a6a Merge pull request #7843 from smarmau/develop
freqai RL agent info during training
2022-12-06 20:06:41 +01:00
Matthias
e7195b7bfb Merge pull request #7862 from freqtrade/ws_newcandle
New websocket message "new_candle"
2022-12-06 07:07:32 +01:00
Robert Caulk
27b8f462dc Merge pull request #7837 from freqtrade/freqai_bt_from_predictions_improvement
freqAI backtesting - Perfomance improvement
2022-12-05 23:20:55 +01:00
Wagner Costa
c81b00fb37 Merge branch 'develop' into freqai_bt_from_predictions_improvement 2022-12-05 18:00:55 -03:00
Emre
227cdb0938 Change dict update order 2022-12-05 23:58:04 +03:00
Emre
26a61afa15 Move base tf logic to config validation 2022-12-05 23:54:15 +03:00
Emre
bc48099e48 Revert changes 2022-12-05 23:52:48 +03:00
robcaulk
62c69bf2b5 fix custom_info 2022-12-05 20:22:54 +01:00
Matthias
72472587dd Increase test range for api version test 2022-12-05 20:19:01 +01:00
Matthias
7c27eedda5 Bump API version 2022-12-05 19:56:33 +01:00
Matthias
24edc276ea Simplify new_candle message 2022-12-05 19:46:39 +01:00
Matthias
d30a872ed4 Move message-silencing list next to enum 2022-12-05 19:23:03 +01:00
Matthias
687eefa06e Improve emit_df testcase 2022-12-05 18:19:19 +01:00
Matthias
5e533b550f Emit a simple "new candle" message to allow UI's to refresh charts 2022-12-05 18:19:19 +01:00
Matthias
189fa64052 Add more dynamic to directory change 2022-12-05 18:14:16 +01:00
Emre
730fba956b Ensure base tf included in include_timeframes 2022-12-05 16:16:17 +03:00
Emre
e734b39929 Make model_training_parameters optional 2022-12-05 14:54:42 +03:00
Matthias
b0f430b5ac Merge pull request #7850 from freqtrade/dependabot/pip/develop/pytest-random-order-1.1.0
Bump pytest-random-order from 1.0.4 to 1.1.0
2022-12-05 08:50:52 +01:00
Matthias
261f9ac7dc Merge pull request #7851 from freqtrade/dependabot/pip/develop/ccxt-2.2.67
Bump ccxt from 2.2.36 to 2.2.67
2022-12-05 08:06:16 +01:00
Matthias
80f3908626 Merge pull request #7857 from freqtrade/dependabot/pip/develop/mkdocs-material-8.5.11
Bump mkdocs-material from 8.5.10 to 8.5.11
2022-12-05 08:00:23 +01:00
Matthias
4dfb35c165 Merge pull request #7858 from freqtrade/dependabot/pip/develop/orjson-3.8.3
Bump orjson from 3.8.2 to 3.8.3
2022-12-05 08:00:08 +01:00
Matthias
6e657f9911 Merge pull request #7859 from freqtrade/dependabot/github_actions/develop/pypa/gh-action-pypi-publish-1.6.1
Bump pypa/gh-action-pypi-publish from 1.5.1 to 1.6.1
2022-12-05 06:27:37 +01:00
dependabot[bot]
102ab91fa4 Bump orjson from 3.8.2 to 3.8.3
Bumps [orjson](https://github.com/ijl/orjson) from 3.8.2 to 3.8.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.8.2...3.8.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-12-05 05:23:02 +00:00
dependabot[bot]
179adea0e2 Bump ccxt from 2.2.36 to 2.2.67
Bumps [ccxt](https://github.com/ccxt/ccxt) from 2.2.36 to 2.2.67.
- [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/2.2.36...2.2.67)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-05 05:22:42 +00:00
Matthias
d456ec7d5e Merge pull request #7856 from freqtrade/dependabot/pip/develop/fastapi-0.88.0
Bump fastapi from 0.87.0 to 0.88.0
2022-12-05 06:22:18 +01:00
Matthias
0bb4f108dd Merge pull request #7853 from freqtrade/dependabot/pip/develop/pandas-1.5.2
Bump pandas from 1.5.1 to 1.5.2
2022-12-05 06:21:46 +01:00
dependabot[bot]
82d4dca183 Bump mkdocs-material from 8.5.10 to 8.5.11
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 8.5.10 to 8.5.11.
- [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.5.10...8.5.11)

---
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-12-05 05:21:15 +00:00
Matthias
cf0e5903c5 Merge pull request #7852 from freqtrade/dependabot/pip/develop/pymdown-extensions-9.9
Bump pymdown-extensions from 9.8 to 9.9
2022-12-05 06:20:23 +01:00
Matthias
4d19f98bef Merge pull request #7855 from freqtrade/dependabot/pip/develop/jsonschema-4.17.3
Bump jsonschema from 4.17.1 to 4.17.3
2022-12-05 06:19:43 +01:00
dependabot[bot]
2eb8f9f028 Bump pypa/gh-action-pypi-publish from 1.5.1 to 1.6.1
Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.5.1 to 1.6.1.
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.5.1...v1.6.1)

---
updated-dependencies:
- dependency-name: pypa/gh-action-pypi-publish
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-05 03:03:47 +00:00
dependabot[bot]
66bb2c5253 Bump fastapi from 0.87.0 to 0.88.0
Bumps [fastapi](https://github.com/tiangolo/fastapi) from 0.87.0 to 0.88.0.
- [Release notes](https://github.com/tiangolo/fastapi/releases)
- [Commits](https://github.com/tiangolo/fastapi/compare/0.87.0...0.88.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-05 03:01:16 +00:00
dependabot[bot]
caae4441e5 Bump jsonschema from 4.17.1 to 4.17.3
Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.17.1 to 4.17.3.
- [Release notes](https://github.com/python-jsonschema/jsonschema/releases)
- [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.17.1...v4.17.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-05 03:01:12 +00:00
dependabot[bot]
441069f363 Bump pandas from 1.5.1 to 1.5.2
Bumps [pandas](https://github.com/pandas-dev/pandas) from 1.5.1 to 1.5.2.
- [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.5.1...v1.5.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-05 03:01:03 +00:00
dependabot[bot]
16bad8dca6 Bump pymdown-extensions from 9.8 to 9.9
Bumps [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions) from 9.8 to 9.9.
- [Release notes](https://github.com/facelessuser/pymdown-extensions/releases)
- [Commits](https://github.com/facelessuser/pymdown-extensions/compare/9.8...9.9)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-05 03:00:56 +00:00
dependabot[bot]
133a081a39 Bump pytest-random-order from 1.0.4 to 1.1.0
Bumps [pytest-random-order](https://github.com/jbasko/pytest-random-order) from 1.0.4 to 1.1.0.
- [Release notes](https://github.com/jbasko/pytest-random-order/releases)
- [Commits](https://github.com/jbasko/pytest-random-order/compare/v1.0.4...v1.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-05 03:00:39 +00:00
Robert Caulk
f28b314266 Merge pull request #7849 from smarmau/patch-1
Update freqai-reinforcement-learning.md
2022-12-04 15:17:01 +01:00
robcaulk
d8565261e1 ignore initializer type 2022-12-04 14:10:33 +01:00
robcaulk
24766928ba reorganize/generalize tensorboard callback 2022-12-04 13:54:30 +01:00
Matthias
24d8585c33 Merge pull request #7840 from freqtrade/feature-plot-dir
Add plot_feature_importances output dir to docs
2022-12-04 12:53:44 +01:00
smarmau
f7b4fc5bbc Update freqai-reinforcement-learning.md
Change typo of default Tensorboard port to reflect correct port (6006)
2022-12-04 22:22:23 +11:00
robcaulk
38d3b4cab2 add details to doc plot_feature_importance doc 2022-12-04 11:29:21 +01:00
Matthias
310eba5932 Merge pull request #7735 from freqtrade/gc_improvements
Improve python GC behavior
2022-12-03 15:54:59 +01:00
smarmau
b2edc58089 fix flake8 2022-12-03 22:31:02 +11:00
smarmau
d6f45a12ae add multiproc fix flake8 2022-12-03 22:30:04 +11:00
smarmau
469aa0d43f add state/action info to callbacks 2022-12-03 21:16:46 +11:00
smarmau
075c8c23c8 add state/action info to callbacks 2022-12-03 21:16:04 +11:00
Matthias
0be82b4ed1 Merge pull request #7818 from freqtrade/dependabot/pip/develop/torch-1.13.0
Bump torch from 1.12.1 to 1.13.0
2022-12-02 15:52:34 +01:00
Robert Caulk
7ddf7ec0ae Update freqai-parameter-table.md 2022-12-02 11:28:00 +01:00
Matthias
4dc591a170 Merge pull request #7834 from freqtrade/fix-data-drawer-model-load
Fix sb3_contrib loading issue
2022-12-02 06:29:23 +01:00
Matthias
f2624112b0 Merge pull request #7833 from gaugau3000/develop
binance restricted locations and server location
2022-12-02 06:20:35 +01:00
Matthias
8a078a328e Merge pull request #7836 from freqtrade/fix-fees-rl
fix fees RL
2022-12-02 06:15:20 +01:00
Matthias
05424045b0 Temporarily disable since binance blocks US 2022-12-02 06:12:21 +01:00
Wagner Costa
77dc2c92a7 performance improvevemnts - backtest freqai from saved predictions 2022-12-01 12:53:19 -03:00
robcaulk
aceee67e2b Merge remote-tracking branch 'origin/develop' into gc_improvements 2022-12-01 14:32:19 +01:00
robcaulk
2b3e166dc2 fix fees RL 2022-12-01 10:10:28 +01:00
k
eb81cccede add download-data command
change directory
fix relative config path
2022-12-01 16:37:24 +08:00
Emre
396e666e9b Keep old behavior of model loading 2022-12-01 11:03:51 +03:00
Emre
4a9982f86b Fix sb3_contrib loading issue 2022-12-01 10:08:42 +03:00
Matthias
95651fcd5a Improve/simplify telegram exception handling
Move exceptionhandling to the decorator.
2022-12-01 06:27:25 +01:00
gautier pialat
59c7ce02f5 binance restricted locations and server location
Inform end user before he creates server in a binance restricted location
https://github.com/ccxt/ccxt/issues/15872
2022-11-30 21:29:34 +01:00
Matthias
dac4a35be2 Merge pull request #7828 from freqtrade/fix-state-info-rl
bring back market side setting in get_state_info
2022-11-30 19:57:28 +01:00
Robert Caulk
2bcd8e4e21 Merge pull request #7737 from freqtrade/backtest_fitlivepredictions
FreqAI - Backtesting enhancements and bug fix
2022-11-30 16:51:04 +01:00
Wagner Costa
79821ebb33 fix flake8 errors 2022-11-30 08:41:44 -03:00
robcaulk
e7f72d52b8 bring back market side setting in get_state_info 2022-11-30 12:36:26 +01:00
Wagner Costa
26e8a5766f Merge branch 'develop' into backtest_fitlivepredictions 2022-11-30 08:29:28 -03:00
Wagner Costa
17cf3c7e83 bug fixes and removed fillna from fit_live_predictions 2022-11-30 08:28:45 -03:00
Matthias
915524a161 Merge pull request #7827 from rzhb/patch-2
Update data-analysis.md
2022-11-30 06:45:27 +01:00
rzhb
10a45474e8 Update data-analysis.md
fix typo in code
2022-11-30 12:28:21 +08:00
robcaulk
4571aedb33 consolidate and clean code 2022-11-30 00:53:35 +01:00
Matthias
3c322bf7df Improve forceenter validation messages 2022-11-29 18:27:08 +01:00
Matthias
e6b8cb8ea9 Merge pull request #7795 from froggleston/entry_exit_date_print
Add date selection arguments to backtest-analysis printout
2022-11-29 16:56:58 +01:00
Wagner Costa
8ea58ab352 change BT prediction files to feather format 2022-11-29 10:38:35 -03:00
Wagner Costa
df979ece33 Merge branch 'develop' into backtest_fitlivepredictions 2022-11-29 09:39:15 -03:00
dependabot[bot]
b87545cd12 Bump torch from 1.12.1 to 1.13.0
Bumps [torch](https://github.com/pytorch/pytorch) from 1.12.1 to 1.13.0.
- [Release notes](https://github.com/pytorch/pytorch/releases)
- [Changelog](https://github.com/pytorch/pytorch/blob/master/RELEASE.md)
- [Commits](https://github.com/pytorch/pytorch/compare/v1.12.1...v1.13.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-29 07:46:38 +00:00
Robert Caulk
066d040fd3 Merge pull request #7814 from freqtrade/dependabot/pip/develop/sb3-contrib-1.6.2
Bump sb3-contrib from 1.6.1 to 1.6.2
2022-11-29 08:45:50 +01:00
Matthias
c3daddc629 Merge pull request #7809 from richardjozsa/develop
Improve the RL learning process
2022-11-29 06:28:36 +01:00
Matthias
100d65b20b Merge pull request #7822 from eltociear/patch-1
Fix typo in strategy_analysis_example.md
2022-11-29 06:24:36 +01:00
Matthias
5500c10f78 Improve CI file layout 2022-11-28 20:41:26 +01:00
Matthias
2c75b5e027 Extract "live" test from regular tests 2022-11-28 20:41:26 +01:00
Matthias
8efa8bc78a Update stable-baselines3 to 1.6.2 2022-11-28 19:35:17 +01:00
Matthias
e891c41760 Fix typo in ipynb, too. 2022-11-28 18:20:30 +01:00
Robert Caulk
c9cc87b4ac Merge pull request #7823 from freqtrade/fix/rl-model-type
Set model_type in base RL model
2022-11-28 18:07:36 +01:00
Emre
9cbfa12011 Directly set model_type in base RL model 2022-11-28 16:02:17 +03:00
Robert Davey
05a7fca242 Fix utils docs for backtesting-analysis 2022-11-28 12:12:45 +00:00
Matthias
1cdf5e0cfd Merge pull request #7812 from freqtrade/dependabot/pip/develop/jsonschema-4.17.1
Bump jsonschema from 4.17.0 to 4.17.1
2022-11-28 10:06:12 +01:00
Ikko Ashimine
9880e9ab60 Fix typo in strategy_analysis_example.md
seperate -> separate
2022-11-28 17:10:17 +09:00
Matthias
d67ca27f5e Merge pull request #7817 from freqtrade/dependabot/pip/develop/prompt-toolkit-3.0.33
Bump prompt-toolkit from 3.0.32 to 3.0.33
2022-11-28 08:12:11 +01:00
dependabot[bot]
dc03317cc8 Bump jsonschema from 4.17.0 to 4.17.1
Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.17.0 to 4.17.1.
- [Release notes](https://github.com/python-jsonschema/jsonschema/releases)
- [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.17.0...v4.17.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-28 07:02:54 +00:00
Matthias
f7ba1a4348 Merge pull request #7819 from freqtrade/dependabot/pip/develop/cryptography-38.0.4
Bump cryptography from 38.0.1 to 38.0.4
2022-11-28 08:02:22 +01:00
Matthias
98883fc909 Merge pull request #7815 from freqtrade/dependabot/pip/develop/urllib3-1.26.13
Bump urllib3 from 1.26.12 to 1.26.13
2022-11-28 08:01:10 +01:00
Matthias
40b274351c Merge pull request #7813 from freqtrade/dependabot/pip/develop/flake8-6.0.0
Bump flake8 from 5.0.4 to 6.0.0
2022-11-28 08:00:45 +01:00
Matthias
868c2061b7 Merge pull request #7816 from freqtrade/dependabot/pip/develop/pyarrow-10.0.1
Bump pyarrow from 10.0.0 to 10.0.1
2022-11-28 06:40:38 +01:00
Matthias
d73fd42769 Fix flake8 error introduced with 6.0 update 2022-11-28 06:38:35 +01:00
dependabot[bot]
9c28cc810d Bump cryptography from 38.0.1 to 38.0.4
Bumps [cryptography](https://github.com/pyca/cryptography) from 38.0.1 to 38.0.4.
- [Release notes](https://github.com/pyca/cryptography/releases)
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/38.0.1...38.0.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-28 05:33:45 +00:00
Matthias
8e60364f0d Merge pull request #7808 from freqtrade/fix-freqai-rl-reward-link
Fix custom reward function link
2022-11-28 06:33:24 +01:00
Matthias
51e773fe37 Merge pull request #7820 from freqtrade/dependabot/pip/develop/ccxt-2.2.36
Bump ccxt from 2.1.96 to 2.2.36
2022-11-28 06:32:17 +01:00
dependabot[bot]
348731598e Bump ccxt from 2.1.96 to 2.2.36
Bumps [ccxt](https://github.com/ccxt/ccxt) from 2.1.96 to 2.2.36.
- [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/2.1.96...2.2.36)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-28 03:01:25 +00:00
dependabot[bot]
a46b09d400 Bump prompt-toolkit from 3.0.32 to 3.0.33
Bumps [prompt-toolkit](https://github.com/prompt-toolkit/python-prompt-toolkit) from 3.0.32 to 3.0.33.
- [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.32...3.0.33)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-28 03:01:01 +00:00
dependabot[bot]
924bbad199 Bump pyarrow from 10.0.0 to 10.0.1
Bumps [pyarrow](https://github.com/apache/arrow) from 10.0.0 to 10.0.1.
- [Release notes](https://github.com/apache/arrow/releases)
- [Commits](https://github.com/apache/arrow/compare/go/v10.0.0...go/v10.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-28 03:00:58 +00:00
dependabot[bot]
5aec51a16c Bump urllib3 from 1.26.12 to 1.26.13
Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.12 to 1.26.13.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/1.26.13/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/1.26.12...1.26.13)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-28 03:00:55 +00:00
dependabot[bot]
7e75bc8fcf Bump sb3-contrib from 1.6.1 to 1.6.2
Bumps [sb3-contrib](https://github.com/Stable-Baselines-Team/stable-baselines3-contrib) from 1.6.1 to 1.6.2.
- [Release notes](https://github.com/Stable-Baselines-Team/stable-baselines3-contrib/releases)
- [Commits](https://github.com/Stable-Baselines-Team/stable-baselines3-contrib/compare/v1.6.1...v1.6.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-28 03:00:48 +00:00
dependabot[bot]
49e41925b0 Bump flake8 from 5.0.4 to 6.0.0
Bumps [flake8](https://github.com/pycqa/flake8) from 5.0.4 to 6.0.0.
- [Release notes](https://github.com/pycqa/flake8/releases)
- [Commits](https://github.com/pycqa/flake8/compare/5.0.4...6.0.0)

---
updated-dependencies:
- dependency-name: flake8
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-28 03:00:42 +00:00
Stefano Ariestasia
f410b1b14d Update metrics.py 2022-11-28 08:56:49 +09:00
Emre
f21dbbd8bb Update imports of custom model 2022-11-28 00:06:02 +03:00
robcaulk
56518def42 isort 2022-11-27 21:06:01 +01:00
robcaulk
7fd6bc526e add randomize_starting_position to the rl_config 2022-11-27 21:03:13 +01:00
robcaulk
25e041b98e sneak in small change to FreqaiExampleHybridStrategy docstring and startup count 2022-11-27 20:50:03 +01:00
richardjozsa
64d4a52a56 Improve the RL learning process
Improve the RL learning process by selecting random start point for the agent, it can help to block the agent to only learn on the selected period of time, while improving the quality of the model.
2022-11-27 20:43:50 +01:00
robcaulk
67d9469277 small wording fix 2022-11-27 20:42:04 +01:00
Emre
a02da08065 Fix typo 2022-11-27 22:23:00 +03:00
Matthias
320535a227 improve tests doc wording 2022-11-27 20:07:44 +01:00
Joe Schr
a85602eb9c add "how to run tests" 2022-11-27 20:07:44 +01:00
Emre
5b5859238b Fix typo 2022-11-27 22:06:14 +03:00
Emre
fe00a65163 FIx custom reward link 2022-11-27 21:34:07 +03:00
Matthias
f4025ee5de Merge pull request #7289 from freqtrade/feat/freqai-rl-dev
Add reinforcement learning module to FreqAI
2022-11-27 17:15:21 +01:00
Matthias
2219d2f491 Merge pull request #7707 from freqtrade/bt/full_detail
backtesting - use full detail timeframe
2022-11-27 16:09:23 +01:00
Matthias
cf000a4c00 Bump develop version to 2022.12-dev 2022-11-27 16:08:54 +01:00
Matthias
e4a3efc7d4 Don't use strategy.stoploss too often
discovered in #7760
2022-11-27 15:54:35 +01:00
Matthias
3fc367f536 Merge pull request #7771 from wizrds/feat/refactor-ws
Refactor WebSocket API for performance
2022-11-27 15:49:34 +01:00
froggleston
1a3f88c7b9 Replace separate start/end date option with usual timerange option 2022-11-27 11:30:13 +00:00
Robert Caulk
732757e087 Merge pull request #7801 from initrv/patch-1
Fix 4ac update_total_profit
2022-11-27 12:29:07 +01:00
stm
51d21b413d Fix 4ac update_total_profit
_update_total_profit() must be executed before "self._position = Positions.Neutral" because _update_total_profit() calls get_unrealized_profit(), which returns 0 if position is neutral and total_profit is not updated
2022-11-26 23:35:20 +03:00
froggleston
706bc9ebea Merge branch 'entry_exit_date_print' of github.com:froggleston/freqtrade into entry_exit_date_print 2022-11-26 16:59:27 +00:00
froggleston
4790aaaae1 Implement cli options for backtesting-analysis date filtering 2022-11-26 16:58:56 +00:00
Robert Davey
e1456e407b Merge branch 'freqtrade:develop' into entry_exit_date_print 2022-11-26 16:53:48 +00:00
Timothy Pogue
a26b3a9ca8 change sleep call back to 0.01 2022-11-26 09:40:22 -07:00
robcaulk
b52f05923a fix list to array in constants.py 2022-11-26 13:47:47 +01:00
robcaulk
be890b52fd remove np import 2022-11-26 13:44:58 +01:00
robcaulk
aaaa5a5f64 add documentation for net_arch, other small changes 2022-11-26 13:44:58 +01:00
Matthias
fcf13580f1 Revert "offload initial df computation to thread"
This reverts commit f268187e9b.
2022-11-26 13:33:54 +01:00
Matthias
7b0a76fb70 Improve typehint 2022-11-26 13:33:26 +01:00
Matthias
7ebc8ee169 Fix missing Optional typehint 2022-11-26 13:32:18 +01:00
Matthias
8660ac9aa0 Fix import in docs 2022-11-26 13:12:44 +01:00
Matthias
cf2f12b472 Headers between Tables -> Tables can be jumped to directly 2022-11-26 13:06:21 +01:00
Matthias
bdfedb5fcb Improve typehints / reduce warnings from mypy 2022-11-26 13:03:07 +01:00
robcaulk
81fd2e588f ensure typing, remove unsued code 2022-11-26 12:11:59 +01:00
robcaulk
8dbfd2cacf improve docstring clarity about how to inherit from ReinforcementLearner, demonstrate inherittance with ReinforcementLearner_multiproc 2022-11-26 11:51:08 +01:00
robcaulk
9f13d99b99 improve parameter table, add better documentation for custom calculate_reward, add various helpful notes in docstrings etc 2022-11-26 11:32:39 +01:00
Timothy Pogue
bd95392eea fix formatted string in warning message :) 2022-11-25 13:10:22 -07:00
Timothy Pogue
4aa4c6f49d change sleep in channel send to 0 2022-11-25 13:08:41 -07:00
Timothy Pogue
f268187e9b offload initial df computation to thread 2022-11-25 12:56:33 -07:00
Timothy Pogue
afc00bc30a log warning if channel too far behind, add docstrings to message stream 2022-11-25 12:48:57 -07:00
froggleston
391817243c Tidy up complex functions 2022-11-25 16:12:15 +00:00
Timothy Pogue
bcc8063eeb Merge branch 'develop' into feat/refactor-ws 2022-11-24 13:42:57 -07:00
Timothy Pogue
fc59b02255 prevent ws endpoint from running without valid token 2022-11-24 13:41:10 -07:00
Timothy Pogue
101dec461e close ws channel if can't accept 2022-11-24 11:35:50 -07:00
robcaulk
2e82e6784a move data_provider cleanup to shutdown() 2022-11-24 19:07:38 +01:00
robcaulk
73c458d47b use importlib instead of __import___ 2022-11-24 19:04:35 +01:00
robcaulk
00d2a01bf0 isort 2022-11-24 18:57:01 +01:00
robcaulk
4894d772ed merge develop into feat/freqai-rl-dev 2022-11-24 18:50:11 +01:00
robcaulk
3a07749fcc fix docstring 2022-11-24 18:46:54 +01:00
robcaulk
8855e36f57 reduce freqai testing time by reducing retrain frequency and number of features 2022-11-24 18:16:33 +01:00
robcaulk
44b042ba51 remove unused function 2022-11-24 17:53:26 +01:00
Matthias
8f1a8c752b Add freqairl docker build process 2022-11-24 07:00:12 +01:00
Matthias
e5fc21f577 Fix broken table rendering 2022-11-23 20:59:45 +01:00
Matthias
3d26659d5e Fix some doc typos 2022-11-23 20:09:55 +01:00
Timothy Pogue
48242ca02b update catch block in cancel channel tasks 2022-11-22 12:43:45 -07:00
Wagner Costa
d09157efb8 update code to use one prediction file / pair 2022-11-22 15:15:42 -03:00
Timothy Pogue
a5442772fc ensure only broadcasting to subscribed topics 2022-11-22 09:42:09 -07:00
Wagner Costa
91779bb28b Merge branch 'develop' into backtest_fitlivepredictions 2022-11-22 13:09:48 -03:00
Wagner Costa
c01f25ddc9 update code to freqai_backtest_live_models only from historic predictions 2022-11-22 13:09:09 -03:00
Timothy Pogue
d9d7df70bf fix tests, log unknown errors 2022-11-21 12:21:40 -07:00
Timothy Pogue
d2870d48ea change typing to async iterator 2022-11-20 16:24:44 -07:00
Timothy Pogue
48a1f2418f update typing, remove unneeded try block, readd sleep 2022-11-20 16:18:24 -07:00
Timothy Pogue
60a167bdef add dynamic send timeout 2022-11-20 14:09:45 -07:00
Timothy Pogue
dc79284c54 Merge branch 'develop' into feat/refactor-ws 2022-11-20 10:05:22 -07:00
Wagner Costa Santos
fdc82af883 fix tests - update code to backtest with historic_predictions 2022-11-19 22:27:58 -03:00
Timothy Pogue
3714d7074b smaller throttle in channel send 2022-11-19 13:29:23 -07:00
Timothy Pogue
c1a73a5512 move sleep call in send, minor cleanup 2022-11-19 13:21:26 -07:00
Wagner Costa Santos
80d070e9ee update code to use historic_predictions for freqai_backtest_live_models 2022-11-19 14:15:58 -03:00
robcaulk
d02da279f8 document the simplifications of the training environment 2022-11-19 13:20:20 +01:00
Wagner Costa Santos
3d3195847c Merge branch 'develop' into backtest_fitlivepredictions 2022-11-18 17:53:34 -03:00
Timothy Pogue
98d87b3ba6 Merge branch 'develop' into feat/refactor-ws 2022-11-18 13:41:22 -07:00
Timothy Pogue
0cb6f71c02 better error handling, true async sending, more readable api 2022-11-18 13:32:27 -07:00
robcaulk
61a859ba4c remove tensorboard req from rl reqs 2022-11-18 17:30:03 +01:00
Timothy Pogue
ba493eb7a7 Merge fix/pd-mem-leak 2022-11-17 16:21:12 -07:00
robcaulk
387c905a86 merge develop into RL 2022-11-17 21:59:07 +01:00
robcaulk
60fcd8dce2 fix skipped mac test, fix RL bug in add_state_info, fix use of __import__, revise doc 2022-11-17 21:50:02 +01:00
robcaulk
91df79ff44 merge dev into backtest-live-predictions 2022-11-17 21:20:47 +01:00
Matthias
b929e0bb2b Merge branch 'develop' into gc_improvements 2022-11-17 19:55:03 +01:00
Wagner Costa Santos
3903b04d3f save_live_data_backtest - added docs and tests 2022-11-17 15:20:07 -03:00
Wagner Costa Santos
99bff9cbfa backtesting_from_live_saved_files - code refactoring 2022-11-17 10:30:51 -03:00
Wagner Costa Santos
913749c81b backtesting_from_live_saved_files - code refactoring 2022-11-17 10:30:16 -03:00
Wagner Costa Santos
b01e4e3dbf change default value - save_live_data_backtest as false 2022-11-17 10:14:30 -03:00
Wagner Costa Santos
1a19d90e2e Merge branch 'develop' into backtest_fitlivepredictions 2022-11-17 10:13:11 -03:00
Timothy Pogue
442467e8ae remove old comments and code 2022-11-14 22:26:34 -07:00
Timothy Pogue
d713af045f remove main queue completely 2022-11-14 22:21:40 -07:00
Timothy Pogue
659c8c237f initial revision 2022-11-14 20:27:45 -07:00
robcaulk
bf4d5b432a ensure model_type is defined 2022-11-13 18:50:25 +01:00
robcaulk
6394ef4558 fix docstrings 2022-11-13 17:43:52 +01:00
robcaulk
c8d3e57712 add note that these environments are designed for short-long bots only. 2022-11-13 17:30:56 +01:00
robcaulk
c76afc255a explain how to choose environments, and how to customize them 2022-11-13 17:26:11 +01:00
robcaulk
96fafb7f56 remove limit_ram_use 2022-11-13 17:14:47 +01:00
robcaulk
b421521be3 help default ReinforcementLearner users by assigning the model_type automatically 2022-11-13 17:12:17 +01:00
robcaulk
90f168d1ff remove more user references. cleanup dataprovider 2022-11-13 17:06:06 +01:00
robcaulk
f8f553ec14 remove references to "the user" 2022-11-13 16:58:36 +01:00
robcaulk
388ca21200 update docs, fix bug in environment 2022-11-13 16:56:31 +01:00
robcaulk
3c249ba994 add doc for data_kitchen_thread_count` 2022-11-13 16:11:14 +01:00
robcaulk
af9e400562 add test coverage, fix bug in base environment. Ensure proper fee is used. 2022-11-13 15:31:37 +01:00
robcaulk
81f800a79b switch to using FT calc_profi_pct, reverse entry/exit fees 2022-11-13 13:41:17 +01:00
robcaulk
e45d791c19 Merge remote-tracking branch 'origin/develop' into feat/freqai-rl-dev 2022-11-13 13:00:16 +01:00
robcaulk
259f87bd40 fix rl test; 2022-11-12 19:01:40 +01:00
robcaulk
e71a8b8ac1 add ability to integrate state info or not, and prevent state info integration during backtesting 2022-11-12 18:46:48 +01:00
Wagner Costa Santos
27fa9f1f4e backtest saved dataframe from live 2022-11-12 14:37:23 -03:00
Matthias
7adca97358 Improve python GC behavior 2022-11-12 15:43:02 +01:00
Wagner Costa Santos
f9c6c538be Merge branch 'develop' into backtest_fitlivepredictions 2022-11-12 09:37:45 -03:00
robcaulk
9c6b97c678 ensure normalization acceleration methods are employed in RL 2022-11-12 12:01:59 +01:00
robcaulk
6746868ea7 store dataprovider to self instead of strategy 2022-11-12 11:33:03 +01:00
robcaulk
6ff0e66ddf ensure strat tests are updated 2022-11-12 11:13:31 +01:00
robcaulk
7a4bb040a5 merge develop into feat/freqai-rl-dev 2022-11-12 10:54:34 +01:00
Wagner Costa Santos
4f0f3e5b64 removed unnecessary code 2022-11-09 10:07:24 -03:00
Wagner Costa Santos
8ee95db927 refactoring backtesting_fit_live_predictions function 2022-11-09 09:51:42 -03:00
Wagner Costa Santos
3e57c18ac6 add fix_live_predictions function to backtesting 2022-11-08 18:20:39 -03:00
Wagner Costa Santos
8d9988a942 enforce date column in backtesting freqai predictions files 2022-11-08 11:06:23 -03:00
Wagner Costa Santos
9c5ba0732a save predictions with date and merge by date 2022-11-08 10:32:18 -03:00
Matthias
2c1330a4e2 Update docs to new behavior 2022-11-06 08:32:27 +01:00
Matthias
ded57fb301 Remove no longer valid test part 2022-11-05 20:32:31 +01:00
Matthias
d089fdae34 Fix current-time_det calculation 2022-11-05 20:02:36 +01:00
Matthias
5bd3e54b17 Add test for detail backtesting 2022-11-05 20:01:05 +01:00
Matthias
0888b53b5a Udpate current_time handling for detail loop 2022-11-05 17:02:27 +01:00
Matthias
29ba263c3c Update some test parameters 2022-11-05 17:02:27 +01:00
Matthias
a11d579bc2 Verify order fills on "detail" timeframe 2022-11-05 17:02:27 +01:00
robcaulk
a2843165e1 fix leftovers from merge 2022-10-30 10:31:38 +01:00
robcaulk
52e15b2070 Merge remote-tracking branch 'origin/develop' into feat/freqai-rl-dev 2022-10-30 10:16:39 +01:00
robcaulk
d1a0874683 merge develop into feat/freqai-rl-dev 2022-10-30 10:13:03 +01:00
Matteo Manzi
51b410ac1a Update utils.md 2022-10-18 19:28:29 +02:00
Matteo Manzi
8c39b37223 Update bug_report.md 2022-10-18 19:26:09 +02:00
Matteo Manzi
35cc6aa966 Update data-analysis.md 2022-10-18 19:25:37 +02:00
Matteo Manzi
67850d92af Update question.md 2022-10-18 19:24:46 +02:00
Matteo Manzi
fe3d99b568 Update feature_request.md 2022-10-18 19:22:49 +02:00
Matteo Manzi
11d6d0be9e Update sql_cheatsheet.md 2022-10-18 19:22:07 +02:00
Matteo Manzi
abcbe7a421 Update updating.md 2022-10-18 19:15:59 +02:00
Matteo Manzi
d427226900 Update docker_quickstart.md 2022-10-18 19:15:20 +02:00
robcaulk
8d7adfabe9 clean RL tests to avoid dir pollution and increase speed 2022-10-08 12:10:38 +02:00
Matthias
3e258e000e Don't set use_db without resetting it 2022-10-07 07:05:56 +02:00
Matthias
b9f1872d51 Install RL dependencies as dev dependency 2022-10-06 08:28:15 +02:00
robcaulk
e5204101d9 add tensorboard back to reqs to keep default integration working (and for docker) 2022-10-05 21:34:10 +02:00
robcaulk
488739424d fix reward inconsistency in template 2022-10-05 20:55:50 +02:00
robcaulk
017e476f49 add extras to setup.py for RL 2022-10-05 17:20:40 +02:00
robcaulk
cf10a76a2a bring back Trades.use_db = True 2022-10-05 17:06:18 +02:00
robcaulk
17fb7f7a3b gym needs 0.21 to match stable_baselines3 2022-10-05 16:46:02 +02:00
robcaulk
ab4705efd2 provide background and goals for RL in doc 2022-10-05 16:39:38 +02:00
robcaulk
b5dd92f85a remove RL reqs from general FAI reqs 2022-10-05 16:25:24 +02:00
robcaulk
9cb4832c87 merge feat/freqai into dev-merge-rl 2022-10-05 16:16:07 +02:00
robcaulk
5cfadc689b Merge remote-tracking branch 'origin/develop' into fix-freqai-rl-remote 2022-10-05 16:05:37 +02:00
robcaulk
936ca24482 separate RL install from general FAI install, update docs 2022-10-05 15:58:54 +02:00
robcaulk
9c73411ac2 Merge remote-tracking branch 'origin/develop' into dev-merge-rl 2022-10-05 15:21:45 +02:00
Robert Caulk
8c7f478724 Update requirements-freqai.txt 2022-10-05 10:59:33 +02:00
Robert Caulk
52b774b5eb Merge branch 'develop' into feat/freqai-rl-dev 2022-10-05 09:37:17 +02:00
robcaulk
292d72d593 automatically handle model_save_type for user 2022-10-03 18:42:20 +02:00
robcaulk
cf882fa84e fix tests 2022-10-01 20:26:41 +02:00
robcaulk
ab9d781b06 add reinforcement learning page to docs 2022-10-01 17:50:05 +02:00
robcaulk
048cb95bd6 Merge remote-tracking branch 'origin/develop' into dev-merge-rl 2022-10-01 17:48:47 +02:00
Robert Caulk
09e834fa21 Merge pull request #7492 from wizrds/freqai-rl-dev
Shutdown Subproc Env on signal
2022-09-30 00:19:44 +02:00
Robert Caulk
6e74d46660 Ensure 1 thread available 2022-09-29 14:02:00 +02:00
Robert Caulk
7ef56e3029 Ensure at least 1 thread is available 2022-09-29 14:01:22 +02:00
Robert Caulk
555cc42630 Ensure 1 thread is available (for testing purposes) 2022-09-29 14:00:09 +02:00
Robert Caulk
dcf6ebe273 Update BaseReinforcementLearningModel.py 2022-09-29 00:37:03 +02:00
robcaulk
83343dc2f1 control number of threads, update doc 2022-09-29 00:10:18 +02:00
Timothy Pogue
099137adac remove hasattr calls 2022-09-27 22:35:15 -06:00
Timothy Pogue
9e36b0d2ea fix formatting 2022-09-27 22:02:33 -06:00
Timothy Pogue
caa47a2f47 close subproc env on shutdown 2022-09-28 03:06:05 +00:00
robcaulk
647200e8a7 isort 2022-09-23 19:30:56 +02:00
robcaulk
77c360b264 improve typing, improve docstrings, ensure global tests pass 2022-09-23 19:17:27 +02:00
robcaulk
9c361f4422 increase test coverage for RL and FreqAI 2022-09-23 18:04:43 +02:00
Robert Caulk
95121550ef Remove unnecessary models, add model arg 2022-09-23 10:37:34 +02:00
Robert Caulk
f7dd3045f7 Parameterize backtesting test 2022-09-23 10:30:52 +02:00
Robert Caulk
f5cd8f62c6 Remove unused code from BaseEnv 2022-09-23 10:24:39 +02:00
robcaulk
1c56fa034f add test_models folder 2022-09-23 09:19:16 +02:00
robcaulk
7295ba0fb2 add test for Base4ActionEnv 2022-09-22 23:42:33 +02:00
robcaulk
f6e9753c99 show advanced users how they can customize agent indepth` 2022-09-22 21:18:09 +02:00
robcaulk
eeebb78a5c skip darwin in RL tests, remove example scripts, improve doc 2022-09-22 21:16:21 +02:00
robcaulk
ea8e34e192 Merge branch 'develop' into dev-merge-rl 2022-09-22 19:46:50 +02:00
robcaulk
7b1d409c98 fix mypy/flake8 2022-09-17 17:51:06 +02:00
robcaulk
d056d766ed make tests pass 2022-09-17 17:46:47 +02:00
robcaulk
025b98decd bring back doc sentence 2022-09-15 01:01:33 +02:00
robcaulk
3b97b3d5c8 fix mypy error for strategy 2022-09-15 00:56:51 +02:00
robcaulk
8aac644009 add tests. add guardrails. 2022-09-15 00:46:35 +02:00
robcaulk
48140bff91 fix bug in 4ActRLEnv 2022-09-14 22:53:53 +02:00
robcaulk
81417cb795 Merge branch 'develop' into dev-merge-rl 2022-09-14 22:49:11 +02:00
robcaulk
69b3fcfd32 Merge branch 'develop' into dev-merge-rl 2022-09-04 11:23:25 +02:00
robcaulk
27dce20b29 fix bug in Base4ActionRLEnv, improve example strats 2022-09-04 11:21:54 +02:00
robcaulk
240b529533 fix tensorboard path so that users can track all historical models 2022-08-31 16:50:39 +02:00
Richard Jozsa
2493e0c8a5 Unnecessary lines in Base4, and changes for box space, to fit better for our needs (#7324) 2022-08-31 16:37:02 +02:00
Richard Jozsa
1a8e1362a1 There was an error in the docs around continual learning and thread count (#7314)
* Error in the docs
2022-08-29 11:15:06 +02:00
robcaulk
67cddae756 fix tensorboard image 2022-08-28 21:00:26 +02:00
robcaulk
af8f308584 start the reinforcement learning doc 2022-08-28 20:52:03 +02:00
robcaulk
7766350c15 refactor environment inheritence tree to accommodate flexible action types/counts. fix bug in train profit handling 2022-08-28 19:21:57 +02:00
robcaulk
8c313b431d remove whitespace from Dockerfile 2022-08-26 11:14:01 +02:00
robcaulk
baa4f8e3d0 remove Base3ActionEnv in favor of Base4Action 2022-08-26 11:04:25 +02:00
richardjozsa
cdc550da9a Revert the docker changes to be inline with the original freqtrade image
Reverted the changes, and added a new way of doing, Dockerfile.freqai with that file the users can make their own dockerimage.
2022-08-26 11:04:25 +02:00
richardjozsa
d31926efdf Added Base4Action 2022-08-26 11:04:25 +02:00
robcaulk
3199eb453b reduce code for base use-case, ensure multiproc inherits custom env, add ability to limit ram use. 2022-08-25 19:05:51 +02:00
robcaulk
05ccebf9a1 automate eval freq in multiproc 2022-08-25 12:29:48 +02:00
robcaulk
94cfc8e63f fix multiproc callback, add continual learning to multiproc, fix totalprofit bug in env, set eval_freq automatically, improve default reward 2022-08-25 11:46:18 +02:00
robcaulk
d1bee29b1e improve default reward, fix bugs in environment 2022-08-24 18:32:40 +02:00
robcaulk
a61821e1c6 remove monitor log 2022-08-24 16:33:13 +02:00
robcaulk
bd870e2331 fix monitor bug, set default values in case user doesnt set params 2022-08-24 16:32:14 +02:00
robcaulk
c0cee5df07 add continual retraining feature, handly mypy typing reqs, improve docstrings 2022-08-24 13:00:55 +02:00
robcaulk
b708134c1a switch multiproc thread count to rl_config definition 2022-08-24 13:00:55 +02:00
robcaulk
b26ed7dea4 fix generic reward, add time duration to reward 2022-08-24 13:00:55 +02:00
robcaulk
280a1dc3f8 add live rate, add trade duration 2022-08-24 13:00:55 +02:00
robcaulk
f9a49744e6 add strategy to the freqai object 2022-08-24 13:00:55 +02:00
richardjozsa
a2a4bc05db Fix the state profit calculation logic 2022-08-24 13:00:55 +02:00
robcaulk
29f0e01c4a expose environment reward parameters to the user config 2022-08-24 13:00:55 +02:00
robcaulk
d88a0dbf82 add sb3_contrib models to the available agents. include sb3_contrib in requirements. 2022-08-24 13:00:55 +02:00
robcaulk
8b3a8234ac fix env bug, allow example strat to short 2022-08-24 13:00:55 +02:00
mrzdev
8cd4daad0a Feat/freqai rl dev (#7)
* access trades through get_trades_proxy method to allow backtesting
2022-08-24 13:00:55 +02:00
robcaulk
3eb897c2f8 reuse callback, allow user to acces all stable_baselines3 agents via config 2022-08-24 13:00:55 +02:00
robcaulk
4b9499e321 improve nomenclature and fix short exit bug 2022-08-24 13:00:55 +02:00
sonnhfit
4baa36bdcf fix persist a single training environment for PPO 2022-08-24 13:00:55 +02:00
robcaulk
f95602f6bd persist a single training environment. 2022-08-24 13:00:55 +02:00
robcaulk
5d4e5e69fe reinforce training with state info, reinforce prediction with state info, restructure config to accommodate all parameters from any user imported model type. Set 5Act to default env on TDQN. Clean example config. 2022-08-24 13:00:55 +02:00
sonnhfit
7962a1439b remove keep low profit 2022-08-24 13:00:55 +02:00
sonnhfit
81b5aa66e8 make env keep current position when low profit 2022-08-24 13:00:55 +02:00
sonnhfit
45218faeb0 fix coding convention 2022-08-24 13:00:55 +02:00
richardjozsa
d55092ff17 Docker building update, and TDQN repair with the newer release of SB+ 2022-08-24 13:00:55 +02:00
robcaulk
74e4fd0633 ensure config example can work with backtesting RL 2022-08-24 13:00:55 +02:00
robcaulk
b90da46b1b improve price df handling to enable backtesting 2022-08-24 13:00:55 +02:00
MukavaValkku
2080ff86ed 5ac base fixes in logic 2022-08-24 13:00:55 +02:00
robcaulk
16cec7dfbd fix save/reload functionality for stablebaselines 2022-08-24 13:00:55 +02:00
sonnhfit
0475b7cb18 remove unuse code and fix coding conventions 2022-08-24 13:00:55 +02:00
MukavaValkku
d60a166fbf multiproc TDQN with xtra callbacks 2022-08-24 13:00:55 +02:00
robcaulk
dd382dd370 add monitor to eval env so that multiproc can save best_model 2022-08-24 13:00:55 +02:00
robcaulk
69d542d3e2 match config and strats to upstream freqai 2022-08-24 13:00:55 +02:00
robcaulk
e5df39e891 ensuring best_model is placed in ram and saved to disk and loaded from disk 2022-08-24 13:00:55 +02:00
robcaulk
bf7ceba958 set cpu threads in config 2022-08-24 13:00:55 +02:00
MukavaValkku
57c488a6f1 learning_rate + multicpu changes 2022-08-24 13:00:55 +02:00
MukavaValkku
48bb51b458 example config added 2022-08-24 13:00:55 +02:00
MukavaValkku
b1fc5a06ca example config added 2022-08-24 13:00:55 +02:00
sonnhfit
6d8e838a8f update tensorboard dependency 2022-08-24 13:00:55 +02:00
robcaulk
acf3484e88 add multiprocessing variant of ReinforcementLearningPPO 2022-08-24 13:00:55 +02:00
MukavaValkku
cf0731095f type fix 2022-08-24 13:00:55 +02:00
MukavaValkku
1c81ec6016 3ac and 5ac example strategies 2022-08-24 13:00:55 +02:00
MukavaValkku
13cd18dc9a PPO policy change + verbose=1 2022-08-24 13:00:55 +02:00
robcaulk
926023935f make base 3ac and base 5ac environments. TDQN defaults to 3AC. 2022-08-24 13:00:55 +02:00
MukavaValkku
096533bcb9 3ac to 5ac 2022-08-24 13:00:55 +02:00
MukavaValkku
718c9d0440 action fix 2022-08-24 13:00:55 +02:00
robcaulk
9c78e6c26f base PPO model only customizes reward for 3AC 2022-08-24 13:00:55 +02:00
robcaulk
6048f60f13 get TDQN working with 5 action environment 2022-08-24 13:00:55 +02:00
robcaulk
d4db5c3281 ensure TDQN class is properly named 2022-08-24 13:00:55 +02:00
robcaulk
91683e1dca restructure RL so that user can customize environment 2022-08-24 13:00:55 +02:00
sonnhfit
ecd1f55abc add rl module 2022-08-24 13:00:55 +02:00
sonnhfit
70b25461f0 add rl dependency 2022-08-24 13:00:55 +02:00
MukavaValkku
9b895500b3 initial commit - new dev branch 2022-08-24 13:00:55 +02:00
MukavaValkku
cd3fe44424 callback function and TDQN model added 2022-08-24 13:00:55 +02:00
MukavaValkku
01232e9a1f callback function and TDQN model added 2022-08-24 13:00:55 +02:00
MukavaValkku
8eeaab2746 add reward function 2022-08-24 13:00:55 +02:00
MukavaValkku
ec813434f5 ReinforcementLearningModel 2022-08-24 13:00:55 +02:00
MukavaValkku
2f4d73eb06 Revert "ReinforcementLearningModel"
This reverts commit 4d8dfe1ff1daa47276eda77118ddf39c13512a85.
2022-08-24 13:00:55 +02:00
MukavaValkku
c1e7db3130 ReinforcementLearningModel 2022-08-24 13:00:55 +02:00
robcaulk
05ed1b544f Working base for reinforcement learning model 2022-08-24 13:00:40 +02:00
251 changed files with 21467 additions and 13266 deletions

View File

@@ -20,7 +20,7 @@ Please do not use bug reports to request new features.
* Operating system: ____
* Python Version: _____ (`python -V`)
* CCXT version: _____ (`pip freeze | grep ccxt`)
* Freqtrade Version: ____ (`freqtrade -V` or `docker-compose run --rm freqtrade -V` for Freqtrade running in docker)
* Freqtrade Version: ____ (`freqtrade -V` or `docker compose run --rm freqtrade -V` for Freqtrade running in docker)
Note: All issues other than enhancement requests will be closed without further comment if the above template is deleted or not filled out.

View File

@@ -18,7 +18,7 @@ Have you search for this feature before requesting it? It's highly likely that a
* Operating system: ____
* Python Version: _____ (`python -V`)
* CCXT version: _____ (`pip freeze | grep ccxt`)
* Freqtrade Version: ____ (`freqtrade -V` or `docker-compose run --rm freqtrade -V` for Freqtrade running in docker)
* Freqtrade Version: ____ (`freqtrade -V` or `docker compose run --rm freqtrade -V` for Freqtrade running in docker)
## Describe the enhancement

View File

@@ -18,7 +18,7 @@ Please do not use the question template to report bugs or to request new feature
* Operating system: ____
* Python Version: _____ (`python -V`)
* CCXT version: _____ (`pip freeze | grep ccxt`)
* Freqtrade Version: ____ (`freqtrade -V` or `docker-compose run --rm freqtrade -V` for Freqtrade running in docker)
* Freqtrade Version: ____ (`freqtrade -V` or `docker compose run --rm freqtrade -V` for Freqtrade running in docker)
## Your question

View File

@@ -23,7 +23,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ ubuntu-18.04, ubuntu-20.04, ubuntu-22.04 ]
os: [ ubuntu-20.04, ubuntu-22.04 ]
python-version: ["3.8", "3.9", "3.10"]
steps:
@@ -66,12 +66,6 @@ jobs:
- name: Tests
run: |
pytest --random-order --cov=freqtrade --cov-config=.coveragerc
if: matrix.python-version != '3.9' || matrix.os != 'ubuntu-22.04'
- name: Tests incl. ccxt compatibility tests
run: |
pytest --random-order --cov=freqtrade --cov-config=.coveragerc --longrun
if: matrix.python-version == '3.9' && matrix.os == 'ubuntu-22.04'
- name: Coveralls
if: (runner.os == 'Linux' && matrix.python-version == '3.10' && matrix.os == 'ubuntu-22.04')
@@ -94,7 +88,7 @@ jobs:
run: |
cp config_examples/config_bittrex.example.json config.json
freqtrade create-userdir --userdir user_data
freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt-loss SharpeHyperOptLossDaily --print-all
freqtrade hyperopt --datadir tests/testdata -e 6 --strategy SampleStrategy --hyperopt-loss SharpeHyperOptLossDaily --print-all
- name: Flake8
run: |
@@ -154,6 +148,19 @@ jobs:
if: runner.os == 'macOS'
run: |
brew update
# homebrew fails to update python due to unlinking failures
# https://github.com/actions/runner-images/issues/6817
rm /usr/local/bin/2to3 || true
rm /usr/local/bin/2to3-3.11 || true
rm /usr/local/bin/idle3 || true
rm /usr/local/bin/idle3.11 || true
rm /usr/local/bin/pydoc3 || true
rm /usr/local/bin/pydoc3.11 || true
rm /usr/local/bin/python3 || true
rm /usr/local/bin/python3.11 || true
rm /usr/local/bin/python3-config || true
rm /usr/local/bin/python3.11-config || true
brew install hdf5 c-blosc
python -m pip install --upgrade pip wheel
export LD_LIBRARY_PATH=${HOME}/dependencies/lib:$LD_LIBRARY_PATH
@@ -310,9 +317,66 @@ jobs:
details: Freqtrade doc test failed!
webhookUrl: ${{ secrets.DISCORD_WEBHOOK }}
build_linux_online:
# Run pytest with "live" checks
runs-on: ubuntu-22.04
# permissions:
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.9"
- name: Cache_dependencies
uses: actions/cache@v3
id: cache
with:
path: ~/dependencies/
key: ${{ runner.os }}-dependencies
- name: pip cache (linux)
uses: actions/cache@v3
if: runner.os == 'Linux'
with:
path: ~/.cache/pip
key: test-${{ matrix.os }}-${{ matrix.python-version }}-pip
- name: TA binary *nix
if: steps.cache.outputs.cache-hit != 'true'
run: |
cd build_helpers && ./install_ta-lib.sh ${HOME}/dependencies/; cd ..
- name: Installation - *nix
if: runner.os == 'Linux'
run: |
python -m pip install --upgrade pip wheel
export LD_LIBRARY_PATH=${HOME}/dependencies/lib:$LD_LIBRARY_PATH
export TA_LIBRARY_PATH=${HOME}/dependencies/lib
export TA_INCLUDE_PATH=${HOME}/dependencies/include
pip install -r requirements-dev.txt
pip install -e .
- name: Tests incl. ccxt compatibility tests
env:
CI_WEB_PROXY: http://152.67.78.211:13128
run: |
pytest --random-order --cov=freqtrade --cov-config=.coveragerc --longrun
# Notify only once - when CI completes (and after deploy) in case it's successfull
notify-complete:
needs: [ build_linux, build_macos, build_windows, docs_check, mypy_version_check, pre-commit ]
needs: [
build_linux,
build_macos,
build_windows,
docs_check,
mypy_version_check,
pre-commit,
build_linux_online
]
runs-on: ubuntu-22.04
# Discord notification can't handle schedule events
if: (github.event_name != 'schedule')
@@ -361,7 +425,7 @@ jobs:
python setup.py sdist bdist_wheel
- name: Publish to PyPI (Test)
uses: pypa/gh-action-pypi-publish@v1.5.1
uses: pypa/gh-action-pypi-publish@v1.6.4
if: (github.event_name == 'release')
with:
user: __token__
@@ -369,7 +433,7 @@ jobs:
repository_url: https://test.pypi.org/legacy/
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@v1.5.1
uses: pypa/gh-action-pypi-publish@v1.6.4
if: (github.event_name == 'release')
with:
user: __token__

View File

@@ -2,33 +2,33 @@
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pycqa/flake8
rev: "4.0.1"
rev: "6.0.0"
hooks:
- id: flake8
# stages: [push]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: "v0.942"
rev: "v0.991"
hooks:
- id: mypy
exclude: build_helpers
additional_dependencies:
- types-cachetools==5.2.1
- types-cachetools==5.3.0.0
- types-filelock==3.2.7
- types-requests==2.28.11.5
- types-requests==2.28.11.13
- types-tabulate==0.9.0.0
- types-python-dateutil==2.8.19.4
- types-python-dateutil==2.8.19.6
# stages: [push]
- repo: https://github.com/pycqa/isort
rev: "5.10.1"
rev: "5.12.0"
hooks:
- id: isort
name: isort (python)
# stages: [push]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.4.0
rev: v4.4.0
hooks:
- id: end-of-file-fixer
exclude: |

View File

@@ -1,4 +1,4 @@
FROM python:3.10.7-slim-bullseye as base
FROM python:3.10.10-slim-bullseye as base
# Setup env
ENV LANG C.UTF-8

View File

@@ -1,6 +1,7 @@
# ![freqtrade](https://raw.githubusercontent.com/freqtrade/freqtrade/develop/docs/assets/freqtrade_poweredby.svg)
[![Freqtrade CI](https://github.com/freqtrade/freqtrade/workflows/Freqtrade%20CI/badge.svg)](https://github.com/freqtrade/freqtrade/actions/)
[![DOI](https://joss.theoj.org/papers/10.21105/joss.04864/status.svg)](https://doi.org/10.21105/joss.04864)
[![Coverage Status](https://coveralls.io/repos/github/freqtrade/freqtrade/badge.svg?branch=develop&service=github)](https://coveralls.io/github/freqtrade/freqtrade?branch=develop)
[![Documentation](https://readthedocs.org/projects/freqtrade/badge/)](https://www.freqtrade.io)
[![Maintainability](https://api.codeclimate.com/v1/badges/5737e6d668200b7518ff/maintainability)](https://codeclimate.com/github/freqtrade/freqtrade/maintainability)
@@ -39,6 +40,7 @@ Please read the [exchange specific notes](docs/exchanges.md) to learn about even
- [X] [Binance](https://www.binance.com/)
- [X] [Gate.io](https://www.gate.io/ref/6266643)
- [X] [OKX](https://okx.com/)
- [X] [Bybit](https://bybit.com/)
Please make sure to read the [exchange specific notes](docs/exchanges.md), as well as the [trading with leverage](docs/leverage.md) documentation before diving in.
@@ -163,6 +165,10 @@ first. If it hasn't been reported, please
ensure you follow the template guide so that the team can assist you as
quickly as possible.
For every [issue](https://github.com/freqtrade/freqtrade/issues/new/choose) created, kindly follow up and mark satisfaction or reminder to close issue when equilibrium ground is reached.
--Maintain github's [community policy](https://docs.github.com/en/site-policy/github-terms/github-community-code-of-conduct)--
### [Feature Requests](https://github.com/freqtrade/freqtrade/labels/enhancement)
Have you a great idea to improve the bot you want to share? Please,

Binary file not shown.

View File

@@ -14,5 +14,8 @@ if ($pyv -eq '3.9') {
if ($pyv -eq '3.10') {
pip install build_helpers\TA_Lib-0.4.25-cp310-cp310-win_amd64.whl
}
if ($pyv -eq '3.11') {
pip install build_helpers\TA_Lib-0.4.25-cp311-cp311-win_amd64.whl
}
pip install -r requirements-dev.txt
pip install -e .

View File

@@ -7,11 +7,13 @@ export DOCKER_BUILDKIT=1
TAG=$(echo "${BRANCH_NAME}" | sed -e "s/\//_/g")
TAG_PLOT=${TAG}_plot
TAG_FREQAI=${TAG}_freqai
TAG_FREQAI_RL=${TAG_FREQAI}rl
TAG_PI="${TAG}_pi"
TAG_ARM=${TAG}_arm
TAG_PLOT_ARM=${TAG_PLOT}_arm
TAG_FREQAI_ARM=${TAG_FREQAI}_arm
TAG_FREQAI_RL_ARM=${TAG_FREQAI_RL}_arm
CACHE_IMAGE=freqtradeorg/freqtrade_cache
echo "Running for ${TAG}"
@@ -41,9 +43,11 @@ docker tag freqtrade:$TAG_ARM ${CACHE_IMAGE}:$TAG_ARM
docker build --cache-from freqtrade:${TAG_ARM} --build-arg sourceimage=${CACHE_IMAGE} --build-arg sourcetag=${TAG_ARM} -t freqtrade:${TAG_PLOT_ARM} -f docker/Dockerfile.plot .
docker build --cache-from freqtrade:${TAG_ARM} --build-arg sourceimage=${CACHE_IMAGE} --build-arg sourcetag=${TAG_ARM} -t freqtrade:${TAG_FREQAI_ARM} -f docker/Dockerfile.freqai .
docker build --cache-from freqtrade:${TAG_ARM} --build-arg sourceimage=${CACHE_IMAGE} --build-arg sourcetag=${TAG_ARM} -t freqtrade:${TAG_FREQAI_RL_ARM} -f docker/Dockerfile.freqai_rl .
docker tag freqtrade:$TAG_PLOT_ARM ${CACHE_IMAGE}:$TAG_PLOT_ARM
docker tag freqtrade:$TAG_FREQAI_ARM ${CACHE_IMAGE}:$TAG_FREQAI_ARM
docker tag freqtrade:$TAG_FREQAI_RL_ARM ${CACHE_IMAGE}:$TAG_FREQAI_RL_ARM
# Run backtest
docker run --rm -v $(pwd)/config_examples/config_bittrex.example.json:/freqtrade/config.json:ro -v $(pwd)/tests:/tests freqtrade:${TAG_ARM} backtesting --datadir /tests/testdata --strategy-path /tests/strategy/strats/ --strategy StrategyTestV3
@@ -58,6 +62,7 @@ docker images
# docker push ${IMAGE_NAME}
docker push ${CACHE_IMAGE}:$TAG_PLOT_ARM
docker push ${CACHE_IMAGE}:$TAG_FREQAI_ARM
docker push ${CACHE_IMAGE}:$TAG_FREQAI_RL_ARM
docker push ${CACHE_IMAGE}:$TAG_ARM
# Create multi-arch image
@@ -65,17 +70,21 @@ docker push ${CACHE_IMAGE}:$TAG_ARM
# Otherwise installation might fail.
echo "create manifests"
docker manifest create --amend ${IMAGE_NAME}:${TAG} ${CACHE_IMAGE}:${TAG_ARM} ${IMAGE_NAME}:${TAG_PI} ${CACHE_IMAGE}:${TAG}
docker manifest create ${IMAGE_NAME}:${TAG} ${CACHE_IMAGE}:${TAG} ${CACHE_IMAGE}:${TAG_ARM} ${IMAGE_NAME}:${TAG_PI}
docker manifest push -p ${IMAGE_NAME}:${TAG}
docker manifest create ${IMAGE_NAME}:${TAG_PLOT} ${CACHE_IMAGE}:${TAG_PLOT_ARM} ${CACHE_IMAGE}:${TAG_PLOT}
docker manifest create ${IMAGE_NAME}:${TAG_PLOT} ${CACHE_IMAGE}:${TAG_PLOT} ${CACHE_IMAGE}:${TAG_PLOT_ARM}
docker manifest push -p ${IMAGE_NAME}:${TAG_PLOT}
docker manifest create ${IMAGE_NAME}:${TAG_FREQAI} ${CACHE_IMAGE}:${TAG_FREQAI_ARM} ${CACHE_IMAGE}:${TAG_FREQAI}
docker manifest create ${IMAGE_NAME}:${TAG_FREQAI} ${CACHE_IMAGE}:${TAG_FREQAI} ${CACHE_IMAGE}:${TAG_FREQAI_ARM}
docker manifest push -p ${IMAGE_NAME}:${TAG_FREQAI}
docker manifest create ${IMAGE_NAME}:${TAG_FREQAI_RL} ${CACHE_IMAGE}:${TAG_FREQAI_RL} ${CACHE_IMAGE}:${TAG_FREQAI_RL_ARM}
docker manifest push -p ${IMAGE_NAME}:${TAG_FREQAI_RL}
# Tag as latest for develop builds
if [ "${TAG}" = "develop" ]; then
echo 'Tagging image as latest'
docker manifest create ${IMAGE_NAME}:latest ${CACHE_IMAGE}:${TAG_ARM} ${IMAGE_NAME}:${TAG_PI} ${CACHE_IMAGE}:${TAG}
docker manifest push -p ${IMAGE_NAME}:latest
fi

View File

@@ -6,6 +6,7 @@
TAG=$(echo "${BRANCH_NAME}" | sed -e "s/\//_/g")
TAG_PLOT=${TAG}_plot
TAG_FREQAI=${TAG}_freqai
TAG_FREQAI_RL=${TAG_FREQAI}rl
TAG_PI="${TAG}_pi"
PI_PLATFORM="linux/arm/v7"
@@ -25,7 +26,10 @@ if [ "${GITHUB_EVENT_NAME}" = "schedule" ]; then
--cache-to=type=registry,ref=${CACHE_TAG} \
-f docker/Dockerfile.armhf \
--platform ${PI_PLATFORM} \
-t ${IMAGE_NAME}:${TAG_PI} --push .
-t ${IMAGE_NAME}:${TAG_PI} \
--push \
--provenance=false \
.
else
echo "event ${GITHUB_EVENT_NAME}: building with cache"
# Build regular image
@@ -34,12 +38,16 @@ else
# Pull last build to avoid rebuilding the whole image
# docker pull --platform ${PI_PLATFORM} ${IMAGE_NAME}:${TAG}
# disable provenance due to https://github.com/docker/buildx/issues/1509
docker buildx build \
--cache-from=type=registry,ref=${CACHE_TAG} \
--cache-to=type=registry,ref=${CACHE_TAG} \
-f docker/Dockerfile.armhf \
--platform ${PI_PLATFORM} \
-t ${IMAGE_NAME}:${TAG_PI} --push .
-t ${IMAGE_NAME}:${TAG_PI} \
--push \
--provenance=false \
.
fi
if [ $? -ne 0 ]; then
@@ -51,9 +59,11 @@ docker tag freqtrade:$TAG ${CACHE_IMAGE}:$TAG
docker build --cache-from freqtrade:${TAG} --build-arg sourceimage=${CACHE_IMAGE} --build-arg sourcetag=${TAG} -t freqtrade:${TAG_PLOT} -f docker/Dockerfile.plot .
docker build --cache-from freqtrade:${TAG} --build-arg sourceimage=${CACHE_IMAGE} --build-arg sourcetag=${TAG} -t freqtrade:${TAG_FREQAI} -f docker/Dockerfile.freqai .
docker build --cache-from freqtrade:${TAG_FREQAI} --build-arg sourceimage=${CACHE_IMAGE} --build-arg sourcetag=${TAG_FREQAI} -t freqtrade:${TAG_FREQAI_RL} -f docker/Dockerfile.freqai_rl .
docker tag freqtrade:$TAG_PLOT ${CACHE_IMAGE}:$TAG_PLOT
docker tag freqtrade:$TAG_FREQAI ${CACHE_IMAGE}:$TAG_FREQAI
docker tag freqtrade:$TAG_FREQAI_RL ${CACHE_IMAGE}:$TAG_FREQAI_RL
# Run backtest
docker run --rm -v $(pwd)/config_examples/config_bittrex.example.json:/freqtrade/config.json:ro -v $(pwd)/tests:/tests freqtrade:${TAG} backtesting --datadir /tests/testdata --strategy-path /tests/strategy/strats/ --strategy StrategyTestV3
@@ -65,11 +75,10 @@ fi
docker images
docker push ${CACHE_IMAGE}
docker push ${CACHE_IMAGE}:$TAG
docker push ${CACHE_IMAGE}:$TAG_PLOT
docker push ${CACHE_IMAGE}:$TAG_FREQAI
docker push ${CACHE_IMAGE}:$TAG
docker push ${CACHE_IMAGE}:$TAG_FREQAI_RL
docker images

View File

@@ -59,20 +59,6 @@
"pairlists": [
{"method": "StaticPairList"}
],
"edge": {
"enabled": false,
"process_throttle_secs": 3600,
"calculate_since_number_of_days": 7,
"allowed_risk": 0.01,
"stoploss_range_min": -0.01,
"stoploss_range_max": -0.1,
"stoploss_range_step": -0.01,
"minimum_winrate": 0.60,
"minimum_expectancy": 0.20,
"min_trade_number": 10,
"max_trade_duration_minute": 1440,
"remove_pumps": false
},
"telegram": {
"enabled": false,
"token": "your_telegram_token",

View File

@@ -56,20 +56,6 @@
"pairlists": [
{"method": "StaticPairList"}
],
"edge": {
"enabled": false,
"process_throttle_secs": 3600,
"calculate_since_number_of_days": 7,
"allowed_risk": 0.01,
"stoploss_range_min": -0.01,
"stoploss_range_max": -0.1,
"stoploss_range_step": -0.01,
"minimum_winrate": 0.60,
"minimum_expectancy": 0.20,
"min_trade_number": 10,
"max_trade_duration_minute": 1440,
"remove_pumps": false
},
"telegram": {
"enabled": false,
"token": "your_telegram_token",

View File

@@ -21,8 +21,8 @@
"ccxt_config": {},
"ccxt_async_config": {},
"pair_whitelist": [
"1INCH/USDT",
"ALGO/USDT"
"1INCH/USDT:USDT",
"ALGO/USDT:USDT"
],
"pair_blacklist": []
},
@@ -48,7 +48,7 @@
],
"freqai": {
"enabled": true,
"purge_old_models": true,
"purge_old_models": 2,
"train_period_days": 15,
"backtest_period_days": 7,
"live_retrain_hours": 0,
@@ -60,8 +60,8 @@
"1h"
],
"include_corr_pairlist": [
"BTC/USDT",
"ETH/USDT"
"BTC/USDT:USDT",
"ETH/USDT:USDT"
],
"label_period_candles": 20,
"include_shifted_candles": 2,
@@ -79,9 +79,7 @@
"test_size": 0.33,
"random_state": 1
},
"model_training_parameters": {
"n_estimators": 1000
}
"model_training_parameters": {}
},
"bot_name": "",
"force_entry_enable": true,

View File

@@ -60,6 +60,7 @@
"force_entry": "market",
"stoploss": "market",
"stoploss_on_exchange": false,
"stoploss_price_type": "last",
"stoploss_on_exchange_interval": 60,
"stoploss_on_exchange_limit_ratio": 0.99
},

View File

@@ -64,20 +64,6 @@
"pairlists": [
{"method": "StaticPairList"}
],
"edge": {
"enabled": false,
"process_throttle_secs": 3600,
"calculate_since_number_of_days": 7,
"allowed_risk": 0.01,
"stoploss_range_min": -0.01,
"stoploss_range_max": -0.1,
"stoploss_range_step": -0.01,
"minimum_winrate": 0.60,
"minimum_expectancy": 0.20,
"min_trade_number": 10,
"max_trade_duration_minute": 1440,
"remove_pumps": false
},
"telegram": {
"enabled": false,
"token": "your_telegram_token",

View File

@@ -1,4 +1,4 @@
FROM python:3.9.12-slim-bullseye as base
FROM python:3.9.16-slim-bullseye as base
# Setup env
ENV LANG C.UTF-8

View File

@@ -0,0 +1,8 @@
ARG sourceimage=freqtradeorg/freqtrade
ARG sourcetag=develop_freqai
FROM ${sourceimage}:${sourcetag}
# Install dependencies
COPY requirements-freqai.txt requirements-freqai-rl.txt /freqtrade/
RUN pip install -r requirements-freqai-rl.txt --user --no-cache-dir

View File

@@ -32,7 +32,7 @@ To analyze the entry/exit tags, we now need to use the `freqtrade backtesting-an
with `--analysis-groups` option provided with space-separated arguments (default `0 1 2`):
``` bash
freqtrade backtesting-analysis -c <config.json> --analysis-groups 0 1 2 3 4
freqtrade backtesting-analysis -c <config.json> --analysis-groups 0 1 2 3 4 5
```
This command will read from the last backtesting results. The `--analysis-groups` option is
@@ -43,6 +43,7 @@ ranging from the simplest (0) to the most detailed per pair, per buy and per sel
* 2: profit summaries grouped by enter_tag and exit_tag
* 3: profit summaries grouped by pair and enter_tag
* 4: profit summaries grouped by pair, enter_ and exit_tag (this can get quite large)
* 5: profit summaries grouped by exit_tag
More options are available by running with the `-h` option.
@@ -100,3 +101,17 @@ freqtrade backtesting-analysis -c <config.json> --analysis-groups 0 2 --enter-re
The indicators have to be present in your strategy's main DataFrame (either for your main
timeframe or for informative timeframes) otherwise they will simply be ignored in the script
output.
### Filtering the trade output by date
To show only trades between dates within your backtested timerange, supply the usual `timerange` option in `YYYYMMDD-[YYYYMMDD]` format:
```
--timerange : Timerange to filter output trades, start date inclusive, end date exclusive. e.g. 20220101-20221231
```
For example, if your backtest timerange was `20220101-20221231` but you only want to output trades in January:
```bash
freqtrade backtesting-analysis -c <config.json> --timerange 20220101-20220201
```

View File

@@ -75,7 +75,7 @@ This function needs to return a floating point number (`float`). Smaller numbers
## Overriding pre-defined spaces
To override a pre-defined space (`roi_space`, `generate_roi_table`, `stoploss_space`, `trailing_space`), define a nested class called Hyperopt and define the required spaces as follows:
To override a pre-defined space (`roi_space`, `generate_roi_table`, `stoploss_space`, `trailing_space`, `max_open_trades_space`), define a nested class called Hyperopt and define the required spaces as follows:
```python
from freqtrade.optimize.space import Categorical, Dimension, Integer, SKDecimal
@@ -123,6 +123,12 @@ class MyAwesomeStrategy(IStrategy):
Categorical([True, False], name='trailing_only_offset_is_reached'),
]
# Define a custom max_open_trades space
def max_open_trades_space(self) -> List[Dimension]:
return [
Integer(-1, 10, name='max_open_trades'),
]
```
!!! Note

View File

@@ -192,7 +192,7 @@ $RepeatedMsgReduction on
### Logging to journald
This needs the `systemd` python package installed as the dependency, which is not available on Windows. Hence, the whole journald logging functionality is not available for a bot running on Windows.
This needs the `cysystemd` python package installed as dependency (`pip install cysystemd`), which is not available on Windows. Hence, the whole journald logging functionality is not available for a bot running on Windows.
To send Freqtrade log messages to `journald` system service use the `--logfile` command line option with the value in the following format:

View File

@@ -300,7 +300,11 @@ A backtesting result will look like that:
| Absolute profit | 0.00762792 BTC |
| Total profit % | 76.2% |
| CAGR % | 460.87% |
| Sortino | 1.88 |
| Sharpe | 2.97 |
| Calmar | 6.29 |
| Profit factor | 1.11 |
| Expectancy | -0.15 |
| Avg. stake amount | 0.001 BTC |
| Total trade volume | 0.429 BTC |
| | |
@@ -400,7 +404,11 @@ It contains some useful key metrics about performance of your strategy on backte
| Absolute profit | 0.00762792 BTC |
| Total profit % | 76.2% |
| CAGR % | 460.87% |
| Sortino | 1.88 |
| Sharpe | 2.97 |
| Calmar | 6.29 |
| Profit factor | 1.11 |
| Expectancy | -0.15 |
| Avg. stake amount | 0.001 BTC |
| Total trade volume | 0.429 BTC |
| | |
@@ -447,6 +455,9 @@ It contains some useful key metrics about performance of your strategy on backte
- `Absolute profit`: Profit made in stake currency.
- `Total profit %`: Total profit. Aligned to the `TOTAL` row's `Tot Profit %` from the first table. Calculated as `(End capital Starting capital) / Starting capital`.
- `CAGR %`: Compound annual growth rate.
- `Sortino`: Annualized Sortino ratio.
- `Sharpe`: Annualized Sharpe ratio.
- `Calmar`: Annualized Calmar ratio.
- `Profit factor`: profit / loss.
- `Avg. stake amount`: Average stake amount, either `stake_amount` or the average when using dynamic stake amount.
- `Total trade volume`: Volume generated on the exchange to reach the above profit.
@@ -583,7 +594,8 @@ To utilize this, you can append `--timeframe-detail 5m` to your regular backtest
freqtrade backtesting --strategy AwesomeStrategy --timeframe 1h --timeframe-detail 5m
```
This will load 1h data as well as 5m data for the timeframe. The strategy will be analyzed with the 1h timeframe - and for every "open trade candle" (candles where a trade is open) the 5m data will be used to simulate intra-candle movements.
This will load 1h data as well as 5m data for the timeframe. The strategy will be analyzed with the 1h timeframe, and Entry orders will only be placed at the main timeframe, however Order fills and exit signals will be evaluated at the 5m candle, simulating intra-candle movements.
All callback functions (`custom_exit()`, `custom_stoploss()`, ... ) will be running for each 5m candle once the trade is opened (so 12 times in the above example of 1h timeframe, and 5m detailed timeframe).
`--timeframe-detail` must be smaller than the original timeframe, otherwise backtesting will fail to start.

View File

@@ -75,3 +75,7 @@ This loop will be repeated again and again until the bot is stopped.
!!! Note
Both Backtesting and Hyperopt include exchange default Fees in the calculation. Custom fees can be passed to backtesting / hyperopt by specifying the `--fee` argument.
!!! Warning "Callback call frequency"
Backtesting will call each callback at max. once per candle (`--timeframe-detail` modifies this behavior to once per detailed candle).
Most callbacks will be called once per iteration in live (usually every ~5s) - which can cause backtesting mismatches.

View File

@@ -11,7 +11,7 @@ Per default, the bot loads the configuration from the `config.json` file, locate
You can specify a different configuration file used by the bot with the `-c/--config` command-line option.
If you used the [Quick start](installation.md/#quick-start) method for installing
If you used the [Quick start](docker_quickstart.md#docker-quick-start) method for installing
the bot, the installation script should have already created the default configuration file (`config.json`) for you.
If the default configuration file is not created we recommend to use `freqtrade new-config --config config.json` to generate a basic configuration file.
@@ -134,7 +134,7 @@ Mandatory parameters are marked as **Required**, which means that they are requi
| Parameter | Description |
|------------|-------------|
| `max_open_trades` | **Required.** Number of open trades your bot is allowed to have. Only one open trade per pair is possible, so the length of your pairlist is another limitation that can apply. If -1 then it is ignored (i.e. potentially unlimited open trades, limited by the pairlist). [More information below](#configuring-amount-per-trade).<br> **Datatype:** Positive integer or -1.
| `max_open_trades` | **Required.** Number of open trades your bot is allowed to have. Only one open trade per pair is possible, so the length of your pairlist is another limitation that can apply. If -1 then it is ignored (i.e. potentially unlimited open trades, limited by the pairlist). [More information below](#configuring-amount-per-trade). [Strategy Override](#parameters-in-the-strategy).<br> **Datatype:** Positive integer or -1.
| `stake_currency` | **Required.** Crypto-currency used for trading. <br> **Datatype:** String
| `stake_amount` | **Required.** Amount of crypto-currency your bot will use for each trade. Set it to `"unlimited"` to allow the bot to use all available balance. [More information below](#configuring-amount-per-trade). <br> **Datatype:** Positive float or `"unlimited"`.
| `tradable_balance_ratio` | Ratio of the total account balance the bot is allowed to trade. [More information below](#configuring-amount-per-trade). <br>*Defaults to `0.99` 99%).*<br> **Datatype:** Positive float between `0.1` and `1.0`.
@@ -263,6 +263,7 @@ Values set in the configuration file always overwrite values set in the strategy
* `minimal_roi`
* `timeframe`
* `stoploss`
* `max_open_trades`
* `trailing_stop`
* `trailing_stop_positive`
* `trailing_stop_positive_offset`
@@ -665,7 +666,7 @@ You should also make sure to read the [Exchanges](exchanges.md) section of the d
### Using proxy with Freqtrade
To use a proxy with freqtrade, export your proxy settings using the variables `"HTTP_PROXY"` and `"HTTPS_PROXY"` set to the appropriate values.
This will have the proxy settings applied to everything (telegram, coingecko, ...) except exchange requests.
This will have the proxy settings applied to everything (telegram, coingecko, ...) **except** for exchange requests.
``` bash
export HTTP_PROXY="http://addr:port"
@@ -681,11 +682,12 @@ To use a proxy for exchange connections - you will have to define the proxies as
{
"exchange": {
"ccxt_config": {
"aiohttp_proxy": "http://addr:port",
"proxies": {
"http": "http://addr:port",
"https": "http://addr:port"
},
"aiohttp_proxy": "http://addr:port",
"proxies": {
"http": "http://addr:port",
"https": "http://addr:port"
},
}
}
}
```

View File

@@ -5,7 +5,7 @@ You can analyze the results of backtests and trading history easily using Jupyte
## Quick start with docker
Freqtrade provides a docker-compose file which starts up a jupyter lab server.
You can run this server using the following command: `docker-compose -f docker/docker-compose-jupyter.yml up`
You can run this server using the following command: `docker compose -f docker/docker-compose-jupyter.yml up`
This will create a dockercontainer running jupyter lab, which will be accessible using `https://127.0.0.1:8888/lab`.
Please use the link that's printed in the console after startup for simplified login.
@@ -83,7 +83,7 @@ from pathlib import Path
project_root = "somedir/freqtrade"
i=0
try:
os.chdirdir(project_root)
os.chdir(project_root)
assert Path('LICENSE').is_file()
except:
while i<4 and (not Path('LICENSE').is_file()):

View File

@@ -49,6 +49,13 @@ For more information about the [Remote container extension](https://code.visuals
New code should be covered by basic unittests. Depending on the complexity of the feature, Reviewers may request more in-depth unittests.
If necessary, the Freqtrade team can assist and give guidance with writing good tests (however please don't expect anyone to write the tests for you).
#### How to run tests
Use `pytest` in root folder to run all available testcases and confirm your local environment is setup correctly
!!! Note "feature branches"
Tests are expected to pass on the `develop` and `stable` branches. Other branches may be work in progress with tests not working yet.
#### Checking log content in tests
Freqtrade uses 2 main methods to check log content in tests, `log_has()` and `log_has_re()` (to check using regex, in case of dynamic log-messages).
@@ -356,7 +363,7 @@ from pathlib import Path
exchange = ccxt.binance({
'apiKey': '<apikey>',
'secret': '<secret>'
'options': {'defaultType': 'future'}
'options': {'defaultType': 'swap'}
})
_ = exchange.load_markets()

View File

@@ -4,20 +4,22 @@ This page explains how to run the bot with Docker. It is not meant to work out o
## Install Docker
Start by downloading and installing Docker CE for your platform:
Start by downloading and installing Docker / Docker Desktop for your platform:
* [Mac](https://docs.docker.com/docker-for-mac/install/)
* [Windows](https://docs.docker.com/docker-for-windows/install/)
* [Linux](https://docs.docker.com/install/)
To simplify running freqtrade, [`docker-compose`](https://docs.docker.com/compose/install/) should be installed and available to follow the below [docker quick start guide](#docker-quick-start).
!!! Info "Docker compose install"
Freqtrade documentation assumes the use of Docker desktop (or the docker compose plugin).
While the docker-compose standalone installation still works, it will require changing all `docker compose` commands from `docker compose` to `docker-compose` to work (e.g. `docker compose up -d` will become `docker-compose up -d`).
## Freqtrade with docker-compose
## Freqtrade with docker
Freqtrade provides an official Docker image on [Dockerhub](https://hub.docker.com/r/freqtradeorg/freqtrade/), as well as a [docker-compose file](https://github.com/freqtrade/freqtrade/blob/stable/docker-compose.yml) ready for usage.
Freqtrade provides an official Docker image on [Dockerhub](https://hub.docker.com/r/freqtradeorg/freqtrade/), as well as a [docker compose file](https://github.com/freqtrade/freqtrade/blob/stable/docker-compose.yml) ready for usage.
!!! Note
- The following section assumes that `docker` and `docker-compose` are installed and available to the logged in user.
- The following section assumes that `docker` is installed and available to the logged in user.
- All below commands use relative directories and will have to be executed from the directory containing the `docker-compose.yml` file.
### Docker quick start
@@ -31,13 +33,13 @@ cd ft_userdata/
curl https://raw.githubusercontent.com/freqtrade/freqtrade/stable/docker-compose.yml -o docker-compose.yml
# Pull the freqtrade image
docker-compose pull
docker compose pull
# Create user directory structure
docker-compose run --rm freqtrade create-userdir --userdir user_data
docker compose run --rm freqtrade create-userdir --userdir user_data
# Create configuration - Requires answering interactive questions
docker-compose run --rm freqtrade new-config --config user_data/config.json
docker compose run --rm freqtrade new-config --config user_data/config.json
```
The above snippet creates a new directory called `ft_userdata`, downloads the latest compose file and pulls the freqtrade image.
@@ -64,7 +66,7 @@ The `SampleStrategy` is run by default.
Once this is done, you're ready to launch the bot in trading mode (Dry-run or Live-trading, depending on your answer to the corresponding question you made above).
``` bash
docker-compose up -d
docker compose up -d
```
!!! Warning "Default configuration"
@@ -84,27 +86,27 @@ You can now access the UI by typing localhost:8080 in your browser.
#### Monitoring the bot
You can check for running instances with `docker-compose ps`.
You can check for running instances with `docker compose ps`.
This should list the service `freqtrade` as `running`. If that's not the case, best check the logs (see next point).
#### Docker-compose logs
#### Docker compose logs
Logs will be written to: `user_data/logs/freqtrade.log`.
You can also check the latest log with the command `docker-compose logs -f`.
You can also check the latest log with the command `docker compose logs -f`.
#### Database
The database will be located at: `user_data/tradesv3.sqlite`
#### Updating freqtrade with docker-compose
#### Updating freqtrade with docker
Updating freqtrade when using `docker-compose` is as simple as running the following 2 commands:
Updating freqtrade when using `docker` is as simple as running the following 2 commands:
``` bash
# Download the latest image
docker-compose pull
docker compose pull
# Restart the image
docker-compose up -d
docker compose up -d
```
This will first pull the latest image, and will then restart the container with the just pulled version.
@@ -116,43 +118,43 @@ This will first pull the latest image, and will then restart the container with
Advanced users may edit the docker-compose file further to include all possible options or arguments.
All freqtrade arguments will be available by running `docker-compose run --rm freqtrade <command> <optional arguments>`.
All freqtrade arguments will be available by running `docker compose run --rm freqtrade <command> <optional arguments>`.
!!! Warning "`docker-compose` for trade commands"
Trade commands (`freqtrade trade <...>`) should not be ran via `docker-compose run` - but should use `docker-compose up -d` instead.
!!! Warning "`docker compose` for trade commands"
Trade commands (`freqtrade trade <...>`) should not be ran via `docker compose run` - but should use `docker compose up -d` instead.
This makes sure that the container is properly started (including port forwardings) and will make sure that the container will restart after a system reboot.
If you intend to use freqUI, please also ensure to adjust the [configuration accordingly](rest-api.md#configuration-with-docker), otherwise the UI will not be available.
!!! Note "`docker-compose run --rm`"
!!! Note "`docker compose run --rm`"
Including `--rm` will remove the container after completion, and is highly recommended for all modes except trading mode (running with `freqtrade trade` command).
??? Note "Using docker without docker-compose"
"`docker-compose run --rm`" will require a compose file to be provided.
??? Note "Using docker without docker"
"`docker compose run --rm`" will require a compose file to be provided.
Some freqtrade commands that don't require authentication such as `list-pairs` can be run with "`docker run --rm`" instead.
For example `docker run --rm freqtradeorg/freqtrade:stable list-pairs --exchange binance --quote BTC --print-json`.
This can be useful for fetching exchange information to add to your `config.json` without affecting your running containers.
#### Example: Download data with docker-compose
#### Example: Download data with docker
Download backtesting data for 5 days for the pair ETH/BTC and 1h timeframe from Binance. The data will be stored in the directory `user_data/data/` on the host.
``` bash
docker-compose run --rm freqtrade download-data --pairs ETH/BTC --exchange binance --days 5 -t 1h
docker compose run --rm freqtrade download-data --pairs ETH/BTC --exchange binance --days 5 -t 1h
```
Head over to the [Data Downloading Documentation](data-download.md) for more details on downloading data.
#### Example: Backtest with docker-compose
#### Example: Backtest with docker
Run backtesting in docker-containers for SampleStrategy and specified timerange of historical data, on 5m timeframe:
``` bash
docker-compose run --rm freqtrade backtesting --config user_data/config.json --strategy SampleStrategy --timerange 20190801-20191001 -i 5m
docker compose run --rm freqtrade backtesting --config user_data/config.json --strategy SampleStrategy --timerange 20190801-20191001 -i 5m
```
Head over to the [Backtesting Documentation](backtesting.md) to learn more.
### Additional dependencies with docker-compose
### Additional dependencies with docker
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.custom) for an example).
@@ -166,15 +168,15 @@ You'll then also need to modify the `docker-compose.yml` file and uncomment the
dockerfile: "./Dockerfile.<yourextension>"
```
You can then run `docker-compose build --pull` to build the docker image, and run it using the commands described above.
You can then run `docker compose build --pull` to build the docker image, and run it using the commands described above.
### Plotting with docker-compose
### Plotting with docker
Commands `freqtrade plot-profit` and `freqtrade plot-dataframe` ([Documentation](plotting.md)) are available by changing the image to `*_plot` in your docker-compose.yml file.
You can then use these commands as follows:
``` bash
docker-compose run --rm freqtrade plot-dataframe --strategy AwesomeStrategy -p BTC/ETH --timerange=20180801-20180805
docker compose run --rm freqtrade plot-dataframe --strategy AwesomeStrategy -p BTC/ETH --timerange=20180801-20180805
```
The output will be stored in the `user_data/plot` directory, and can be opened with any modern browser.
@@ -185,7 +187,7 @@ Freqtrade provides a docker-compose file which starts up a jupyter lab server.
You can run this server using the following command:
``` bash
docker-compose -f docker/docker-compose-jupyter.yml up
docker compose -f docker/docker-compose-jupyter.yml up
```
This will create a docker-container running jupyter lab, which will be accessible using `https://127.0.0.1:8888/lab`.
@@ -194,7 +196,7 @@ Please use the link that's printed in the console after startup for simplified l
Since part of this image is built on your machine, it is recommended to rebuild the image from time to time to keep freqtrade (and dependencies) up-to-date.
``` bash
docker-compose -f docker/docker-compose-jupyter.yml build --no-cache
docker compose -f docker/docker-compose-jupyter.yml build --no-cache
```
## Troubleshooting

View File

@@ -54,6 +54,9 @@ This configuration enables kraken, as well as rate-limiting to avoid bans from t
## Binance
!!! Warning "Server location and geo-ip restrictions"
Please be aware that binance restrict api access regarding the server country. The currents and non exhaustive countries blocked are United States, Malaysia (Singapour), Ontario (Canada). Please go to [binance terms > b. Eligibility](https://www.binance.com/en/terms) to find up to date list.
Binance supports [time_in_force](configuration.md#understand-order_time_in_force).
!!! Tip "Stoploss on Exchange"
@@ -72,6 +75,25 @@ Binance has been split into 2, and users must use the correct ccxt exchange ID f
* [binance.com](https://www.binance.com/) - International users. Use exchange id: `binance`.
* [binance.us](https://www.binance.us/) - US based users. Use exchange id: `binanceus`.
### Binance RSA keys
Freqtrade supports binance RSA API keys.
We recommend to use them as environment variable.
``` bash
export FREQTRADE__EXCHANGE__SECRET="$(cat ./rsa_binance.private)"
```
They can however also be configured via configuration file. Since json doesn't support multi-line strings, you'll have to replace all newlines with `\n` to have a valid json file.
``` json
// ...
"key": "<someapikey>",
"secret": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBABACAFQA<...>s8KX8=\n-----END PRIVATE KEY-----"
// ...
```
### Binance Futures
Binance has specific (unfortunately complex) [Futures Trading Quantitative Rules](https://www.binance.com/en/support/faq/4f462ebe6ff445d4a170be7d9e897272) which need to be followed, and which prohibit a too low stake-amount (among others) for too many orders.
@@ -221,8 +243,8 @@ OKX requires a passphrase for each api key, you will therefore need to add this
OKX only provides 100 candles per api call. Therefore, the strategy will only have a pretty low amount of data available in backtesting mode.
!!! Warning "Futures"
OKX Futures has the concept of "position mode" - which can be Net or long/short (hedge mode).
Freqtrade supports both modes (we recommend to use net mode) - but changing the mode mid-trading is not supported and will lead to exceptions and failures to place trades.
OKX Futures has the concept of "position mode" - which can be "Buy/Sell" or long/short (hedge mode).
Freqtrade supports both modes (we recommend to use Buy/Sell mode) - but changing the mode mid-trading is not supported and will lead to exceptions and failures to place trades.
OKX also only provides MARK candles for the past ~3 months. Backtesting futures prior to that date will therefore lead to slight deviations, as funding-fees cannot be calculated correctly without this data.
## Gate.io
@@ -233,6 +255,18 @@ OKX requires a passphrase for each api key, you will therefore need to add this
Gate.io allows the use of `POINT` to pay for fees. As this is not a tradable currency (no regular market available), automatic fee calculations will fail (and default to a fee of 0).
The configuration parameter `exchange.unknown_fee_rate` can be used to specify the exchange rate between Point and the stake currency. Obviously, changing the stake-currency will also require changes to this value.
## Bybit
Futures trading on bybit is currently supported for USDT markets, and will use isolated futures mode.
Users with unified accounts (there's no way back) can create a Sub-account which will start as "non-unified", and can therefore use isolated futures.
On startup, freqtrade will set the position mode to "One-way Mode" for the whole (sub)account. This avoids making this call over and over again (slowing down bot operations), but means that changes to this setting may result in exceptions and errors.
As bybit doesn't provide funding rate history, the dry-run calculation is used for live trades as well.
!!! Tip "Stoploss on Exchange"
Bybit (futures only) supports `stoploss_on_exchange` and uses `stop-loss-limit` orders. It provides great advantages, so we recommend to benefit from it by enabling stoploss on exchange.
On futures, Bybit supports both `stop-limit` as well as `stop-market` orders. You can use either `"limit"` or `"market"` in the `order_types.stoploss` configuration setting to decide which type to use.
## All exchanges
Should you experience constant errors with Nonce (like `InvalidNonce`), it is best to regenerate the API keys. Resetting Nonce is difficult and it's usually easier to regenerate the API keys.

View File

@@ -2,7 +2,7 @@
## Supported Markets
Freqtrade supports spot trading only.
Freqtrade supports spot trading, as well as (isolated) futures trading for some selected exchanges. Please refer to the [documentation start page](index.md#supported-futures-exchanges-experimental) for an uptodate list of supported exchanges.
### Can my bot open short positions?
@@ -248,8 +248,26 @@ The Edge module is mostly a result of brainstorming of [@mishaker](https://githu
You can find further info on expectancy, win rate, risk management and position size in the following sources:
- https://www.tradeciety.com/ultimate-math-guide-for-traders/
- http://www.vantharp.com/tharp-concepts/expectancy.asp
- https://samuraitradingacademy.com/trading-expectancy/
- https://www.learningmarkets.com/determining-expectancy-in-your-trading/
- http://www.lonestocktrader.com/make-money-trading-positive-expectancy/
- https://www.lonestocktrader.com/make-money-trading-positive-expectancy/
- https://www.babypips.com/trading/trade-expectancy-matter
## Official channels
Freqtrade is using exclusively the following official channels:
* [Freqtrade discord server](https://discord.gg/p7nuUNVfP7)
* [Freqtrade documentation (https://freqtrade.io)](https://freqtrade.io)
* [Freqtrade github organization](https://github.com/freqtrade)
Nobody affiliated with the freqtrade project will ask you about your exchange keys or anything else exposing your funds to exploitation.
Should you be asked to expose your exchange keys or send funds to some random wallet, then please don't follow these instructions.
Failing to follow these guidelines will not be responsibility of freqtrade.
## "Freqtrade token"
Freqtrade does not have a Crypto token offering.
Token offerings you find on the internet referring Freqtrade, FreqAI or freqUI must be considered to be a scam, trying to exploit freqtrade's popularity for their own, nefarious gains.

View File

@@ -9,7 +9,7 @@ FreqAI is configured through the typical [Freqtrade config file](configuration.m
```json
"freqai": {
"enabled": true,
"purge_old_models": true,
"purge_old_models": 2,
"train_period_days": 30,
"backtest_period_days": 7,
"identifier" : "unique-id",
@@ -26,10 +26,7 @@ FreqAI is configured through the typical [Freqtrade config file](configuration.m
},
"data_split_parameters" : {
"test_size": 0.25
},
"model_training_parameters" : {
"n_estimators": 100
},
}
}
```
@@ -46,116 +43,113 @@ The FreqAI strategy requires including the following lines of code in the standa
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# the model will return all labels created by user in `populate_any_indicators`
# the model will return all labels created by user in `set_freqai_labels()`
# (& appended targets), an indication of whether or not the prediction should be accepted,
# the target mean/std values for each of the labels created by user in
# `populate_any_indicators()` for each training period.
# `feature_engineering_*` for each training period.
dataframe = self.freqai.start(dataframe, metadata, self)
return dataframe
def populate_any_indicators(
self, pair, df, tf, informative=None, set_generalized_indicators=False
):
def feature_engineering_expand_all(self, dataframe, period, **kwargs):
"""
Function designed to automatically generate, name and merge features
from user indicated timeframes in the configuration file. User controls the indicators
passed to the training/prediction by prepending indicators with `'%-' + pair `
(see convention below). I.e. user should not prepend any supporting metrics
(e.g. bb_lowerband below) with % unless they explicitly want to pass that metric to the
model.
:param pair: pair to be used as informative
:param df: strategy dataframe which will receive merges from informatives
:param tf: timeframe of the dataframe which will modify the feature names
:param informative: the dataframe associated with the informative pair
*Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined
`indicator_periods_candles`, `include_timeframes`, `include_shifted_candles`, and
`include_corr_pairs`. In other words, a single feature defined in this function
will automatically expand to a total of
`indicator_periods_candles` * `include_timeframes` * `include_shifted_candles` *
`include_corr_pairs` numbers of features added to the model.
All features must be prepended with `%` to be recognized by FreqAI internals.
:param df: strategy dataframe which will receive the features
:param period: period of the indicator - usage example:
dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period)
"""
if informative is None:
informative = self.dp.get_pair_dataframe(pair, tf)
dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period)
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
dataframe["%-sma-period"] = ta.SMA(dataframe, timeperiod=period)
dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period)
# first loop is automatically duplicating indicators for time periods
for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]:
t = int(t)
informative[f"%-{pair}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t)
informative[f"%-{pair}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t)
informative[f"%-{pair}adx-period_{t}"] = ta.ADX(informative, window=t)
return dataframe
indicators = [col for col in informative if col.startswith("%")]
# This loop duplicates and shifts all indicators to add a sense of recency to data
for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1):
if n == 0:
continue
informative_shift = informative[indicators].shift(n)
informative_shift = informative_shift.add_suffix("_shift-" + str(n))
informative = pd.concat((informative, informative_shift), axis=1)
def feature_engineering_expand_basic(self, dataframe, **kwargs):
"""
*Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined
`include_timeframes`, `include_shifted_candles`, and `include_corr_pairs`.
In other words, a single feature defined in this function
will automatically expand to a total of
`include_timeframes` * `include_shifted_candles` * `include_corr_pairs`
numbers of features added to the model.
df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True)
skip_columns = [
(s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"]
]
df = df.drop(columns=skip_columns)
Features defined here will *not* be automatically duplicated on user defined
`indicator_periods_candles`
# Add generalized indicators here (because in live, it will call this
# function to populate indicators during training). Notice how we ensure not to
# add them multiple times
if set_generalized_indicators:
All features must be prepended with `%` to be recognized by FreqAI internals.
# user adds targets here by prepending them with &- (see convention below)
# If user wishes to use multiple targets, a multioutput prediction model
# needs to be used such as templates/CatboostPredictionMultiModel.py
df["&-s_close"] = (
df["close"]
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
.mean()
/ df["close"]
- 1
:param df: strategy dataframe which will receive the features
dataframe["%-pct-change"] = dataframe["close"].pct_change()
dataframe["%-ema-200"] = ta.EMA(dataframe, timeperiod=200)
"""
dataframe["%-pct-change"] = dataframe["close"].pct_change()
dataframe["%-raw_volume"] = dataframe["volume"]
dataframe["%-raw_price"] = dataframe["close"]
return dataframe
def feature_engineering_standard(self, dataframe, **kwargs):
"""
*Only functional with FreqAI enabled strategies*
This optional function will be called once with the dataframe of the base timeframe.
This is the final function to be called, which means that the dataframe entering this
function will contain all the features and columns created by all other
freqai_feature_engineering_* functions.
This function is a good place to do custom exotic feature extractions (e.g. tsfresh).
This function is a good place for any feature that should not be auto-expanded upon
(e.g. day of the week).
All features must be prepended with `%` to be recognized by FreqAI internals.
:param df: strategy dataframe which will receive the features
usage example: dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7
"""
dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7
dataframe["%-hour_of_day"] = (dataframe["date"].dt.hour + 1) / 25
return dataframe
def set_freqai_targets(self, dataframe, **kwargs):
"""
*Only functional with FreqAI enabled strategies*
Required function to set the targets for the model.
All targets must be prepended with `&` to be recognized by the FreqAI internals.
:param df: strategy dataframe which will receive the targets
usage example: dataframe["&-target"] = dataframe["close"].shift(-1) / dataframe["close"]
"""
dataframe["&-s_close"] = (
dataframe["close"]
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
.mean()
/ dataframe["close"]
- 1
)
return df
```
Notice how the `populate_any_indicators()` is where [features](freqai-feature-engineering.md#feature-engineering) and labels/targets are added. A full example strategy is available in `templates/FreqaiExampleStrategy.py`.
Notice also the location of the labels under `if set_generalized_indicators:` at the bottom of the example. This is where single features and labels/targets should be added to the feature set to avoid duplication of them from various configuration parameters that multiply the feature set, such as `include_timeframes`.
Notice how the `feature_engineering_*()` is where [features](freqai-feature-engineering.md#feature-engineering) are added. Meanwhile `set_freqai_targets()` adds the labels/targets. A full example strategy is available in `templates/FreqaiExampleStrategy.py`.
!!! Note
The `self.freqai.start()` function cannot be called outside the `populate_indicators()`.
!!! Note
Features **must** be defined in `populate_any_indicators()`. Defining FreqAI features in `populate_indicators()`
will cause the algorithm to fail in live/dry mode. In order to add generalized features that are not associated with a specific pair or timeframe, the following structure inside `populate_any_indicators()` should be used
(as exemplified in `freqtrade/templates/FreqaiExampleStrategy.py`):
```python
def populate_any_indicators(self, pair, df, tf, informative=None, set_generalized_indicators=False):
...
# Add generalized indicators here (because in live, it will call only this function to populate
# indicators for retraining). Notice how we ensure not to add them multiple times by associating
# these generalized indicators to the basepair/timeframe
if set_generalized_indicators:
df['%-day_of_week'] = (df["date"].dt.dayofweek + 1) / 7
df['%-hour_of_day'] = (df['date'].dt.hour + 1) / 25
# user adds targets here by prepending them with &- (see convention below)
# If user wishes to use multiple targets, a multioutput prediction model
# needs to be used such as templates/CatboostPredictionMultiModel.py
df["&-s_close"] = (
df["close"]
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
.mean()
/ df["close"]
- 1
)
```
Please see the example script located in `freqtrade/templates/FreqaiExampleStrategy.py` for a full example of `populate_any_indicators()`.
Features **must** be defined in `feature_engineering_*()`. Defining FreqAI features in `populate_indicators()`
will cause the algorithm to fail in live/dry mode. In order to add generalized features that are not associated with a specific pair or timeframe, you should use `feature_engineering_standard()`
(as exemplified in `freqtrade/templates/FreqaiExampleStrategy.py`).
## Important dataframe key patterns
@@ -163,18 +157,18 @@ Below are the values you can expect to include/use inside a typical strategy dat
| DataFrame Key | Description |
|------------|-------------|
| `df['&*']` | Any dataframe column prepended with `&` in `populate_any_indicators()` is treated as a training target (label) inside FreqAI (typically following the naming convention `&-s*`). For example, to predict the close price 40 candles into the future, you would set `df['&-s_close'] = df['close'].shift(-self.freqai_info["feature_parameters"]["label_period_candles"])` with `"label_period_candles": 40` in the config. FreqAI makes the predictions and gives them back under the same key (`df['&-s_close']`) to be used in `populate_entry/exit_trend()`. <br> **Datatype:** Depends on the output of the model.
| `df['&*']` | Any dataframe column prepended with `&` in `set_freqai_targets()` is treated as a training target (label) inside FreqAI (typically following the naming convention `&-s*`). For example, to predict the close price 40 candles into the future, you would set `df['&-s_close'] = df['close'].shift(-self.freqai_info["feature_parameters"]["label_period_candles"])` with `"label_period_candles": 40` in the config. FreqAI makes the predictions and gives them back under the same key (`df['&-s_close']`) to be used in `populate_entry/exit_trend()`. <br> **Datatype:** Depends on the output of the model.
| `df['&*_std/mean']` | Standard deviation and mean values of the defined labels during training (or live tracking with `fit_live_predictions_candles`). Commonly used to understand the rarity of a prediction (use the z-score as shown in `templates/FreqaiExampleStrategy.py` and explained [here](#creating-a-dynamic-target-threshold) to evaluate how often a particular prediction was observed during training or historically with `fit_live_predictions_candles`). <br> **Datatype:** Float.
| `df['do_predict']` | Indication of an outlier data point. The return value is integer between -2 and 2, which lets you know if the prediction is trustworthy or not. `do_predict==1` means that the prediction is trustworthy. If the Dissimilarity Index (DI, see details [here](freqai-feature-engineering.md#identifying-outliers-with-the-dissimilarity-index-di)) of the input data point is above the threshold defined in the config, FreqAI will subtract 1 from `do_predict`, resulting in `do_predict==0`. If `use_SVM_to_remove_outliers()` is active, the Support Vector Machine (SVM, see details [here](freqai-feature-engineering.md#identifying-outliers-using-a-support-vector-machine-svm)) may also detect outliers in training and prediction data. In this case, the SVM will also subtract 1 from `do_predict`. If the input data point was considered an outlier by the SVM but not by the DI, or vice versa, the result will be `do_predict==0`. If both the DI and the SVM considers the input data point to be an outlier, the result will be `do_predict==-1`. As with the SVM, if `use_DBSCAN_to_remove_outliers` is active, DBSCAN (see details [here](freqai-feature-engineering.md#identifying-outliers-with-dbscan)) may also detect outliers and subtract 1 from `do_predict`. Hence, if both the SVM and DBSCAN are active and identify a datapoint that was above the DI threshold as an outlier, the result will be `do_predict==-2`. A particular case is when `do_predict == 2`, which means that the model has expired due to exceeding `expired_hours`. <br> **Datatype:** Integer between -2 and 2.
| `df['DI_values']` | Dissimilarity Index (DI) values are proxies for the level of confidence FreqAI has in the prediction. A lower DI means the prediction is close to the training data, i.e., higher prediction confidence. See details about the DI [here](freqai-feature-engineering.md#identifying-outliers-with-the-dissimilarity-index-di). <br> **Datatype:** Float.
| `df['%*']` | Any dataframe column prepended with `%` in `populate_any_indicators()` is treated as a training feature. For example, you can include the RSI in the training feature set (similar to in `templates/FreqaiExampleStrategy.py`) by setting `df['%-rsi']`. See more details on how this is done [here](freqai-feature-engineering.md). <br> **Note:** Since the number of features prepended with `%` can multiply very quickly (10s of thousands of features are easily engineered using the multiplictative functionality of, e.g., `include_shifted_candles` and `include_timeframes` as described in the [parameter table](freqai-parameter-table.md)), these features are removed from the dataframe that is returned from FreqAI to the strategy. To keep a particular type of feature for plotting purposes, you would prepend it with `%%`. <br> **Datatype:** Depends on the output of the model.
| `df['%*']` | Any dataframe column prepended with `%` in `feature_engineering_*()` is treated as a training feature. For example, you can include the RSI in the training feature set (similar to in `templates/FreqaiExampleStrategy.py`) by setting `df['%-rsi']`. See more details on how this is done [here](freqai-feature-engineering.md). <br> **Note:** Since the number of features prepended with `%` can multiply very quickly (10s of thousands of features are easily engineered using the multiplictative functionality of, e.g., `include_shifted_candles` and `include_timeframes` as described in the [parameter table](freqai-parameter-table.md)), these features are removed from the dataframe that is returned from FreqAI to the strategy. To keep a particular type of feature for plotting purposes, you would prepend it with `%%`. <br> **Datatype:** Depends on the output of the model.
## Setting the `startup_candle_count`
The `startup_candle_count` in the FreqAI strategy needs to be set up in the same way as in the standard Freqtrade strategy (see details [here](strategy-customization.md#strategy-startup-period)). This value is used by Freqtrade to ensure that a sufficient amount of data is provided when calling the `dataprovider`, to avoid any NaNs at the beginning of the first training. You can easily set this value by identifying the longest period (in candle units) which is passed to the indicator creation functions (e.g., Ta-Lib functions). In the presented example, `startup_candle_count` is 20 since this is the maximum value in `indicators_periods_candles`.
The `startup_candle_count` in the FreqAI strategy needs to be set up in the same way as in the standard Freqtrade strategy (see details [here](strategy-customization.md#strategy-startup-period)). This value is used by Freqtrade to ensure that a sufficient amount of data is provided when calling the `dataprovider`, to avoid any NaNs at the beginning of the first training. You can easily set this value by identifying the longest period (in candle units) which is passed to the indicator creation functions (e.g., TA-Lib functions). In the presented example, `startup_candle_count` is 20 since this is the maximum value in `indicators_periods_candles`.
!!! Note
There are instances where the Ta-Lib functions actually require more data than just the passed `period` or else the feature dataset gets populated with NaNs. Anecdotally, multiplying the `startup_candle_count` by 2 always leads to a fully NaN free training dataset. Hence, it is typically safest to multiply the expected `startup_candle_count` by 2. Look out for this log message to confirm that the data is clean:
There are instances where the TA-Lib functions actually require more data than just the passed `period` or else the feature dataset gets populated with NaNs. Anecdotally, multiplying the `startup_candle_count` by 2 always leads to a fully NaN free training dataset. Hence, it is typically safest to multiply the expected `startup_candle_count` by 2. Look out for this log message to confirm that the data is clean:
```
2022-08-31 15:14:04 - freqtrade.freqai.data_kitchen - INFO - dropped 0 training points due to NaNs in populated dataset 4319.
@@ -182,7 +176,7 @@ The `startup_candle_count` in the FreqAI strategy needs to be set up in the same
## Creating a dynamic target threshold
Deciding when to enter or exit a trade can be done in a dynamic way to reflect current market conditions. FreqAI allows you to return additional information from the training of a model (more info [here](freqai-feature-engineering.md#returning-additional-info-from-training)). For example, the `&*_std/mean` return values describe the statistical distribution of the target/label *during the most recent training*. Comparing a given prediction to these values allows you to know the rarity of the prediction. In `templates/FreqaiExampleStrategy.py`, the `target_roi` and `sell_roi` are defined to be 1.25 z-scores away from the mean which causes predictions that are closer to the mean to be filtered out.
Deciding when to enter or exit a trade can be done in a dynamic way to reflect current market conditions. FreqAI allows you to return additional information from the training of a model (more info [here](freqai-feature-engineering.md#returning-additional-info-from-training)). For example, the `&*_std/mean` return values describe the statistical distribution of the target/label *during the most recent training*. Comparing a given prediction to these values allows you to know the rarity of the prediction. In `templates/FreqaiExampleStrategy.py`, the `target_roi` and `sell_roi` are defined to be 1.25 z-scores away from the mean which causes predictions that are closer to the mean to be filtered out.
```python
dataframe["target_roi"] = dataframe["&-s_close_mean"] + dataframe["&-s_close_std"] * 1.25
@@ -211,7 +205,7 @@ All of the aforementioned model libraries implement gradient boosted decision tr
* LightGBM: https://lightgbm.readthedocs.io/en/v3.3.2/#
* XGBoost: https://xgboost.readthedocs.io/en/stable/#
There are also numerous online articles describing and comparing the algorithms. Some relatively light-weight examples would be [CatBoost vs. LightGBM vs. XGBoost — Which is the best algorithm?](https://towardsdatascience.com/catboost-vs-lightgbm-vs-xgboost-c80f40662924#:~:text=In%20CatBoost%2C%20symmetric%20trees%2C%20or,the%20same%20depth%20can%20differ.) and [XGBoost, LightGBM or CatBoost — which boosting algorithm should I use?](https://medium.com/riskified-technology/xgboost-lightgbm-or-catboost-which-boosting-algorithm-should-i-use-e7fda7bb36bc). Keep in mind that the performance of each model is highly dependent on the application and so any reported metrics might not be true for your particular use of the model.
There are also numerous online articles describing and comparing the algorithms. Some relatively lightweight examples would be [CatBoost vs. LightGBM vs. XGBoost — Which is the best algorithm?](https://towardsdatascience.com/catboost-vs-lightgbm-vs-xgboost-c80f40662924#:~:text=In%20CatBoost%2C%20symmetric%20trees%2C%20or,the%20same%20depth%20can%20differ.) and [XGBoost, LightGBM or CatBoost — which boosting algorithm should I use?](https://medium.com/riskified-technology/xgboost-lightgbm-or-catboost-which-boosting-algorithm-should-i-use-e7fda7bb36bc). Keep in mind that the performance of each model is highly dependent on the application and so any reported metrics might not be true for your particular use of the model.
Apart from the models already available in FreqAI, it is also possible to customize and create your own prediction models using the `IFreqaiModel` class. You are encouraged to inherit `fit()`, `train()`, and `predict()` to customize various aspects of the training procedures. You can place custom FreqAI models in `user_data/freqaimodels` - and freqtrade will pick them up from there based on the provided `--freqaimodel` name - which has to correspond to the class name of your custom model.
Make sure to use unique names to avoid overriding built-in models.
@@ -230,7 +224,7 @@ If you want to predict multiple targets, you need to define multiple labels usin
#### Classifiers
If you are using a classifier, you need to specify a target that has discrete values. FreqAI includes a variety of classifiers, such as the `CatboostClassifier` via the flag `--freqaimodel CatboostClassifier`. If you elects to use a classifier, the classes need to be set using strings. For example, if you want to predict if the price 100 candles into the future goes up or down you would set
If you are using a classifier, you need to specify a target that has discrete values. FreqAI includes a variety of classifiers, such as the `CatboostClassifier` via the flag `--freqaimodel CatboostClassifier`. If you elects to use a classifier, the classes need to be set using strings. For example, if you want to predict if the price 100 candles into the future goes up or down you would set
```python
df['&s-up_or_down'] = np.where( df["close"].shift(-100) > df["close"], 'up', 'down')

View File

@@ -2,96 +2,150 @@
## Defining the features
Low level feature engineering is performed in the user strategy within a function called `populate_any_indicators()`. That function sets the `base features` such as, `RSI`, `MFI`, `EMA`, `SMA`, time of day, volume, etc. The `base features` can be custom indicators or they can be imported from any technical-analysis library that you can find. One important syntax rule is that all `base features` string names are prepended with `%-{pair}`, while labels/targets are prepended with `&`.
Low level feature engineering is performed in the user strategy within a set of functions called `feature_engineering_*`. These function set the `base features` such as, `RSI`, `MFI`, `EMA`, `SMA`, time of day, volume, etc. The `base features` can be custom indicators or they can be imported from any technical-analysis library that you can find. FreqAI is equipped with a set of functions to simplify rapid large-scale feature engineering:
!!! Note
Adding the full pair string, e.g. XYZ/USD, in the feature name enables improved performance for dataframe caching on the backend. If you decide *not* to add the full pair string in the feature string, FreqAI will operate in a reduced performance mode.
| Function | Description |
|---------------|-------------|
| `feature_engineering__expand_all()` | This optional function will automatically expand the defined features on the config defined `indicator_periods_candles`, `include_timeframes`, `include_shifted_candles`, and `include_corr_pairs`.
| `feature_engineering__expand_basic()` | This optional function will automatically expand the defined features on the config defined `include_timeframes`, `include_shifted_candles`, and `include_corr_pairs`. Note: this function does *not* expand across `include_periods_candles`.
| `feature_engineering_standard()` | This optional function will be called once with the dataframe of the base timeframe. This is the final function to be called, which means that the dataframe entering this function will contain all the features and columns from the base asset created by the other `feature_engineering_expand` functions. This function is a good place to do custom exotic feature extractions (e.g. tsfresh). This function is also a good place for any feature that should not be auto-expanded upon (e.g., day of the week).
| `set_freqai_targets()` | Required function to set the targets for the model. All targets must be prepended with `&` to be recognized by the FreqAI internals.
Meanwhile, high level feature engineering is handled within `"feature_parameters":{}` in the FreqAI config. Within this file, it is possible to decide large scale feature expansions on top of the `base_features` such as "including correlated pairs" or "including informative timeframes" or even "including recent candles."
It is advisable to start from the template `populate_any_indicators()` in the source provided example strategy (found in `templates/FreqaiExampleStrategy.py`) to ensure that the feature definitions are following the correct conventions. Here is an example of how to set the indicators and labels in the strategy:
It is advisable to start from the template `feature_engineering_*` functions in the source provided example strategy (found in `templates/FreqaiExampleStrategy.py`) to ensure that the feature definitions are following the correct conventions. Here is an example of how to set the indicators and labels in the strategy:
```python
def populate_any_indicators(
self, pair, df, tf, informative=None, set_generalized_indicators=False
):
def feature_engineering_expand_all(self, dataframe, period, metadata, **kwargs):
"""
Function designed to automatically generate, name, and merge features
from user-indicated timeframes in the configuration file. The user controls the indicators
passed to the training/prediction by prepending indicators with `'%-' + pair `
(see convention below). I.e., the user should not prepend any supporting metrics
(e.g., bb_lowerband below) with % unless they explicitly want to pass that metric to the
model.
:param pair: pair to be used as informative
:param df: strategy dataframe which will receive merges from informatives
:param tf: timeframe of the dataframe which will modify the feature names
:param informative: the dataframe associated with the informative pair
*Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined
`indicator_periods_candles`, `include_timeframes`, `include_shifted_candles`, and
`include_corr_pairs`. In other words, a single feature defined in this function
will automatically expand to a total of
`indicator_periods_candles` * `include_timeframes` * `include_shifted_candles` *
`include_corr_pairs` numbers of features added to the model.
All features must be prepended with `%` to be recognized by FreqAI internals.
Access metadata such as the current pair/timeframe/period with:
`metadata["pair"]` `metadata["tf"]` `metadata["period"]`
:param df: strategy dataframe which will receive the features
:param period: period of the indicator - usage example:
:param metadata: metadata of current pair
dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period)
"""
if informative is None:
informative = self.dp.get_pair_dataframe(pair, tf)
dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period)
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
dataframe["%-sma-period"] = ta.SMA(dataframe, timeperiod=period)
dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period)
# first loop is automatically duplicating indicators for time periods
for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]:
t = int(t)
informative[f"%-{pair}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t)
informative[f"%-{pair}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t)
informative[f"%-{pair}adx-period_{t}"] = ta.ADX(informative, window=t)
bollinger = qtpylib.bollinger_bands(
qtpylib.typical_price(dataframe), window=period, stds=2.2
)
dataframe["bb_lowerband-period"] = bollinger["lower"]
dataframe["bb_middleband-period"] = bollinger["mid"]
dataframe["bb_upperband-period"] = bollinger["upper"]
bollinger = qtpylib.bollinger_bands(
qtpylib.typical_price(informative), window=t, stds=2.2
dataframe["%-bb_width-period"] = (
dataframe["bb_upperband-period"]
- dataframe["bb_lowerband-period"]
) / dataframe["bb_middleband-period"]
dataframe["%-close-bb_lower-period"] = (
dataframe["close"] / dataframe["bb_lowerband-period"]
)
dataframe["%-roc-period"] = ta.ROC(dataframe, timeperiod=period)
dataframe["%-relative_volume-period"] = (
dataframe["volume"] / dataframe["volume"].rolling(period).mean()
)
return dataframe
def feature_engineering_expand_basic(self, dataframe, metadata, **kwargs):
"""
*Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined
`include_timeframes`, `include_shifted_candles`, and `include_corr_pairs`.
In other words, a single feature defined in this function
will automatically expand to a total of
`include_timeframes` * `include_shifted_candles` * `include_corr_pairs`
numbers of features added to the model.
Features defined here will *not* be automatically duplicated on user defined
`indicator_periods_candles`
Access metadata such as the current pair/timeframe with:
`metadata["pair"]` `metadata["tf"]`
All features must be prepended with `%` to be recognized by FreqAI internals.
:param df: strategy dataframe which will receive the features
:param metadata: metadata of current pair
dataframe["%-pct-change"] = dataframe["close"].pct_change()
dataframe["%-ema-200"] = ta.EMA(dataframe, timeperiod=200)
"""
dataframe["%-pct-change"] = dataframe["close"].pct_change()
dataframe["%-raw_volume"] = dataframe["volume"]
dataframe["%-raw_price"] = dataframe["close"]
return dataframe
def feature_engineering_standard(self, dataframe, metadata, **kwargs):
"""
*Only functional with FreqAI enabled strategies*
This optional function will be called once with the dataframe of the base timeframe.
This is the final function to be called, which means that the dataframe entering this
function will contain all the features and columns created by all other
freqai_feature_engineering_* functions.
This function is a good place to do custom exotic feature extractions (e.g. tsfresh).
This function is a good place for any feature that should not be auto-expanded upon
(e.g. day of the week).
Access metadata such as the current pair with:
`metadata["pair"]`
All features must be prepended with `%` to be recognized by FreqAI internals.
:param df: strategy dataframe which will receive the features
:param metadata: metadata of current pair
usage example: dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7
"""
dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7
dataframe["%-hour_of_day"] = (dataframe["date"].dt.hour + 1) / 25
return dataframe
def set_freqai_targets(self, dataframe, metadata, **kwargs):
"""
*Only functional with FreqAI enabled strategies*
Required function to set the targets for the model.
All targets must be prepended with `&` to be recognized by the FreqAI internals.
Access metadata such as the current pair with:
`metadata["pair"]`
:param df: strategy dataframe which will receive the targets
:param metadata: metadata of current pair
usage example: dataframe["&-target"] = dataframe["close"].shift(-1) / dataframe["close"]
"""
dataframe["&-s_close"] = (
dataframe["close"]
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
.mean()
/ dataframe["close"]
- 1
)
informative[f"{pair}bb_lowerband-period_{t}"] = bollinger["lower"]
informative[f"{pair}bb_middleband-period_{t}"] = bollinger["mid"]
informative[f"{pair}bb_upperband-period_{t}"] = bollinger["upper"]
informative[f"%-{pair}bb_width-period_{t}"] = (
informative[f"{pair}bb_upperband-period_{t}"]
- informative[f"{pair}bb_lowerband-period_{t}"]
) / informative[f"{pair}bb_middleband-period_{t}"]
informative[f"%-{pair}close-bb_lower-period_{t}"] = (
informative["close"] / informative[f"{pair}bb_lowerband-period_{t}"]
)
informative[f"%-{pair}relative_volume-period_{t}"] = (
informative["volume"] / informative["volume"].rolling(t).mean()
)
indicators = [col for col in informative if col.startswith("%")]
# This loop duplicates and shifts all indicators to add a sense of recency to data
for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1):
if n == 0:
continue
informative_shift = informative[indicators].shift(n)
informative_shift = informative_shift.add_suffix("_shift-" + str(n))
informative = pd.concat((informative, informative_shift), axis=1)
df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True)
skip_columns = [
(s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"]
]
df = df.drop(columns=skip_columns)
# Add generalized indicators here (because in live, it will call this
# function to populate indicators during training). Notice how we ensure not to
# add them multiple times
if set_generalized_indicators:
df["%-day_of_week"] = (df["date"].dt.dayofweek + 1) / 7
df["%-hour_of_day"] = (df["date"].dt.hour + 1) / 25
# user adds targets here by prepending them with &- (see convention below)
# If user wishes to use multiple targets, a multioutput prediction model
# needs to be used such as templates/CatboostPredictionMultiModel.py
df["&-s_close"] = (
df["close"]
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
.mean()
/ df["close"]
- 1
)
return df
return dataframe
```
In the presented example, the user does not wish to pass the `bb_lowerband` as a feature to the model,
@@ -118,15 +172,28 @@ After having defined the `base features`, the next step is to expand upon them u
}
```
The `include_timeframes` in the config above are the timeframes (`tf`) of each call to `populate_any_indicators()` in the strategy. In the presented case, the user is asking for the `5m`, `15m`, and `4h` timeframes of the `rsi`, `mfi`, `roc`, and `bb_width` to be included in the feature set.
The `include_timeframes` in the config above are the timeframes (`tf`) of each call to `feature_engineering_expand_*()` in the strategy. In the presented case, the user is asking for the `5m`, `15m`, and `4h` timeframes of the `rsi`, `mfi`, `roc`, and `bb_width` to be included in the feature set.
You can ask for each of the defined features to be included also for informative pairs using the `include_corr_pairlist`. This means that the feature set will include all the features from `populate_any_indicators` on all the `include_timeframes` for each of the correlated pairs defined in the config (`ETH/USD`, `LINK/USD`, and `BNB/USD` in the presented example).
You can ask for each of the defined features to be included also for informative pairs using the `include_corr_pairlist`. This means that the feature set will include all the features from `feature_engineering_expand_*()` on all the `include_timeframes` for each of the correlated pairs defined in the config (`ETH/USD`, `LINK/USD`, and `BNB/USD` in the presented example).
`include_shifted_candles` indicates the number of previous candles to include in the feature set. For example, `include_shifted_candles: 2` tells FreqAI to include the past 2 candles for each of the features in the feature set.
In total, the number of features the user of the presented example strat has created is: length of `include_timeframes` * no. features in `populate_any_indicators()` * length of `include_corr_pairlist` * no. `include_shifted_candles` * length of `indicator_periods_candles`
In total, the number of features the user of the presented example strat has created is: length of `include_timeframes` * no. features in `feature_engineering_expand_*()` * length of `include_corr_pairlist` * no. `include_shifted_candles` * length of `indicator_periods_candles`
$= 3 * 3 * 3 * 2 * 2 = 108$.
### Gain finer control over `feature_engineering_*` functions with `metadata`
All `feature_engineering_*` and `set_freqai_targets()` functions are passed a `metadata` dictionary which contains information about the `pair`, `tf` (timeframe), and `period` that FreqAI is automating for feature building. As such, a user can use `metadata` inside `feature_engineering_*` functions as criteria for blocking/reserving features for certain timeframes, periods, pairs etc.
```py
def feature_engineering_expand_all(self, dataframe, period, metadata, **kwargs):
if metadata["tf"] == "1h":
dataframe["%-roc-period"] = ta.ROC(dataframe, timeperiod=period)
```
This will block `ta.ROC()` from being added to any timeframes other than `"1h"`.
### Returning additional info from training
Important metrics can be returned to the strategy at the end of each model training by assigning them to `dk.data['extra_returns_per_train']['my_new_value'] = XYZ` inside the custom prediction model class.
@@ -167,7 +234,7 @@ This will perform PCA on the features and reduce their dimensionality so that th
## Inlier metric
The `inlier_metric` is a metric aimed at quantifying how similar a the features of a data point are to the most recent historic data points.
The `inlier_metric` is a metric aimed at quantifying how similar the features of a data point are to the most recent historical data points.
You define the lookback window by setting `inlier_metric_window` and FreqAI computes the distance between the present time point and each of the previous `inlier_metric_window` lookback points. A Weibull function is fit to each of the lookback distributions and its cumulative distribution function (CDF) is used to produce a quantile for each lookback point. The `inlier_metric` is then computed for each time point as the average of the corresponding lookback quantiles. The figure below explains the concept for an `inlier_metric_window` of 5.

View File

@@ -4,32 +4,39 @@ The table below will list all configuration parameters available for FreqAI. Som
Mandatory parameters are marked as **Required** and have to be set in one of the suggested ways.
### General configuration parameters
| Parameter | Description |
|------------|-------------|
| | **General configuration parameters**
| | **General configuration parameters within the `config.freqai` tree**
| `freqai` | **Required.** <br> The parent dictionary containing all the parameters for controlling FreqAI. <br> **Datatype:** Dictionary.
| `train_period_days` | **Required.** <br> Number of days to use for the training data (width of the sliding window). <br> **Datatype:** Positive integer.
| `backtest_period_days` | **Required.** <br> Number of days to inference from the trained model before sliding the `train_period_days` window defined above, and retraining the model during backtesting (more info [here](freqai-running.md#backtesting)). This can be fractional days, but beware that the provided `timerange` will be divided by this number to yield the number of trainings necessary to complete the backtest. <br> **Datatype:** Float.
| `identifier` | **Required.** <br> A unique ID for the current model. If models are saved to disk, the `identifier` allows for reloading specific pre-trained models/data. <br> **Datatype:** String.
| `live_retrain_hours` | Frequency of retraining during dry/live runs. <br> **Datatype:** Float > 0. <br> Default: `0` (models retrain as often as possible).
| `expiration_hours` | Avoid making predictions if a model is more than `expiration_hours` old. <br> **Datatype:** Positive integer. <br> Default: `0` (models never expire).
| `purge_old_models` | Delete obsolete models. <br> **Datatype:** Boolean. <br> Default: `False` (all historic models remain on disk).
| `purge_old_models` | Number of models to keep on disk (not relevant to backtesting). Default is 2, which means that dry/live runs will keep the latest 2 models on disk. Setting to 0 keeps all models. This parameter also accepts a boolean to maintain backwards compatibility. <br> **Datatype:** Integer. <br> Default: `2`.
| `save_backtest_models` | Save models to disk when running backtesting. Backtesting operates most efficiently by saving the prediction data and reusing them directly for subsequent runs (when you wish to tune entry/exit parameters). Saving backtesting models to disk also allows to use the same model files for starting a dry/live instance with the same model `identifier`. <br> **Datatype:** Boolean. <br> Default: `False` (no models are saved).
| `fit_live_predictions_candles` | Number of historical candles to use for computing target (label) statistics from prediction data, instead of from the training dataset (more information can be found [here](freqai-configuration.md#creating-a-dynamic-target-threshold)). <br> **Datatype:** Positive integer.
| `follow_mode` | Use a `follower` that will look for models associated with a specific `identifier` and load those for inferencing. A `follower` will **not** train new models. <br> **Datatype:** Boolean. <br> Default: `False`.
| `continual_learning` | Use the final state of the most recently trained model as starting point for the new model, allowing for incremental learning (more information can be found [here](freqai-running.md#continual-learning)). <br> **Datatype:** Boolean. <br> Default: `False`.
| `write_metrics_to_disk` | Collect train timings, inference timings and cpu usage in json file. <br> **Datatype:** Boolean. <br> Default: `False`
| | **Feature parameters**
| `data_kitchen_thread_count` | <br> Designate the number of threads you want to use for data processing (outlier methods, normalization, etc.). This has no impact on the number of threads used for training. If user does not set it (default), FreqAI will use max number of threads - 2 (leaving 1 physical core available for Freqtrade bot and FreqUI) <br> **Datatype:** Positive integer.
### Feature parameters
| Parameter | Description |
|------------|-------------|
| | **Feature parameters within the `freqai.feature_parameters` sub dictionary**
| `feature_parameters` | A dictionary containing the parameters used to engineer the feature set. Details and examples are shown [here](freqai-feature-engineering.md). <br> **Datatype:** Dictionary.
| `include_timeframes` | A list of timeframes that all indicators in `populate_any_indicators` will be created for. The list is added as features to the base indicators dataset. <br> **Datatype:** List of timeframes (strings).
| `include_corr_pairlist` | A list of correlated coins that FreqAI will add as additional features to all `pair_whitelist` coins. All indicators set in `populate_any_indicators` during feature engineering (see details [here](freqai-feature-engineering.md)) will be created for each correlated coin. The correlated coins features are added to the base indicators dataset. <br> **Datatype:** List of assets (strings).
| `label_period_candles` | Number of candles into the future that the labels are created for. This is used in `populate_any_indicators` (see `templates/FreqaiExampleStrategy.py` for detailed usage). You can create custom labels and choose whether to make use of this parameter or not. <br> **Datatype:** Positive integer.
| `include_timeframes` | A list of timeframes that all indicators in `feature_engineering_expand_*()` will be created for. The list is added as features to the base indicators dataset. <br> **Datatype:** List of timeframes (strings).
| `include_corr_pairlist` | A list of correlated coins that FreqAI will add as additional features to all `pair_whitelist` coins. All indicators set in `feature_engineering_expand_*()` during feature engineering (see details [here](freqai-feature-engineering.md)) will be created for each correlated coin. The correlated coins features are added to the base indicators dataset. <br> **Datatype:** List of assets (strings).
| `label_period_candles` | Number of candles into the future that the labels are created for. This is used in `feature_engineering_expand_all()` (see `templates/FreqaiExampleStrategy.py` for detailed usage). You can create custom labels and choose whether to make use of this parameter or not. <br> **Datatype:** Positive integer.
| `include_shifted_candles` | Add features from previous candles to subsequent candles with the intent of adding historical information. If used, FreqAI will duplicate and shift all features from the `include_shifted_candles` previous candles so that the information is available for the subsequent candle. <br> **Datatype:** Positive integer.
| `weight_factor` | Weight training data points according to their recency (see details [here](freqai-feature-engineering.md#weighting-features-for-temporal-importance)). <br> **Datatype:** Positive float (typically < 1).
| `indicator_max_period_candles` | **No longer used (#7325)**. Replaced by `startup_candle_count` which is set in the [strategy](freqai-configuration.md#building-a-freqai-strategy). `startup_candle_count` is timeframe independent and defines the maximum *period* used in `populate_any_indicators()` for indicator creation. FreqAI uses this parameter together with the maximum timeframe in `include_time_frames` to calculate how many data points to download such that the first data point does not include a NaN. <br> **Datatype:** Positive integer.
| `indicator_max_period_candles` | **No longer used (#7325)**. Replaced by `startup_candle_count` which is set in the [strategy](freqai-configuration.md#building-a-freqai-strategy). `startup_candle_count` is timeframe independent and defines the maximum *period* used in `feature_engineering_*()` for indicator creation. FreqAI uses this parameter together with the maximum timeframe in `include_time_frames` to calculate how many data points to download such that the first data point does not include a NaN. <br> **Datatype:** Positive integer.
| `indicator_periods_candles` | Time periods to calculate indicators for. The indicators are added to the base indicator dataset. <br> **Datatype:** List of positive integers.
| `principal_component_analysis` | Automatically reduce the dimensionality of the data set using Principal Component Analysis. See details about how it works [here](#reducing-data-dimensionality-with-principal-component-analysis) <br> **Datatype:** Boolean. <br> Default: `False`.
| `plot_feature_importances` | Create a feature importance plot for each model for the top/bottom `plot_feature_importances` number of features. <br> **Datatype:** Integer. <br> Default: `0`.
| `plot_feature_importances` | Create a feature importance plot for each model for the top/bottom `plot_feature_importances` number of features. Plot is stored in `user_data/models/<identifier>/sub-train-<COIN>_<timestamp>.html`. <br> **Datatype:** Integer. <br> Default: `0`.
| `DI_threshold` | Activates the use of the Dissimilarity Index for outlier detection when set to > 0. See details about how it works [here](freqai-feature-engineering.md#identifying-outliers-with-the-dissimilarity-index-di). <br> **Datatype:** Positive float (typically < 1).
| `use_SVM_to_remove_outliers` | Train a support vector machine to detect and remove outliers from the training dataset, as well as from incoming data points. See details about how it works [here](freqai-feature-engineering.md#identifying-outliers-using-a-support-vector-machine-svm). <br> **Datatype:** Boolean.
| `svm_params` | All parameters available in Sklearn's `SGDOneClassSVM()`. See details about some select parameters [here](freqai-feature-engineering.md#identifying-outliers-using-a-support-vector-machine-svm). <br> **Datatype:** Dictionary.
@@ -38,16 +45,51 @@ Mandatory parameters are marked as **Required** and have to be set in one of the
| `noise_standard_deviation` | If set, FreqAI adds noise to the training features with the aim of preventing overfitting. FreqAI generates random deviates from a gaussian distribution with a standard deviation of `noise_standard_deviation` and adds them to all data points. `noise_standard_deviation` should be kept relative to the normalized space, i.e., between -1 and 1. In other words, since data in FreqAI is always normalized to be between -1 and 1, `noise_standard_deviation: 0.05` would result in 32% of the data being randomly increased/decreased by more than 2.5% (i.e., the percent of data falling within the first standard deviation). <br> **Datatype:** Integer. <br> Default: `0`.
| `outlier_protection_percentage` | Enable to prevent outlier detection methods from discarding too much data. If more than `outlier_protection_percentage` % of points are detected as outliers by the SVM or DBSCAN, FreqAI will log a warning message and ignore outlier detection, i.e., the original dataset will be kept intact. If the outlier protection is triggered, no predictions will be made based on the training dataset. <br> **Datatype:** Float. <br> Default: `30`.
| `reverse_train_test_order` | Split the feature dataset (see below) and use the latest data split for training and test on historical split of the data. This allows the model to be trained up to the most recent data point, while avoiding overfitting. However, you should be careful to understand the unorthodox nature of this parameter before employing it. <br> **Datatype:** Boolean. <br> Default: `False` (no reversal).
| | **Data split parameters**
| `data_split_parameters` | Include any additional parameters available from Scikit-learn `test_train_split()`, which are shown [here](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html) (external website). <br> **Datatype:** Dictionary.
| `shuffle_after_split` | Split the data into train and test sets, and then shuffle both sets individually. <br> **Datatype:** Boolean. <br> Default: `False`.
| `buffer_train_data_candles` | Cut `buffer_train_data_candles` off the beginning and end of the training data *after* the indicators were populated. The main example use is when predicting maxima and minima, the argrelextrema function cannot know the maxima/minima at the edges of the timerange. To improve model accuracy, it is best to compute argrelextrema on the full timerange and then use this function to cut off the edges (buffer) by the kernel. In another case, if the targets are set to a shifted price movement, this buffer is unnecessary because the shifted candles at the end of the timerange will be NaN and FreqAI will automatically cut those off of the training dataset.<br> **Datatype:** Boolean. <br> Default: `False`.
### Data split parameters
| Parameter | Description |
|------------|-------------|
| | **Data split parameters within the `freqai.data_split_parameters` sub dictionary**
| `data_split_parameters` | Include any additional parameters available from scikit-learn `test_train_split()`, which are shown [here](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html) (external website). <br> **Datatype:** Dictionary.
| `test_size` | The fraction of data that should be used for testing instead of training. <br> **Datatype:** Positive float < 1.
| `shuffle` | Shuffle the training data points during training. Typically, to not remove the chronological order of data in time-series forecasting, this is set to `False`. <br> **Datatype:** Boolean. <br> Defaut: `False`.
| | **Model training parameters**
### Model training parameters
| Parameter | Description |
|------------|-------------|
| | **Model training parameters within the `freqai.model_training_parameters` sub dictionary**
| `model_training_parameters` | A flexible dictionary that includes all parameters available by the selected model library. For example, if you use `LightGBMRegressor`, this dictionary can contain any parameter available by the `LightGBMRegressor` [here](https://lightgbm.readthedocs.io/en/latest/pythonapi/lightgbm.LGBMRegressor.html) (external website). If you select a different model, this dictionary can contain any parameter from that model. A list of the currently available models can be found [here](freqai-configuration.md#using-different-prediction-models). <br> **Datatype:** Dictionary.
| `n_estimators` | The number of boosted trees to fit in the training of the model. <br> **Datatype:** Integer.
| `learning_rate` | Boosting learning rate during training of the model. <br> **Datatype:** Float.
| `n_jobs`, `thread_count`, `task_type` | Set the number of threads for parallel processing and the `task_type` (`gpu` or `cpu`). Different model libraries use different parameter names. <br> **Datatype:** Float.
### Reinforcement Learning parameters
| Parameter | Description |
|------------|-------------|
| | **Reinforcement Learning Parameters within the `freqai.rl_config` sub dictionary**
| `rl_config` | A dictionary containing the control parameters for a Reinforcement Learning model. <br> **Datatype:** Dictionary.
| `train_cycles` | Training time steps will be set based on the `train_cycles * number of training data points. <br> **Datatype:** Integer.
| `cpu_count` | Number of processors to dedicate to the Reinforcement Learning training process. <br> **Datatype:** int.
| `max_trade_duration_candles`| Guides the agent training to keep trades below desired length. Example usage shown in `prediction_models/ReinforcementLearner.py` within the customizable `calculate_reward()` function. <br> **Datatype:** int.
| `model_type` | Model string from stable_baselines3 or SBcontrib. Available strings include: `'TRPO', 'ARS', 'RecurrentPPO', 'MaskablePPO', 'PPO', 'A2C', 'DQN'`. User should ensure that `model_training_parameters` match those available to the corresponding stable_baselines3 model by visiting their documentaiton. [PPO doc](https://stable-baselines3.readthedocs.io/en/master/modules/ppo.html) (external website) <br> **Datatype:** string.
| `policy_type` | One of the available policy types from stable_baselines3 <br> **Datatype:** string.
| `max_training_drawdown_pct` | The maximum drawdown that the agent is allowed to experience during training. <br> **Datatype:** float. <br> Default: 0.8
| `cpu_count` | Number of threads/cpus to dedicate to the Reinforcement Learning training process (depending on if `ReinforcementLearning_multiproc` is selected or not). Recommended to leave this untouched, by default, this value is set to the total number of physical cores minus 1. <br> **Datatype:** int.
| `model_reward_parameters` | Parameters used inside the customizable `calculate_reward()` function in `ReinforcementLearner.py` <br> **Datatype:** int.
| `add_state_info` | Tell FreqAI to include state information in the feature set for training and inferencing. The current state variables include trade duration, current profit, trade position. This is only available in dry/live runs, and is automatically switched to false for backtesting. <br> **Datatype:** bool. <br> Default: `False`.
| `net_arch` | Network architecture which is well described in [`stable_baselines3` doc](https://stable-baselines3.readthedocs.io/en/master/guide/custom_policy.html#examples). In summary: `[<shared layers>, dict(vf=[<non-shared value network layers>], pi=[<non-shared policy network layers>])]`. By default this is set to `[128, 128]`, which defines 2 shared hidden layers with 128 units each.
| `randomize_starting_position` | Randomize the starting point of each episode to avoid overfitting. <br> **Datatype:** bool. <br> Default: `False`.
### Additional parameters
| Parameter | Description |
|------------|-------------|
| | **Extraneous parameters**
| `keras` | If the selected model makes use of Keras (typical for Tensorflow-based prediction models), this flag needs to be activated so that the model save/loading follows Keras standards. <br> **Datatype:** Boolean. <br> Default: `False`.
| `conv_width` | The width of a convolutional neural network input tensor. This replaces the need for shifting candles (`include_shifted_candles`) by feeding in historical data points as the second dimension of the tensor. Technically, this parameter can also be used for regressors, but it only adds computational overhead and does not change the model training/prediction. <br> **Datatype:** Integer. <br> Default: `2`.
| `reduce_df_footprint` | Recast all numeric columns to float32/int32, with the objective of reducing ram/disk usage and decreasing train/inference timing. This parameter is set in the main level of the Freqtrade configuration file (not inside FreqAI). <br> **Datatype:** Boolean. <br> Default: `False`.
| `freqai.keras` | If the selected model makes use of Keras (typical for TensorFlow-based prediction models), this flag needs to be activated so that the model save/loading follows Keras standards. <br> **Datatype:** Boolean. <br> Default: `False`.
| `freqai.conv_width` | The width of a convolutional neural network input tensor. This replaces the need for shifting candles (`include_shifted_candles`) by feeding in historical data points as the second dimension of the tensor. Technically, this parameter can also be used for regressors, but it only adds computational overhead and does not change the model training/prediction. <br> **Datatype:** Integer. <br> Default: `2`.
| `freqai.reduce_df_footprint` | Recast all numeric columns to float32/int32, with the objective of reducing ram/disk usage and decreasing train/inference timing. This parameter is set in the main level of the Freqtrade configuration file (not inside FreqAI). <br> **Datatype:** Boolean. <br> Default: `False`.

View File

@@ -0,0 +1,267 @@
# Reinforcement Learning
!!! Note "Installation size"
Reinforcement learning dependencies include large packages such as `torch`, which should be explicitly requested during `./setup.sh -i` by answering "y" to the question "Do you also want dependencies for freqai-rl (~700mb additional space required) [y/N]?".
Users who prefer docker should ensure they use the docker image appended with `_freqairl`.
## Background and terminology
### What is RL and why does FreqAI need it?
Reinforcement learning involves two important components, the *agent* and the training *environment*. During agent training, the agent moves through historical data candle by candle, always making 1 of a set of actions: Long entry, long exit, short entry, short exit, neutral). During this training process, the environment tracks the performance of these actions and rewards the agent according to a custom user made `calculate_reward()` (here we offer a default reward for users to build on if they wish [details here](#creating-a-custom-reward-function)). The reward is used to train weights in a neural network.
A second important component of the FreqAI RL implementation is the use of *state* information. State information is fed into the network at each step, including current profit, current position, and current trade duration. These are used to train the agent in the training environment, and to reinforce the agent in dry/live (this functionality is not available in backtesting). *FreqAI + Freqtrade is a perfect match for this reinforcing mechanism since this information is readily available in live deployments.*
Reinforcement learning is a natural progression for FreqAI, since it adds a new layer of adaptivity and market reactivity that Classifiers and Regressors cannot match. However, Classifiers and Regressors have strengths that RL does not have such as robust predictions. Improperly trained RL agents may find "cheats" and "tricks" to maximize reward without actually winning any trades. For this reason, RL is more complex and demands a higher level of understanding than typical Classifiers and Regressors.
### The RL interface
With the current framework, we aim to expose the training environment via the common "prediction model" file, which is a user inherited `BaseReinforcementLearner` object (e.g. `freqai/prediction_models/ReinforcementLearner`). Inside this user class, the RL environment is available and customized via `MyRLEnv` as [shown below](#creating-a-custom-reward-function).
We envision the majority of users focusing their effort on creative design of the `calculate_reward()` function [details here](#creating-a-custom-reward-function), while leaving the rest of the environment untouched. Other users may not touch the environment at all, and they will only play with the configuration settings and the powerful feature engineering that already exists in FreqAI. Meanwhile, we enable advanced users to create their own model classes entirely.
The framework is built on stable_baselines3 (torch) and OpenAI gym for the base environment class. But generally speaking, the model class is well isolated. Thus, the addition of competing libraries can be easily integrated into the existing framework. For the environment, it is inheriting from `gym.env` which means that it is necessary to write an entirely new environment in order to switch to a different library.
### Important considerations
As explained above, the agent is "trained" in an artificial trading "environment". In our case, that environment may seem quite similar to a real Freqtrade backtesting environment, but it is *NOT*. In fact, the RL training environment is much more simplified. It does not incorporate any of the complicated strategy logic, such as callbacks like `custom_exit`, `custom_stoploss`, leverage controls, etc. The RL environment is instead a very "raw" representation of the true market, where the agent has free will to learn the policy (read: stoploss, take profit, etc.) which is enforced by the `calculate_reward()`. Thus, it is important to consider that the agent training environment is not identical to the real world.
## Running Reinforcement Learning
Setting up and running a Reinforcement Learning model is the same as running a Regressor or Classifier. The same two flags, `--freqaimodel` and `--strategy`, must be defined on the command line:
```bash
freqtrade trade --freqaimodel ReinforcementLearner --strategy MyRLStrategy --config config.json
```
where `ReinforcementLearner` will use the templated `ReinforcementLearner` from `freqai/prediction_models/ReinforcementLearner` (or a custom user defined one located in `user_data/freqaimodels`). The strategy, on the other hand, follows the same base [feature engineering](freqai-feature-engineering.md) with `feature_engineering_*` as a typical Regressor. The difference lies in the creation of the targets, Reinforcement Learning doesn't require them. However, FreqAI requires a default (neutral) value to be set in the action column:
```python
def set_freqai_targets(self, dataframe, **kwargs):
"""
*Only functional with FreqAI enabled strategies*
Required function to set the targets for the model.
All targets must be prepended with `&` to be recognized by the FreqAI internals.
More details about feature engineering available:
https://www.freqtrade.io/en/latest/freqai-feature-engineering
:param df: strategy dataframe which will receive the targets
usage example: dataframe["&-target"] = dataframe["close"].shift(-1) / dataframe["close"]
"""
# For RL, there are no direct targets to set. This is filler (neutral)
# until the agent sends an action.
dataframe["&-action"] = 0
```
Most of the function remains the same as for typical Regressors, however, the function above shows how the strategy must pass the raw price data to the agent so that it has access to raw OHLCV in the training environment:
```python
def feature_engineering_standard(self, dataframe, **kwargs):
# The following features are necessary for RL models
dataframe[f"%-raw_close"] = dataframe["close"]
dataframe[f"%-raw_open"] = dataframe["open"]
dataframe[f"%-raw_high"] = dataframe["high"]
dataframe[f"%-raw_low"] = dataframe["low"]
```
Finally, there is no explicit "label" to make - instead it is necessary to assign the `&-action` column which will contain the agent's actions when accessed in `populate_entry/exit_trends()`. In the present example, the neutral action to 0. This value should align with the environment used. FreqAI provides two environments, both use 0 as the neutral action.
After users realize there are no labels to set, they will soon understand that the agent is making its "own" entry and exit decisions. This makes strategy construction rather simple. The entry and exit signals come from the agent in the form of an integer - which are used directly to decide entries and exits in the strategy:
```python
def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
enter_long_conditions = [df["do_predict"] == 1, df["&-action"] == 1]
if enter_long_conditions:
df.loc[
reduce(lambda x, y: x & y, enter_long_conditions), ["enter_long", "enter_tag"]
] = (1, "long")
enter_short_conditions = [df["do_predict"] == 1, df["&-action"] == 3]
if enter_short_conditions:
df.loc[
reduce(lambda x, y: x & y, enter_short_conditions), ["enter_short", "enter_tag"]
] = (1, "short")
return df
def populate_exit_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
exit_long_conditions = [df["do_predict"] == 1, df["&-action"] == 2]
if exit_long_conditions:
df.loc[reduce(lambda x, y: x & y, exit_long_conditions), "exit_long"] = 1
exit_short_conditions = [df["do_predict"] == 1, df["&-action"] == 4]
if exit_short_conditions:
df.loc[reduce(lambda x, y: x & y, exit_short_conditions), "exit_short"] = 1
return df
```
It is important to consider that `&-action` depends on which environment they choose to use. The example above shows 5 actions, where 0 is neutral, 1 is enter long, 2 is exit long, 3 is enter short and 4 is exit short.
## Configuring the Reinforcement Learner
In order to configure the `Reinforcement Learner` the following dictionary must exist in the `freqai` config:
```json
"rl_config": {
"train_cycles": 25,
"add_state_info": true,
"max_trade_duration_candles": 300,
"max_training_drawdown_pct": 0.02,
"cpu_count": 8,
"model_type": "PPO",
"policy_type": "MlpPolicy",
"model_reward_parameters": {
"rr": 1,
"profit_aim": 0.025
}
}
```
Parameter details can be found [here](freqai-parameter-table.md), but in general the `train_cycles` decides how many times the agent should cycle through the candle data in its artificial environment to train weights in the model. `model_type` is a string which selects one of the available models in [stable_baselines](https://stable-baselines3.readthedocs.io/en/master/)(external link).
!!! Note
If you would like to experiment with `continual_learning`, then you should set that value to `true` in the main `freqai` configuration dictionary. This will tell the Reinforcement Learning library to continue training new models from the final state of previous models, instead of retraining new models from scratch each time a retrain is initiated.
!!! Note
Remember that the general `model_training_parameters` dictionary should contain all the model hyperparameter customizations for the particular `model_type`. For example, `PPO` parameters can be found [here](https://stable-baselines3.readthedocs.io/en/master/modules/ppo.html).
## Creating a custom reward function
As you begin to modify the strategy and the prediction model, you will quickly realize some important differences between the Reinforcement Learner and the Regressors/Classifiers. Firstly, the strategy does not set a target value (no labels!). Instead, you set the `calculate_reward()` function inside the `MyRLEnv` class (see below). A default `calculate_reward()` is provided inside `prediction_models/ReinforcementLearner.py` to demonstrate the necessary building blocks for creating rewards, but users are encouraged to create their own custom reinforcement learning model class (see below) and save it to `user_data/freqaimodels`. It is inside the `calculate_reward()` where creative theories about the market can be expressed. For example, you can reward your agent when it makes a winning trade, and penalize the agent when it makes a losing trade. Or perhaps, you wish to reward the agent for entering trades, and penalize the agent for sitting in trades too long. Below we show examples of how these rewards are all calculated:
```python
from freqtrade.freqai.prediction_models.ReinforcementLearner import ReinforcementLearner
from freqtrade.freqai.RL.Base5ActionRLEnv import Actions, Base5ActionRLEnv, Positions
class MyCoolRLModel(ReinforcementLearner):
"""
User created RL prediction model.
Save this file to `freqtrade/user_data/freqaimodels`
then use it with:
freqtrade trade --freqaimodel MyCoolRLModel --config config.json --strategy SomeCoolStrat
Here the users can override any of the functions
available in the `IFreqaiModel` inheritance tree. Most importantly for RL, this
is where the user overrides `MyRLEnv` (see below), to define custom
`calculate_reward()` function, or to override any other parts of the environment.
This class also allows users to override any other part of the IFreqaiModel tree.
For example, the user can override `def fit()` or `def train()` or `def predict()`
to take fine-tuned control over these processes.
Another common override may be `def data_cleaning_predict()` where the user can
take fine-tuned control over the data handling pipeline.
"""
class MyRLEnv(Base5ActionRLEnv):
"""
User made custom environment. This class inherits from BaseEnvironment and gym.env.
Users can override any functions from those parent classes. Here is an example
of a user customized `calculate_reward()` function.
"""
def calculate_reward(self, action: int) -> float:
# first, penalize if the action is not valid
if not self._is_valid(action):
return -2
pnl = self.get_unrealized_profit()
factor = 100
# you can use feature values from dataframe
# Assumes the shifted RSI indicator has been generated in the strategy.
rsi_now = self.raw_features[f"%-rsi-period-10_shift-1_{self.pair}_"
f"{self.config['timeframe']}"].iloc[self._current_tick]
# reward agent for entering trades
if (action in (Actions.Long_enter.value, Actions.Short_enter.value)
and self._position == Positions.Neutral):
if rsi_now < 40:
factor = 40 / rsi_now
else:
factor = 1
return 25 * factor
# discourage agent from not entering trades
if action == Actions.Neutral.value and self._position == Positions.Neutral:
return -1
max_trade_duration = self.rl_config.get('max_trade_duration_candles', 300)
trade_duration = self._current_tick - self._last_trade_tick
if trade_duration <= max_trade_duration:
factor *= 1.5
elif trade_duration > max_trade_duration:
factor *= 0.5
# discourage sitting in position
if self._position in (Positions.Short, Positions.Long) and \
action == Actions.Neutral.value:
return -1 * trade_duration / max_trade_duration
# close long
if action == Actions.Long_exit.value and self._position == Positions.Long:
if pnl > self.profit_aim * self.rr:
factor *= self.rl_config['model_reward_parameters'].get('win_reward_factor', 2)
return float(pnl * factor)
# close short
if action == Actions.Short_exit.value and self._position == Positions.Short:
if pnl > self.profit_aim * self.rr:
factor *= self.rl_config['model_reward_parameters'].get('win_reward_factor', 2)
return float(pnl * factor)
return 0.
```
### Using Tensorboard
Reinforcement Learning models benefit from tracking training metrics. FreqAI has integrated Tensorboard to allow users to track training and evaluation performance across all coins and across all retrainings. Tensorboard is activated via the following command:
```bash
cd freqtrade
tensorboard --logdir user_data/models/unique-id
```
where `unique-id` is the `identifier` set in the `freqai` configuration file. This command must be run in a separate shell to view the output in their browser at 127.0.0.1:6006 (6006 is the default port used by Tensorboard).
![tensorboard](assets/tensorboard.jpg)
### Custom logging
FreqAI also provides a built in episodic summary logger called `self.tensorboard_log` for adding custom information to the Tensorboard log. By default, this function is already called once per step inside the environment to record the agent actions. All values accumulated for all steps in a single episode are reported at the conclusion of each episode, followed by a full reset of all metrics to 0 in preparation for the subsequent episode.
`self.tensorboard_log` can also be used anywhere inside the environment, for example, it can be added to the `calculate_reward` function to collect more detailed information about how often various parts of the reward were called:
```py
class MyRLEnv(Base5ActionRLEnv):
"""
User made custom environment. This class inherits from BaseEnvironment and gym.env.
Users can override any functions from those parent classes. Here is an example
of a user customized `calculate_reward()` function.
"""
def calculate_reward(self, action: int) -> float:
if not self._is_valid(action):
self.tensorboard_log("is_valid")
return -2
```
!!! Note
The `self.tensorboard_log()` function is designed for tracking incremented objects only i.e. events, actions inside the training environment. If the event of interest is a float, the float can be passed as the second argument e.g. `self.tensorboard_log("float_metric1", 0.23)` would add 0.23 to `float_metric`. In this case you can also disable incrementing using `inc=False` parameter.
### Choosing a base environment
FreqAI provides three base environments, `Base3ActionRLEnvironment`, `Base4ActionEnvironment` and `Base5ActionEnvironment`. As the names imply, the environments are customized for agents that can select from 3, 4 or 5 actions. The `Base3ActionEnvironment` is the simplest, the agent can select from hold, long, or short. This environment can also be used for long-only bots (it automatically follows the `can_short` flag from the strategy), where long is the enter condition and short is the exit condition. Meanwhile, in the `Base4ActionEnvironment`, the agent can enter long, enter short, hold neutral, or exit position. Finally, in the `Base5ActionEnvironment`, the agent has the same actions as Base4, but instead of a single exit action, it separates exit long and exit short. The main changes stemming from the environment selection include:
* the actions available in the `calculate_reward`
* the actions consumed by the user strategy
All of the FreqAI provided environments inherit from an action/position agnostic environment object called the `BaseEnvironment`, which contains all shared logic. The architecture is designed to be easily customized. The simplest customization is the `calculate_reward()` (see details [here](#creating-a-custom-reward-function)). However, the customizations can be further extended into any of the functions inside the environment. You can do this by simply overriding those functions inside your `MyRLEnv` in the prediction model file. Or for more advanced customizations, it is encouraged to create an entirely new environment inherited from `BaseEnvironment`.
!!! Note
Only the `Base3ActionRLEnv` can do long-only training/trading (set the user strategy attribute `can_short = False`).

View File

@@ -67,6 +67,10 @@ Backtesting mode requires [downloading the necessary data](#downloading-data-to-
*want* to retrain a new model with the same config file, you should simply change the `identifier`.
This way, you can return to using any model you wish by simply specifying the `identifier`.
!!! Note
Backtesting calls `set_freqai_targets()` one time for each backtest window (where the number of windows is the full backtest timerange divided by the `backtest_period_days` parameter). Doing this means that the targets simulate dry/live behavior without look ahead bias. However, the definition of the features in `feature_engineering_*()` is performed once on the entire backtest timerange. This means that you should be sure that features do look-ahead into the future.
More details about look-ahead bias can be found in [Common Mistakes](strategy-customization.md#common-mistakes-when-developing-strategies).
---
### Saving prediction data
@@ -79,16 +83,11 @@ To change your **features**, you **must** set a new `identifier` in the config t
To save the models generated during a particular backtest so that you can start a live deployment from one of them instead of training a new model, you must set `save_backtest_models` to `True` in the config.
### Backtest live models
### Backtest live collected predictions
FreqAI allow you to reuse ready models through the backtest parameter `--freqai-backtest-live-models`. This can be useful when you want to reuse models generated in dry/run for comparison or other study. For that, you must set `"purge_old_models"` to `True` in the config.
FreqAI allow you to reuse live historic predictions through the backtest parameter `--freqai-backtest-live-models`. This can be useful when you want to reuse predictions generated in dry/run for comparison or other study.
The `--timerange` parameter must not be informed, as it will be automatically calculated through the training end dates of the models.
Each model has an identifier derived from the training end date. If you have only 1 model trained, FreqAI will backtest from the training end date until the current date. If you have more than 1 model, each model will perform the backtesting according to the training end date until the training end date of the next model and so on. For the last model, the period of the previous model will be used for the execution.
!!! Note
Currently, there is no checking for expired models, even if the `expired_hours` parameter is set.
The `--timerange` parameter must not be informed, as it will be automatically calculated through the data in the historic predictions file.
### Downloading data to cover the full backtest period
@@ -121,7 +120,7 @@ In the presented example config, the user will only allow predictions on models
Model training parameters are unique to the selected machine learning library. FreqAI allows you to set any parameter for any library using the `model_training_parameters` dictionary in the config. The example config (found in `config_examples/config_freqai.example.json`) shows some of the example parameters associated with `Catboost` and `LightGBM`, but you can add any parameters available in those libraries or any other machine learning library you choose to implement.
Data split parameters are defined in `data_split_parameters` which can be any parameters associated with Scikit-learn's `train_test_split()` function. `train_test_split()` has a parameters called `shuffle` which allows to shuffle the data or keep it unshuffled. This is particularly useful to avoid biasing training with temporally auto-correlated data. More details about these parameters can be found the [Scikit-learn website](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html) (external website).
Data split parameters are defined in `data_split_parameters` which can be any parameters associated with scikit-learn's `train_test_split()` function. `train_test_split()` has a parameters called `shuffle` which allows to shuffle the data or keep it unshuffled. This is particularly useful to avoid biasing training with temporally auto-correlated data. More details about these parameters can be found the [scikit-learn website](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html) (external website).
The FreqAI specific parameter `label_period_candles` defines the offset (number of candles into the future) used for the `labels`. In the presented [example config](freqai-configuration.md#setting-up-the-configuration-file), the user is asking for `labels` that are 24 candles in the future.
@@ -140,7 +139,7 @@ freqtrade hyperopt --hyperopt-loss SharpeHyperOptLoss --strategy FreqaiExampleSt
`hyperopt` requires you to have the data pre-downloaded in the same fashion as if you were doing [backtesting](#backtesting). In addition, you must consider some restrictions when trying to hyperopt FreqAI strategies:
- The `--analyze-per-epoch` hyperopt parameter is not compatible with FreqAI.
- It's not possible to hyperopt indicators in the `populate_any_indicators()` function. This means that you cannot optimize model parameters using hyperopt. Apart from this exception, it is possible to optimize all other [spaces](hyperopt.md#running-hyperopt-with-smaller-search-space).
- It's not possible to hyperopt indicators in the `feature_engineering_*()` and `set_freqai_targets()` functions. This means that you cannot optimize model parameters using hyperopt. Apart from this exception, it is possible to optimize all other [spaces](hyperopt.md#running-hyperopt-with-smaller-search-space).
- The backtesting instructions also apply to hyperopt.
The best method for combining hyperopt and FreqAI is to focus on hyperopting entry/exit thresholds/criteria. You need to focus on hyperopting parameters that are not used in your features. For example, you should not try to hyperopt rolling window lengths in the feature creation, or any part of the FreqAI config which changes predictions. In order to efficiently hyperopt the FreqAI strategy, FreqAI stores predictions as dataframes and reuses them. Hence the requirement to hyperopt entry/exit thresholds/criteria only.
@@ -166,20 +165,3 @@ tensorboard --logdir user_data/models/unique-id
where `unique-id` is the `identifier` set in the `freqai` configuration file. This command must be run in a separate shell if you wish to view the output in your browser at 127.0.0.1:6060 (6060 is the default port used by Tensorboard).
![tensorboard](assets/tensorboard.jpg)
## Setting up a follower
You can indicate to the bot that it should not train models, but instead should look for models trained by a leader with a specific `identifier` by defining:
```json
"freqai": {
"enabled": true,
"follow_mode": true,
"identifier": "example",
"feature_parameters": {
// leader bots feature_parameters inserted here
},
}
```
In this example, the user has a leader bot with the `"identifier": "example"`. The leader bot is already running or is launched simultaneously with the follower. The follower will load models created by the leader and inference them to obtain predictions instead of training its own models. The user will also need to duplicate the `feature_parameters` parameters from from the leaders freqai configuration file into the freqai section of the followers config.

View File

@@ -4,7 +4,10 @@
## Introduction
FreqAI is a software designed to automate a variety of tasks associated with training a predictive machine learning model to generate market forecasts given a set of input signals. In general, the FreqAI aims to be a sand-box for easily deploying robust machine-learning libraries on real-time data ([details])(#freqai-position-in-open-source-machine-learning-landscape).
FreqAI is a software designed to automate a variety of tasks associated with training a predictive machine learning model to generate market forecasts given a set of input signals. In general, FreqAI aims to be a sandbox for easily deploying robust machine learning libraries on real-time data ([details](#freqai-position-in-open-source-machine-learning-landscape)).
!!! Note
FreqAI is, and always will be, a not-for-profit, open-source project. FreqAI does *not* have a crypto token, FreqAI does *not* sell signals, and FreqAI does not have a domain besides the present [freqtrade documentation](https://www.freqtrade.io/en/latest/freqai/).
Features include:
@@ -19,7 +22,7 @@ Features include:
* **Automatic data download** - Compute timeranges for data downloads and update historic data (in live deployments)
* **Cleaning of incoming data** - Handle NaNs safely before training and model inferencing
* **Dimensionality reduction** - Reduce the size of the training data via [Principal Component Analysis](freqai-feature-engineering.md#data-dimensionality-reduction-with-principal-component-analysis)
* **Deploying bot fleets** - Set one bot to train models while a fleet of [follower bots](freqai-running.md#setting-up-a-follower) inference the models and handle trades
* **Deploying bot fleets** - Set one bot to train models while a fleet of [consumers](producer-consumer.md) use signals.
## Quick start
@@ -70,12 +73,26 @@ pip install -r requirements-freqai.txt
### Usage with docker
If you are using docker, a dedicated tag with FreqAI dependencies is available as `:freqai`. As such - you can replace the image line in your docker-compose file with `image: freqtradeorg/freqtrade:develop_freqai`. This image contains the regular FreqAI dependencies. Similar to native installs, Catboost will not be available on ARM based devices.
If you are using docker, a dedicated tag with FreqAI dependencies is available as `:freqai`. As such - you can replace the image line in your docker compose file with `image: freqtradeorg/freqtrade:develop_freqai`. This image contains the regular FreqAI dependencies. Similar to native installs, Catboost will not be available on ARM based devices.
### FreqAI position in open-source machine learning landscape
Forecasting chaotic time-series based systems, such as equity/cryptocurrency markets, requires a broad set of tools geared toward testing a wide range of hypotheses. Fortunately, a recent maturation of robust machine learning libraries (e.g. `scikit-learn`) has opened up a wide range of research possibilities. Scientists from a diverse range of fields can now easily prototype their studies on an abundance of established machine learning algorithms. Similarly, these user-friendly libraries enable "citzen scientists" to use their basic Python skills for data-exploration. However, leveraging these machine learning libraries on historical and live chaotic data sources can be logistically difficult and expensive. Additionally, robust data-collection, storage, and handling presents a disparate challenge. [`FreqAI`](#freqai) aims to provide a generalized and extensible open-sourced framework geared toward live deployments of adaptive modeling for market forecasting. The `FreqAI` framework is effectively a sandbox for the rich world of open-source machine learning libraries. Inside the `FreqAI` sandbox, users find they can combine a wide variety of third-party libraries to test creative hypotheses on a free live 24/7 chaotic data source - cryptocurrency exchange data.
Forecasting chaotic time-series based systems, such as equity/cryptocurrency markets, requires a broad set of tools geared toward testing a wide range of hypotheses. Fortunately, a recent maturation of robust machine learning libraries (e.g. `scikit-learn`) has opened up a wide range of research possibilities. Scientists from a diverse range of fields can now easily prototype their studies on an abundance of established machine learning algorithms. Similarly, these user-friendly libraries enable "citzen scientists" to use their basic Python skills for data exploration. However, leveraging these machine learning libraries on historical and live chaotic data sources can be logistically difficult and expensive. Additionally, robust data collection, storage, and handling presents a disparate challenge. [`FreqAI`](#freqai) aims to provide a generalized and extensible open-sourced framework geared toward live deployments of adaptive modeling for market forecasting. The `FreqAI` framework is effectively a sandbox for the rich world of open-source machine learning libraries. Inside the `FreqAI` sandbox, users find they can combine a wide variety of third-party libraries to test creative hypotheses on a free live 24/7 chaotic data source - cryptocurrency exchange data.
### Citing FreqAI
FreqAI is [published in the Journal of Open Source Software](https://joss.theoj.org/papers/10.21105/joss.04864). If you find FreqAI useful in your research, please use the following citation:
```bibtex
@article{Caulk2022,
doi = {10.21105/joss.04864},
url = {https://doi.org/10.21105/joss.04864},
year = {2022}, publisher = {The Open Journal},
volume = {7}, number = {80}, pages = {4864},
author = {Robert A. Caulk and Elin Törnquist and Matthias Voppichler and Andrew R. Lawless and Ryan McMullan and Wagner Costa Santos and Timothy C. Pogue and Johan van der Vlugt and Stefan P. Gehring and Pascal Schmidt},
title = {FreqAI: generalizing adaptive modeling for chaotic time-series market forecasts},
journal = {Journal of Open Source Software} }
```
## Common pitfalls
@@ -99,6 +116,8 @@ Code review and software architecture brainstorming:
Software development:
Wagner Costa @wagnercosta
Emre Suzen @aemr3
Timothy Pogue @wizrds
Beta testing and bug reporting:
Stefan Gehring @bloodhunter4rc, @longyu, Andrew Lawless @paranoidandy, Pascal Schmidt @smidelis, Ryan McMullan @smarmau, Juha Nykänen @suikula, Johan van der Vlugt @jooopiert, Richárd Józsa @richardjosza, Timothy Pogue @wizrds
Stefan Gehring @bloodhunter4rc, @longyu, Andrew Lawless @paranoidandy, Pascal Schmidt @smidelis, Ryan McMullan @smarmau, Juha Nykänen @suikula, Johan van der Vlugt @jooopiert, Richárd Józsa @richardjosza

View File

@@ -50,7 +50,7 @@ usage: freqtrade hyperopt [-h] [-v] [--logfile FILE] [-V] [-c PATH] [-d PATH]
[--eps] [--dmmp] [--enable-protections]
[--dry-run-wallet DRY_RUN_WALLET]
[--timeframe-detail TIMEFRAME_DETAIL] [-e INT]
[--spaces {all,buy,sell,roi,stoploss,trailing,protection,default} [{all,buy,sell,roi,stoploss,trailing,protection,default} ...]]
[--spaces {all,buy,sell,roi,stoploss,trailing,protection,trades,default} [{all,buy,sell,roi,stoploss,trailing,protection,trades,default} ...]]
[--print-all] [--no-color] [--print-json] [-j JOBS]
[--random-state INT] [--min-trades INT]
[--hyperopt-loss NAME] [--disable-param-export]
@@ -96,7 +96,7 @@ optional arguments:
Specify detail timeframe for backtesting (`1m`, `5m`,
`30m`, `1h`, `1d`).
-e INT, --epochs INT Specify number of epochs (default: 100).
--spaces {all,buy,sell,roi,stoploss,trailing,protection,default} [{all,buy,sell,roi,stoploss,trailing,protection,default} ...]
--spaces {all,buy,sell,roi,stoploss,trailing,protection,trades,default} [{all,buy,sell,roi,stoploss,trailing,protection,trades,default} ...]
Specify which parameters to hyperopt. Space-separated
list.
--print-all Print all results, not only the best ones.
@@ -180,6 +180,7 @@ Rarely you may also need to create a [nested class](advanced-hyperopt.md#overrid
* `generate_roi_table` - for custom ROI optimization (if you need the ranges for the values in the ROI table that differ from default or the number of entries (steps) in the ROI table which differs from the default 4 steps)
* `stoploss_space` - for custom stoploss optimization (if you need the range for the stoploss parameter in the optimization hyperspace that differs from default)
* `trailing_space` - for custom trailing stop optimization (if you need the ranges for the trailing stop parameters in the optimization hyperspace that differ from default)
* `max_open_trades_space` - for custom max_open_trades optimization (if you need the ranges for the max_open_trades parameter in the optimization hyperspace that differ from default)
!!! Tip "Quickly optimize ROI, stoploss and trailing stoploss"
You can quickly optimize the spaces `roi`, `stoploss` and `trailing` without changing anything in your strategy.
@@ -365,7 +366,7 @@ class MyAwesomeStrategy(IStrategy):
timeframe = '15m'
minimal_roi = {
"0": 0.10
},
}
# Define the parameter spaces
buy_ema_short = IntParameter(3, 50, default=5)
buy_ema_long = IntParameter(15, 200, default=50)
@@ -400,7 +401,7 @@ class MyAwesomeStrategy(IStrategy):
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = []
conditions = []
conditions.append(qtpylib.crossed_above(
dataframe[f'ema_long_{self.buy_ema_long.value}'], dataframe[f'ema_short_{self.buy_ema_short.value}']
))
@@ -643,6 +644,7 @@ Legal values are:
* `roi`: just optimize the minimal profit table for your strategy
* `stoploss`: search for the best stoploss value
* `trailing`: search for the best trailing stop values
* `trades`: search for the best max open trades values
* `protection`: search for the best protection parameters (read the [protections section](#optimizing-protections) on how to properly define these)
* `default`: `all` except `trailing` and `protection`
* space-separated list of any of the above values for example `--spaces roi stoploss`
@@ -916,5 +918,5 @@ Once the optimized strategy has been implemented into your strategy, you should
To achieve same the results (number of trades, their durations, profit, etc.) as during Hyperopt, please use the same configuration and parameters (timerange, timeframe, ...) used for hyperopt `--dmmp`/`--disable-max-market-positions` and `--eps`/`--enable-position-stacking` for Backtesting.
Should results not match, please double-check to make sure you transferred all conditions correctly.
Pay special care to the stoploss (and trailing stoploss) parameters, as these are often set in configuration files, which override changes to the strategy.
You should also carefully review the log of your backtest to ensure that there were no parameters inadvertently set by the configuration (like `stoploss` or `trailing_stop`).
Pay special care to the stoploss, max_open_trades and trailing stoploss parameters, as these are often set in configuration files, which override changes to the strategy.
You should also carefully review the log of your backtest to ensure that there were no parameters inadvertently set by the configuration (like `stoploss`, `max_open_trades` or `trailing_stop`).

View File

@@ -23,6 +23,7 @@ You may also use something like `.*DOWN/BTC` or `.*UP/BTC` to exclude leveraged
* [`StaticPairList`](#static-pair-list) (default, if not configured differently)
* [`VolumePairList`](#volume-pair-list)
* [`ProducerPairList`](#producerpairlist)
* [`RemotePairList`](#remotepairlist)
* [`AgeFilter`](#agefilter)
* [`OffsetFilter`](#offsetfilter)
* [`PerformanceFilter`](#performancefilter)
@@ -173,6 +174,48 @@ You can limit the length of the pairlist with the optional parameter `number_ass
`ProducerPairList` can also be used multiple times in sequence, combining the pairs from multiple producers.
Obviously in complex such configurations, the Producer may not provide data for all pairs, so the strategy must be fit for this.
#### RemotePairList
It allows the user to fetch a pairlist from a remote server or a locally stored json file within the freqtrade directory, enabling dynamic updates and customization of the trading pairlist.
The RemotePairList is defined in the pairlists section of the configuration settings. It uses the following configuration options:
```json
"pairlists": [
{
"method": "RemotePairList",
"pairlist_url": "https://example.com/pairlist",
"number_assets": 10,
"refresh_period": 1800,
"keep_pairlist_on_failure": true,
"read_timeout": 60,
"bearer_token": "my-bearer-token"
}
]
```
The `pairlist_url` option specifies the URL of the remote server where the pairlist is located, or the path to a local file (if file:/// is prepended). This allows the user to use either a remote server or a local file as the source for the pairlist.
The user is responsible for providing a server or local file that returns a JSON object with the following structure:
```json
{
"pairs": ["XRP/USDT", "ETH/USDT", "LTC/USDT"],
"refresh_period": 1800,
}
```
The `pairs` property should contain a list of strings with the trading pairs to be used by the bot. The `refresh_period` property is optional and specifies the number of seconds that the pairlist should be cached before being refreshed.
The optional `keep_pairlist_on_failure` specifies whether the previous received pairlist should be used if the remote server is not reachable or returns an error. The default value is true.
The optional `read_timeout` specifies the maximum amount of time (in seconds) to wait for a response from the remote source, The default value is 60.
The optional `bearer_token` will be included in the requests Authorization Header.
!!! Note
In case of a server error the last received pairlist will be kept if `keep_pairlist_on_failure` is set to true, when set to false a empty pairlist is returned.
#### AgeFilter
Removes pairs that have been listed on the exchange for less than `min_days_listed` days (defaults to `10`) or more than `max_days_listed` days (defaults `None` mean infinity).

View File

@@ -1,6 +1,7 @@
![freqtrade](assets/freqtrade_poweredby.svg)
[![Freqtrade CI](https://github.com/freqtrade/freqtrade/workflows/Freqtrade%20CI/badge.svg)](https://github.com/freqtrade/freqtrade/actions/)
[![DOI](https://joss.theoj.org/papers/10.21105/joss.04864/status.svg)](https://doi.org/10.21105/joss.04864)
[![Coverage Status](https://coveralls.io/repos/github/freqtrade/freqtrade/badge.svg?branch=develop&service=github)](https://coveralls.io/github/freqtrade/freqtrade?branch=develop)
[![Maintainability](https://api.codeclimate.com/v1/badges/5737e6d668200b7518ff/maintainability)](https://codeclimate.com/github/freqtrade/freqtrade/maintainability)
@@ -51,6 +52,7 @@ Please read the [exchange specific notes](exchanges.md) to learn about eventual,
- [X] [Binance](https://www.binance.com/)
- [X] [Gate.io](https://www.gate.io/ref/6266643)
- [X] [OKX](https://okx.com/)
- [X] [Bybit](https://bybit.com/)
Please make sure to read the [exchange specific notes](exchanges.md), as well as the [trading with leverage](leverage.md) documentation before diving in.

View File

@@ -30,6 +30,12 @@ The easiest way to install and run Freqtrade is to clone the bot Github reposito
!!! Warning "Up-to-date clock"
The clock on the system running the bot must be accurate, synchronized to a NTP server frequently enough to avoid problems with communication to the exchanges.
!!! Error "Running setup.py install for gym did not run successfully."
If you get an error related with gym we suggest you to downgrade setuptools it to version 65.5.0 you can do it with the following command:
```bash
pip install setuptools==65.5.0
```
------
## Requirements

View File

@@ -67,8 +67,6 @@ You will also have to pick a "margin mode" (explanation below) - with freqtrade
Freqtrade follows the [ccxt naming conventions for futures](https://docs.ccxt.com/en/latest/manual.html?#perpetual-swap-perpetual-future).
A futures pair will therefore have the naming of `base/quote:settle` (e.g. `ETH/USDT:USDT`).
Binance is currently still an exception to this naming scheme, where pairs are named `ETH/USDT` also for futures markets, but will be aligned as soon as CCXT is ready.
### Margin mode
On top of `trading_mode` - you will also have to configure your `margin_mode`.
@@ -92,6 +90,8 @@ One account is used to share collateral between markets (trading pairs). Margin
"margin_mode": "cross"
```
Please read the [exchange specific notes](exchanges.md) for exchanges that support this mode and how they differ.
## Set leverage to use
Different strategies and risk profiles will require different levels of leverage.

View File

@@ -11,9 +11,6 @@
{% endif %}
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" {{ hidden }}>
<div class="md-sidebar__scrollwrap">
<div id="widget-wrapper">
</div>
<div class="md-sidebar__inner">
{% include "partials/nav.html" %}
</div>
@@ -44,25 +41,4 @@
<script src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<!-- Load binance SDK -->
<script async defer src="https://public.bnbstatic.com/static/js/broker-sdk/broker-sdk@1.0.0.min.js"></script>
<script>
window.onload = function () {
var sidebar = document.getElementById('widget-wrapper')
var newDiv = document.createElement("div");
newDiv.id = "widget";
try {
sidebar.prepend(newDiv);
window.binanceBrokerPortalSdk.initBrokerSDK('#widget', {
apiHost: 'https://www.binance.com',
brokerId: 'R4BD3S82',
slideTime: 4e4,
});
} catch(err) {
console.log(err)
}
}
</script>
{% endblock %}

View File

@@ -1,6 +1,6 @@
markdown==3.3.7
mkdocs==1.4.2
mkdocs-material==8.5.10
mkdocs-material==9.0.13
mdx_truly_sane_lists==1.3
pymdown-extensions==9.8
pymdown-extensions==9.9.2
jinja2==3.1.2

View File

@@ -163,7 +163,7 @@ python3 scripts/rest_client.py --config rest_config.json <command> [optional par
| `strategy <strategy>` | Get specific Strategy content. **Alpha**
| `available_pairs` | List available backtest data. **Alpha**
| `version` | Show version.
| `sysinfo` | Show informations about the system load.
| `sysinfo` | Show information about the system load.
| `health` | Show bot health (last bot loop).
!!! Warning "Alpha status"
@@ -192,6 +192,11 @@ blacklist
:param add: List of coins to add (example: "BNB/BTC")
cancel_open_order
Cancel open order for trade.
:param trade_id: Cancels open orders for this trade.
count
Return the amount of open trades.
@@ -274,7 +279,6 @@ reload_config
Reload configuration.
show_config
Returns part of the configuration, relevant for trading operations.
start
@@ -320,6 +324,7 @@ version
whitelist
Show the current whitelist.
```
### Message WebSocket

View File

@@ -13,12 +13,12 @@ Feel free to use a visual Database editor like SqliteBrowser if you feel more co
sudo apt-get install sqlite3
```
### Using sqlite3 via docker-compose
### Using sqlite3 via docker
The freqtrade docker image does contain sqlite3, so you can edit the database without having to install anything on the host system.
``` bash
docker-compose exec freqtrade /bin/bash
docker compose exec freqtrade /bin/bash
sqlite3 <database-file>.sqlite
```

View File

@@ -24,7 +24,7 @@ These modes can be configured with these values:
```
!!! Note
Stoploss on exchange is only supported for Binance (stop-loss-limit), Huobi (stop-limit), Kraken (stop-loss-market, stop-loss-limit), Gateio (stop-limit), and Kucoin (stop-limit and stop-market) as of now.
Stoploss on exchange is only supported for Binance (stop-loss-limit), Huobi (stop-limit), Kraken (stop-loss-market, stop-loss-limit), Gate (stop-limit), and Kucoin (stop-limit and stop-market) as of now.
<ins>Do not set too low/tight stoploss value if using stop loss on exchange!</ins>
If set to low/tight then you have greater risk of missing fill on the order and stoploss will not work.
@@ -52,6 +52,18 @@ The bot cannot do these every 5 seconds (at each iteration), otherwise it would
So this parameter will tell the bot how often it should update the stoploss order. The default value is 60 (1 minute).
This same logic will reapply a stoploss order on the exchange should you cancel it accidentally.
### stoploss_price_type
!!! Warning "Only applies to futures"
`stoploss_price_type` only applies to futures markets (on exchanges where it's available).
Freqtrade will perform a validation of this setting on startup, failing to start if an invalid setting for your exchange has been selected.
Supported price types are gonna differs between each exchanges. Please check with your exchange on which price types it supports.
Stoploss on exchange on futures markets can trigger on different price types.
The naming for these prices in exchange terminology often varies, but is usually something around "last" (or "contract price" ), "mark" and "index".
Acceptable values for this setting are `"last"`, `"mark"` and `"index"` - which freqtrade will transfer automatically to the corresponding API type, and place the [stoploss on exchange](#stoploss_on_exchange-and-stoploss_on_exchange_limit_ratio) order correspondingly.
### force_exit
`force_exit` is an optional value, which defaults to the same value as `exit` and is used when sending a `/forceexit` command from Telegram or from the Rest API.

View File

@@ -80,7 +80,7 @@ class AwesomeStrategy(IStrategy):
## Enter Tag
When your strategy has multiple buy signals, you can name the signal that triggered.
Then you can access you buy signal on `custom_exit`
Then you can access your buy signal on `custom_exit`
```python
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:

View File

@@ -659,6 +659,7 @@ Position adjustments will always be applied in the direction of the trade, so a
!!! Warning "Backtesting"
During backtesting this callback is called for each candle in `timeframe` or `timeframe_detail`, so run-time performance will be affected.
This can also cause deviating results between live and backtesting, since backtesting can adjust the trade only once per candle, whereas live could adjust the trade multiple times per candle.
``` python
from freqtrade.persistence import Trade
@@ -773,7 +774,7 @@ class DigDeeperStrategy(IStrategy):
* Sell 100@10\$ -> Avg price: 8.5\$, realized profit 150\$, 17.65%
* Buy 150@11\$ -> Avg price: 10\$, realized profit 150\$, 17.65%
* Sell 100@12\$ -> Avg price: 10\$, total realized profit 350\$, 20%
* Sell 150@14\$ -> Avg price: 10\$, total realized profit 950\$, 40%
* Sell 150@14\$ -> Avg price: 10\$, total realized profit 950\$, 40% <- *This will be the last "Exit" message*
The total profit for this trade was 950$ on a 3350$ investment (`100@8$ + 100@9$ + 150@11$`). As such - the final relative profit is 28.35% (`950 / 3350`).
@@ -827,7 +828,7 @@ class AwesomeStrategy(IStrategy):
"""
# Limit orders to use and follow SMA200 as price target for the first 10 minutes since entry trigger for BTC/USDT pair.
if pair == 'BTC/USDT' and entry_tag == 'long_sma200' and side == 'long' and (current_time - timedelta(minutes=10) > trade.open_date_utc:
if pair == 'BTC/USDT' and entry_tag == 'long_sma200' and side == 'long' and (current_time - timedelta(minutes=10)) > trade.open_date_utc:
# just cancel the order if it has been filled more than half of the amount
if order.filled > order.remaining:
return None

View File

@@ -363,9 +363,9 @@ class AwesomeStrategy(IStrategy):
timeframe = "1d"
timeframe_mins = timeframe_to_minutes(timeframe)
minimal_roi = {
"0": 0.05, # 5% for the first 3 candles
str(timeframe_mins * 3)): 0.02, # 2% after 3 candles
str(timeframe_mins * 6)): 0.01, # 1% After 6 candles
"0": 0.05, # 5% for the first 3 candles
str(timeframe_mins * 3): 0.02, # 2% after 3 candles
str(timeframe_mins * 6): 0.01, # 1% After 6 candles
}
```
@@ -989,38 +989,18 @@ from freqtrade.persistence import Trade
The following example queries for the current pair and trades from today, however other filters can easily be added.
``` python
if self.config['runmode'].value in ('live', 'dry_run'):
trades = Trade.get_trades([Trade.pair == metadata['pair'],
Trade.open_date > datetime.utcnow() - timedelta(days=1),
Trade.is_open.is_(False),
]).order_by(Trade.close_date).all()
# Summarize profit for this pair.
curdayprofit = sum(trade.close_profit for trade in trades)
trades = Trade.get_trades_proxy(pair=metadata['pair'],
open_date=datetime.now(timezone.utc) - timedelta(days=1),
is_open=False,
]).order_by(Trade.close_date).all()
# Summarize profit for this pair.
curdayprofit = sum(trade.close_profit for trade in trades)
```
Get amount of stake_currency currently invested in Trades:
``` python
if self.config['runmode'].value in ('live', 'dry_run'):
total_stakes = Trade.total_open_trades_stakes()
```
Retrieve performance per pair.
Returns a List of dicts per pair.
``` python
if self.config['runmode'].value in ('live', 'dry_run'):
performance = Trade.get_overall_performance()
```
Sample return value: ETH/BTC had 5 trades, with a total profit of 1.5% (ratio of 0.015).
``` json
{"pair": "ETH/BTC", "profit": 0.015, "count": 5}
```
For a full list of available methods, please consult the [Trade object](trade-object.md) documentation.
!!! Warning
Trade history is not available during backtesting or hyperopt.
Trade history is not available in `populate_*` methods during backtesting or hyperopt, and will result in empty results.
## Prevent trades from happening for a specific pair

View File

@@ -2,12 +2,37 @@
Debugging a strategy can be time-consuming. Freqtrade offers helper functions to visualize raw data.
The following assumes you work with SampleStrategy, data for 5m timeframe from Binance and have downloaded them into the data directory in the default location.
Please follow the [documentation](https://www.freqtrade.io/en/stable/data-download/) for more details.
## Setup
### Change Working directory to repository root
```python
import os
from pathlib import Path
# Change directory
# Modify this cell to insure that the output shows the correct path.
# Define all paths relative to the project root shown in the cell output
project_root = "somedir/freqtrade"
i=0
try:
os.chdirdir(project_root)
assert Path('LICENSE').is_file()
except:
while i<4 and (not Path('LICENSE').is_file()):
os.chdir(Path(Path.cwd(), '../'))
i+=1
project_root = Path.cwd()
print(Path.cwd())
```
### Configure Freqtrade environment
```python
from freqtrade.configuration import Configuration
# Customize these according to your needs.
@@ -15,14 +40,14 @@ from freqtrade.configuration import Configuration
# Initialize empty configuration object
config = Configuration.from_files([])
# Optionally (recommended), use existing configuration file
# config = Configuration.from_files(["config.json"])
# config = Configuration.from_files(["user_data/config.json"])
# Define some constants
config["timeframe"] = "5m"
# Name of the strategy class
config["strategy"] = "SampleStrategy"
# Location of the data
data_location = config['datadir']
data_location = config["datadir"]
# Pair to analyze - Only use one pair here
pair = "BTC/USDT"
```
@@ -36,12 +61,12 @@ from freqtrade.enums import CandleType
candles = load_pair_history(datadir=data_location,
timeframe=config["timeframe"],
pair=pair,
data_format = "hdf5",
data_format = "json", # Make sure to update this to your data
candle_type=CandleType.SPOT,
)
# Confirm success
print("Loaded " + str(len(candles)) + f" rows of data for {pair} from {data_location}")
print(f"Loaded {len(candles)} rows of data for {pair} from {data_location}")
candles.head()
```
@@ -55,6 +80,7 @@ from freqtrade.resolvers import StrategyResolver
from freqtrade.data.dataprovider import DataProvider
strategy = StrategyResolver.load_strategy(config)
strategy.dp = DataProvider(config, None, None)
strategy.ft_bot_start()
# Generate buy/sell signals using strategy
df = strategy.analyze_ticker(candles, {'pair': pair})
@@ -232,7 +258,7 @@ graph = generate_candlestick_graph(pair=pair,
# Show graph inline
# graph.show()
# Render graph in a seperate window
# Render graph in a separate window
graph.show(renderer="browser")
```

View File

@@ -477,3 +477,254 @@ after:
"ignore_buying_expired_candle_after": 120
}
```
## FreqAI strategy
The `populate_any_indicators()` method has been split into `feature_engineering_expand_all()`, `feature_engineering_expand_basic()`, `feature_engineering_standard()` and`set_freqai_targets()`.
For each new function, the pair (and timeframe where necessary) will be automatically added to the column.
As such, the definition of features becomes much simpler with the new logic.
For a full explanation of each method, please go to the corresponding [freqAI documentation page](freqai-feature-engineering.md#defining-the-features)
``` python linenums="1" hl_lines="12-37 39-42 63-65 67-75"
def populate_any_indicators(
self, pair, df, tf, informative=None, set_generalized_indicators=False
):
if informative is None:
informative = self.dp.get_pair_dataframe(pair, tf)
# first loop is automatically duplicating indicators for time periods
for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]:
t = int(t)
informative[f"%-{pair}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t)
informative[f"%-{pair}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t)
informative[f"%-{pair}adx-period_{t}"] = ta.ADX(informative, timeperiod=t)
informative[f"%-{pair}sma-period_{t}"] = ta.SMA(informative, timeperiod=t)
informative[f"%-{pair}ema-period_{t}"] = ta.EMA(informative, timeperiod=t)
bollinger = qtpylib.bollinger_bands(
qtpylib.typical_price(informative), window=t, stds=2.2
)
informative[f"{pair}bb_lowerband-period_{t}"] = bollinger["lower"]
informative[f"{pair}bb_middleband-period_{t}"] = bollinger["mid"]
informative[f"{pair}bb_upperband-period_{t}"] = bollinger["upper"]
informative[f"%-{pair}bb_width-period_{t}"] = (
informative[f"{pair}bb_upperband-period_{t}"]
- informative[f"{pair}bb_lowerband-period_{t}"]
) / informative[f"{pair}bb_middleband-period_{t}"]
informative[f"%-{pair}close-bb_lower-period_{t}"] = (
informative["close"] / informative[f"{pair}bb_lowerband-period_{t}"]
)
informative[f"%-{pair}roc-period_{t}"] = ta.ROC(informative, timeperiod=t)
informative[f"%-{pair}relative_volume-period_{t}"] = (
informative["volume"] / informative["volume"].rolling(t).mean()
) # (1)
informative[f"%-{pair}pct-change"] = informative["close"].pct_change()
informative[f"%-{pair}raw_volume"] = informative["volume"]
informative[f"%-{pair}raw_price"] = informative["close"]
# (2)
indicators = [col for col in informative if col.startswith("%")]
# This loop duplicates and shifts all indicators to add a sense of recency to data
for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1):
if n == 0:
continue
informative_shift = informative[indicators].shift(n)
informative_shift = informative_shift.add_suffix("_shift-" + str(n))
informative = pd.concat((informative, informative_shift), axis=1)
df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True)
skip_columns = [
(s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"]
]
df = df.drop(columns=skip_columns)
# Add generalized indicators here (because in live, it will call this
# function to populate indicators during training). Notice how we ensure not to
# add them multiple times
if set_generalized_indicators:
df["%-day_of_week"] = (df["date"].dt.dayofweek + 1) / 7
df["%-hour_of_day"] = (df["date"].dt.hour + 1) / 25
# (3)
# user adds targets here by prepending them with &- (see convention below)
df["&-s_close"] = (
df["close"]
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
.mean()
/ df["close"]
- 1
) # (4)
return df
```
1. Features - Move to `feature_engineering_expand_all`
2. Basic features, not expanded across `include_periods_candles` - move to`feature_engineering_expand_basic()`.
3. Standard features which should not be expanded - move to `feature_engineering_standard()`.
4. Targets - Move this part to `set_freqai_targets()`.
### freqai - feature engineering expand all
Features will now expand automatically. As such, the expansion loops, as well as the `{pair}` / `{timeframe}` parts will need to be removed.
``` python linenums="1"
def feature_engineering_expand_all(self, dataframe, period, **kwargs):
"""
*Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined
`indicator_periods_candles`, `include_timeframes`, `include_shifted_candles`, and
`include_corr_pairs`. In other words, a single feature defined in this function
will automatically expand to a total of
`indicator_periods_candles` * `include_timeframes` * `include_shifted_candles` *
`include_corr_pairs` numbers of features added to the model.
All features must be prepended with `%` to be recognized by FreqAI internals.
More details on how these config defined parameters accelerate feature engineering
in the documentation at:
https://www.freqtrade.io/en/latest/freqai-parameter-table/#feature-parameters
https://www.freqtrade.io/en/latest/freqai-feature-engineering/#defining-the-features
:param df: strategy dataframe which will receive the features
:param period: period of the indicator - usage example:
dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period)
"""
dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period)
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
dataframe["%-sma-period"] = ta.SMA(dataframe, timeperiod=period)
dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period)
bollinger = qtpylib.bollinger_bands(
qtpylib.typical_price(dataframe), window=period, stds=2.2
)
dataframe["bb_lowerband-period"] = bollinger["lower"]
dataframe["bb_middleband-period"] = bollinger["mid"]
dataframe["bb_upperband-period"] = bollinger["upper"]
dataframe["%-bb_width-period"] = (
dataframe["bb_upperband-period"]
- dataframe["bb_lowerband-period"]
) / dataframe["bb_middleband-period"]
dataframe["%-close-bb_lower-period"] = (
dataframe["close"] / dataframe["bb_lowerband-period"]
)
dataframe["%-roc-period"] = ta.ROC(dataframe, timeperiod=period)
dataframe["%-relative_volume-period"] = (
dataframe["volume"] / dataframe["volume"].rolling(period).mean()
)
return dataframe
```
### Freqai - feature engineering basic
Basic features. Make sure to remove the `{pair}` part from your features.
``` python linenums="1"
def feature_engineering_expand_basic(self, dataframe, **kwargs):
"""
*Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined
`include_timeframes`, `include_shifted_candles`, and `include_corr_pairs`.
In other words, a single feature defined in this function
will automatically expand to a total of
`include_timeframes` * `include_shifted_candles` * `include_corr_pairs`
numbers of features added to the model.
Features defined here will *not* be automatically duplicated on user defined
`indicator_periods_candles`
All features must be prepended with `%` to be recognized by FreqAI internals.
More details on how these config defined parameters accelerate feature engineering
in the documentation at:
https://www.freqtrade.io/en/latest/freqai-parameter-table/#feature-parameters
https://www.freqtrade.io/en/latest/freqai-feature-engineering/#defining-the-features
:param df: strategy dataframe which will receive the features
dataframe["%-pct-change"] = dataframe["close"].pct_change()
dataframe["%-ema-200"] = ta.EMA(dataframe, timeperiod=200)
"""
dataframe["%-pct-change"] = dataframe["close"].pct_change()
dataframe["%-raw_volume"] = dataframe["volume"]
dataframe["%-raw_price"] = dataframe["close"]
return dataframe
```
### FreqAI - feature engineering standard
``` python linenums="1"
def feature_engineering_standard(self, dataframe, **kwargs):
"""
*Only functional with FreqAI enabled strategies*
This optional function will be called once with the dataframe of the base timeframe.
This is the final function to be called, which means that the dataframe entering this
function will contain all the features and columns created by all other
freqai_feature_engineering_* functions.
This function is a good place to do custom exotic feature extractions (e.g. tsfresh).
This function is a good place for any feature that should not be auto-expanded upon
(e.g. day of the week).
All features must be prepended with `%` to be recognized by FreqAI internals.
More details about feature engineering available:
https://www.freqtrade.io/en/latest/freqai-feature-engineering
:param df: strategy dataframe which will receive the features
usage example: dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7
"""
dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek
dataframe["%-hour_of_day"] = dataframe["date"].dt.hour
return dataframe
```
### FreqAI - set Targets
Targets now get their own, dedicated method.
``` python linenums="1"
def set_freqai_targets(self, dataframe, **kwargs):
"""
*Only functional with FreqAI enabled strategies*
Required function to set the targets for the model.
All targets must be prepended with `&` to be recognized by the FreqAI internals.
More details about feature engineering available:
https://www.freqtrade.io/en/latest/freqai-feature-engineering
:param df: strategy dataframe which will receive the targets
usage example: dataframe["&-target"] = dataframe["close"].shift(-1) / dataframe["close"]
"""
dataframe["&-s_close"] = (
dataframe["close"]
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
.mean()
/ dataframe["close"]
- 1
)
return dataframe
```

View File

@@ -11,18 +11,3 @@
.rst-versions .rst-other-versions {
color: white;
}
#widget-wrapper {
height: calc(220px * 0.5625 + 18px);
width: 220px;
margin: 0 auto 16px auto;
border-style: solid;
border-color: var(--md-code-bg-color);
border-width: 1px;
border-radius: 5px;
}
@media screen and (max-width: calc(76.25em - 1px)) {
#widget-wrapper { display: none; }
}

View File

@@ -162,26 +162,33 @@ official commands. You can ask at any moment for help with `/help`.
| Command | Description |
|----------|-------------|
| **System commands**
| `/start` | Starts the trader
| `/stop` | Stops the trader
| `/stopbuy | /stopentry` | Stops the trader from opening new trades. Gracefully closes open trades according to their rules.
| `/reload_config` | Reloads the configuration file
| `/show_config` | Shows part of the current configuration with relevant settings to operation
| `/logs [limit]` | Show last log messages.
| `/help` | Show help message
| `/version` | Show version
| **Status** |
| `/status` | Lists all open trades
| `/status <trade_id>` | Lists one or more specific trade. Separate multiple <trade_id> with a blank space.
| `/status table` | List all open trades in a table format. Pending buy orders are marked with an asterisk (*) Pending sell orders are marked with a double asterisk (**)
| `/trades [limit]` | List all recently closed trades in a table format.
| `/delete <trade_id>` | Delete a specific trade from the Database. Tries to close open orders. Requires manual handling of this trade on the exchange.
| `/count` | Displays number of trades used and available
| `/locks` | Show currently locked pairs.
| `/unlock <pair or lock_id>` | Remove the lock for this pair (or for this lock id).
| `/profit [<n>]` | Display a summary of your profit/loss from close trades and some stats about your performance, over the last n days (all trades by default)
| **Modify Trade states** |
| `/forceexit <trade_id> | /fx <tradeid>` | Instantly exits the given trade (Ignoring `minimum_roi`).
| `/forceexit all | /fx all` | Instantly exits all open trades (Ignoring `minimum_roi`).
| `/fx` | alias for `/forceexit`
| `/forcelong <pair> [rate]` | Instantly buys the given pair. Rate is optional and only applies to limit orders. (`force_entry_enable` must be set to True)
| `/forceshort <pair> [rate]` | Instantly shorts the given pair. Rate is optional and only applies to limit orders. This will only work on non-spot markets. (`force_entry_enable` must be set to True)
| `/delete <trade_id>` | Delete a specific trade from the Database. Tries to close open orders. Requires manual handling of this trade on the exchange.
| `/cancel_open_order <trade_id> | /coo <trade_id>` | Cancel an open order for a trade.
| **Metrics** |
| `/profit [<n>]` | Display a summary of your profit/loss from close trades and some stats about your performance, over the last n days (all trades by default)
| `/performance` | Show performance of each finished trade grouped by pair
| `/balance` | Show account balance per currency
| `/daily <n>` | Shows profit or loss per day, over the last n days (n defaults to 7)
@@ -193,8 +200,7 @@ official commands. You can ask at any moment for help with `/help`.
| `/whitelist [sorted] [baseonly]` | Show the current whitelist. Optionally display in alphabetical order and/or with just the base currency of each pairing.
| `/blacklist [pair]` | Show the current blacklist, or adds a pair to the blacklist.
| `/edge` | Show validated pairs by Edge if it is enabled.
| `/help` | Show help message
| `/version` | Show version
## Telegram commands in action

148
docs/trade-object.md Normal file
View File

@@ -0,0 +1,148 @@
# Trade Object
## Trade
A position freqtrade enters is stored in a `Trade` object - which is persisted to the database.
It's a core concept of freqtrade - and something you'll come across in many sections of the documentation, which will most likely point you to this location.
It will be passed to the strategy in many [strategy callbacks](strategy-callbacks.md). The object passed to the strategy cannot be modified directly. Indirect modifications may occur based on callback results.
## Trade - Available attributes
The following attributes / properties are available for each individual trade - and can be used with `trade.<property>` (e.g. `trade.pair`).
| Attribute | DataType | Description |
|------------|-------------|-------------|
`pair`| string | Pair of this trade
`is_open`| boolean | Is the trade currently open, or has it been concluded
`open_rate`| float | Rate this trade was entered at (Avg. entry rate in case of trade-adjustments)
`close_rate`| float | Close rate - only set when is_open = False
`stake_amount`| float | Amount in Stake (or Quote) currency.
`amount`| float | Amount in Asset / Base currency that is currently owned.
`open_date`| datetime | Timestamp when trade was opened **use `open_date_utc` instead**
`open_date_utc`| datetime | Timestamp when trade was opened - in UTC
`close_date`| datetime | Timestamp when trade was closed **use `close_date_utc` instead**
`close_date_utc`| datetime | Timestamp when trade was closed - in UTC
`close_profit`| float | Relative profit at the time of trade closure. `0.01` == 1%
`close_profit_abs`| float | Absolute profit (in stake currency) at the time of trade closure.
`leverage` | float | Leverage used for this trade - defaults to 1.0 in spot markets.
`enter_tag`| string | Tag provided on entry via the `enter_tag` column in the dataframe
`is_short` | boolean | True for short trades, False otherwise
`orders` | Order[] | List of order objects attached to this trade (includes both filled and cancelled orders)
`date_last_filled_utc` | datetime | Time of the last filled order
`entry_side` | "buy" / "sell" | Order Side the trade was entered
`exit_side` | "buy" / "sell" | Order Side that will result in a trade exit / position reduction.
`trade_direction` | "long" / "short" | Trade direction in text - long or short.
`nr_of_successful_entries` | int | Number of successful (filled) entry orders
`nr_of_successful_exits` | int | Number of successful (filled) exit orders
## Class methods
The following are class methods - which return generic information, and usually result in an explicit query against the database.
They can be used as `Trade.<method>` - e.g. `open_trades = Trade.get_open_trade_count()`
!!! Warning "Backtesting/hyperopt"
Most methods will work in both backtesting / hyperopt and live/dry modes.
During backtesting, it's limited to usage in [strategy callbacks](strategy-callbacks.md). Usage in `populate_*()` methods is not supported and will result in wrong results.
### get_trades_proxy
When your strategy needs some information on existing (open or close) trades - it's best to use `Trade.get_trades_proxy()`.
Usage:
``` python
from freqtrade.persistence import Trade
from datetime import timedelta
# ...
trade_hist = Trade.get_trades_proxy(pair='ETH/USDT', is_open=False, open_date=current_date - timedelta(days=2))
```
`get_trades_proxy()` supports the following keyword arguments. All arguments are optional - calling `get_trades_proxy()` without arguments will return a list of all trades in the database.
* `pair` e.g. `pair='ETH/USDT'`
* `is_open` e.g. `is_open=False`
* `open_date` e.g. `open_date=current_date - timedelta(days=2)`
* `close_date` e.g. `close_date=current_date - timedelta(days=5)`
### get_open_trade_count
Get the number of currently open trades
``` python
from freqtrade.persistence import Trade
# ...
open_trades = Trade.get_open_trade_count()
```
### get_total_closed_profit
Retrieve the total profit the bot has generated so far.
Aggregates `close_profit_abs` for all closed trades.
``` python
from freqtrade.persistence import Trade
# ...
profit = Trade.get_total_closed_profit()
```
### total_open_trades_stakes
Retrieve the total stake_amount that's currently in trades.
``` python
from freqtrade.persistence import Trade
# ...
profit = Trade.total_open_trades_stakes()
```
### get_overall_performance
Retrieve the overall performance - similar to the `/performance` telegram command.
``` python
from freqtrade.persistence import Trade
# ...
if self.config['runmode'].value in ('live', 'dry_run'):
performance = Trade.get_overall_performance()
```
Sample return value: ETH/BTC had 5 trades, with a total profit of 1.5% (ratio of 0.015).
``` json
{"pair": "ETH/BTC", "profit": 0.015, "count": 5}
```
## Order Object
An `Order` object represents an order on the exchange (or a simulated order in dry-run mode).
An `Order` object will always be tied to it's corresponding [`Trade`](#trade-object), and only really makes sense in the context of a trade.
### Order - Available attributes
an Order object is typically attached to a trade.
Most properties here can be None as they are dependant on the exchange response.
| Attribute | DataType | Description |
|------------|-------------|-------------|
`trade` | Trade | Trade object this order is attached to
`ft_pair` | string | Pair this order is for
`ft_is_open` | boolean | is the order filled?
`order_type` | string | Order type as defined on the exchange - usually market, limit or stoploss
`status` | string | Status as defined by ccxt. Usually open, closed, expired or canceled
`side` | string | Buy or Sell
`price` | float | Price the order was placed at
`average` | float | Average price the order filled at
`amount` | float | Amount in base currency
`filled` | float | Filled amount (in base currency)
`remaining` | float | Remaining amount
`cost` | float | Cost of the order - usually average * filled
`order_date` | datetime | Order creation date **use `order_date_utc` instead**
`order_date_utc` | datetime | Order creation date (in UTC)
`order_fill_date` | datetime | Order fill date **use `order_fill_utc` instead**
`order_fill_date_utc` | datetime | Order fill date

View File

@@ -6,14 +6,14 @@ To update your freqtrade installation, please use one of the below methods, corr
Breaking changes / changed behavior will be documented in the changelog that is posted alongside every release.
For the develop branch, please follow PR's to avoid being surprised by changes.
## docker-compose
## docker
!!! Note "Legacy installations using the `master` image"
We're switching from master to stable for the release Images - please adjust your docker-file and replace `freqtradeorg/freqtrade:master` with `freqtradeorg/freqtrade:stable`
``` bash
docker-compose pull
docker-compose up -d
docker compose pull
docker compose up -d
```
## Installation via setup script

View File

@@ -652,7 +652,7 @@ Common arguments:
You can also use webserver mode via docker.
Starting a one-off container requires the configuration of the port explicitly, as ports are not exposed by default.
You can use `docker-compose run --rm -p 127.0.0.1:8080:8080 freqtrade webserver` to start a one-off container that'll be removed once you stop it. This assumes that port 8080 is still available and no other bot is running on that port.
You can use `docker compose run --rm -p 127.0.0.1:8080:8080 freqtrade webserver` to start a one-off container that'll be removed once you stop it. This assumes that port 8080 is still available and no other bot is running on that port.
Alternatively, you can reconfigure the docker-compose file to have the command updated:
@@ -662,7 +662,7 @@ Alternatively, you can reconfigure the docker-compose file to have the command u
--config /freqtrade/user_data/config.json
```
You can now use `docker-compose up` to start the webserver.
You can now use `docker compose up` to start the webserver.
This assumes that the configuration has a webserver enabled and configured for docker (listening port = `0.0.0.0`).
!!! Tip
@@ -722,6 +722,7 @@ usage: freqtrade backtesting-analysis [-h] [-v] [--logfile FILE] [-V]
[--enter-reason-list ENTER_REASON_LIST [ENTER_REASON_LIST ...]]
[--exit-reason-list EXIT_REASON_LIST [EXIT_REASON_LIST ...]]
[--indicator-list INDICATOR_LIST [INDICATOR_LIST ...]]
[--timerange YYYYMMDD-[YYYYMMDD]]
optional arguments:
-h, --help show this help message and exit
@@ -744,6 +745,10 @@ optional arguments:
--indicator-list INDICATOR_LIST [INDICATOR_LIST ...]
Comma separated list of indicators to analyse. e.g.
'close,rsi,bb_lowerband,profit_abs'
--timerange YYYYMMDD-[YYYYMMDD]
Timerange to filter trades for analysis,
start inclusive, end exclusive. e.g.
20220101-20220201
Common arguments:
-v, --verbose Verbose mode (-vv for more, -vvv to get all messages).

View File

@@ -12,7 +12,7 @@ dependencies:
- py-find-1st
- aiohttp
- SQLAlchemy
- python-telegram-bot
- python-telegram-bot<20.0.0
- arrow
- cachetools
- requests
@@ -54,7 +54,7 @@ dependencies:
# 3/4 req hyperopt
- scipy
- scikit-learn
- scikit-learn<1.2.0
- filelock
- scikit-optimize
- progressbar2

View File

@@ -1,19 +1,20 @@
""" Freqtrade bot """
__version__ = '2022.11'
__version__ = '2023.2'
if 'dev' in __version__:
from pathlib import Path
try:
import subprocess
freqtrade_basedir = Path(__file__).parent
__version__ = __version__ + '-' + subprocess.check_output(
['git', 'log', '--format="%h"', '-n 1'],
stderr=subprocess.DEVNULL).decode("utf-8").rstrip().strip('"')
stderr=subprocess.DEVNULL, cwd=freqtrade_basedir).decode("utf-8").rstrip().strip('"')
except Exception: # pragma: no cover
# git not available, ignore
try:
# Try Fallback to freqtrade_commit file (created by CI while building docker image)
from pathlib import Path
versionfile = Path('./freqtrade_commit')
if versionfile.is_file():
__version__ = f"docker-{__version__}-{versionfile.read_text()[:8]}"

0
freqtrade/__main__.py Normal file → Executable file
View File

8
freqtrade/commands/analyze_commands.py Executable file → Normal file
View File

@@ -60,10 +60,4 @@ def start_analysis_entries_exits(args: Dict[str, Any]) -> None:
logger.info('Starting freqtrade in analysis mode')
process_entry_exit_reasons(config['exportfilename'],
config['exchange']['pair_whitelist'],
config['analysis_groups'],
config['enter_reason_list'],
config['exit_reason_list'],
config['indicator_list']
)
process_entry_exit_reasons(config)

View File

@@ -106,7 +106,7 @@ ARGS_HYPEROPT_SHOW = ["hyperopt_list_best", "hyperopt_list_profitable", "hyperop
"disableparamexport", "backtest_breakdown"]
ARGS_ANALYZE_ENTRIES_EXITS = ["exportfilename", "analysis_groups", "enter_reason_list",
"exit_reason_list", "indicator_list"]
"exit_reason_list", "indicator_list", "timerange"]
NO_CONF_REQURIED = ["convert-data", "convert-trade-data", "download-data", "list-timeframes",
"list-markets", "list-pairs", "list-strategies", "list-freqaimodels",

View File

@@ -108,7 +108,7 @@ def ask_user_config() -> Dict[str, Any]:
"binance",
"binanceus",
"bittrex",
"gateio",
"gate",
"huobi",
"kraken",
"kucoin",
@@ -123,7 +123,7 @@ def ask_user_config() -> Dict[str, Any]:
"message": "Do you want to trade Perpetual Swaps (perpetual futures)?",
"default": False,
"filter": lambda val: 'futures' if val else 'spot',
"when": lambda x: x["exchange_name"] in ['binance', 'gateio', 'okx'],
"when": lambda x: x["exchange_name"] in ['binance', 'gate', 'okx'],
},
{
"type": "autocomplete",

View File

@@ -251,7 +251,8 @@ AVAILABLE_CLI_OPTIONS = {
"spaces": Arg(
'--spaces',
help='Specify which parameters to hyperopt. Space-separated list.',
choices=['all', 'buy', 'sell', 'roi', 'stoploss', 'trailing', 'protection', 'default'],
choices=['all', 'buy', 'sell', 'roi', 'stoploss',
'trailing', 'protection', 'trades', 'default'],
nargs='+',
default='default',
),
@@ -632,10 +633,11 @@ AVAILABLE_CLI_OPTIONS = {
"1: by enter_tag, "
"2: by enter_tag and exit_tag, "
"3: by pair and enter_tag, "
"4: by pair, enter_ and exit_tag (this can get quite large)"),
"4: by pair, enter_ and exit_tag (this can get quite large), "
"5: by exit_tag"),
nargs='+',
default=['0', '1', '2'],
choices=['0', '1', '2', '3', '4'],
choices=['0', '1', '2', '3', '4', '5'],
),
"enter_reason_list": Arg(
"--enter-reason-list",

View File

@@ -14,6 +14,7 @@ from freqtrade.exceptions import OperationalException
from freqtrade.exchange import market_is_active, timeframe_to_minutes
from freqtrade.plugins.pairlist.pairlist_helpers import dynamic_expand_pairlist, expand_pairlist
from freqtrade.resolvers import ExchangeResolver
from freqtrade.util.binance_mig import migrate_binance_futures_data
logger = logging.getLogger(__name__)
@@ -86,6 +87,7 @@ def start_download_data(args: Dict[str, Any]) -> None:
"Please use `--dl-trades` instead for this exchange "
"(will unfortunately take a long time)."
)
migrate_binance_futures_data(config)
pairs_not_available = refresh_backtest_ohlcv_data(
exchange, pairs=expanded_pairs, timeframes=config['timeframes'],
datadir=config['datadir'], timerange=timerange,
@@ -145,6 +147,7 @@ def start_convert_data(args: Dict[str, Any], ohlcv: bool = True) -> None:
"""
config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE)
if ohlcv:
migrate_binance_futures_data(config)
candle_types = [CandleType.from_string(ct) for ct in config.get('candle_types', ['spot'])]
for candle_type in candle_types:
convert_ohlcv_format(config,

0
freqtrade/commands/hyperopt_commands.py Executable file → Normal file
View File

View File

@@ -1,4 +1,5 @@
import logging
import signal
from typing import Any, Dict
@@ -12,15 +13,20 @@ def start_trading(args: Dict[str, Any]) -> int:
# Import here to avoid loading worker module when it's not used
from freqtrade.worker import Worker
def term_handler(signum, frame):
# Raise KeyboardInterrupt - so we can handle it in the same way as Ctrl-C
raise KeyboardInterrupt()
# Create and run worker
worker = None
try:
signal.signal(signal.SIGTERM, term_handler)
worker = Worker(args)
worker.run()
except Exception as e:
logger.error(str(e))
logger.exception("Fatal exception!")
except KeyboardInterrupt:
except (KeyboardInterrupt):
logger.info('SIGINT received, aborting ...')
finally:
if worker:

View File

@@ -355,6 +355,13 @@ def _validate_freqai_include_timeframes(conf: Dict[str, Any]) -> None:
f"Main timeframe of {main_tf} must be smaller or equal to FreqAI "
f"`include_timeframes`.Offending include-timeframes: {', '.join(offending_lines)}")
# Ensure that the base timeframe is included in the include_timeframes list
if main_tf not in freqai_include_timeframes:
feature_parameters = conf.get('freqai', {}).get('feature_parameters', {})
include_timeframes = [main_tf] + freqai_include_timeframes
conf.get('freqai', {}).get('feature_parameters', {}) \
.update({**feature_parameters, 'include_timeframes': include_timeframes})
def _validate_freqai_backtest(conf: Dict[str, Any]) -> None:
if conf.get('runmode', RunMode.OTHER) == RunMode.BACKTEST:

View File

@@ -28,7 +28,7 @@ class Configuration:
Reuse this class for the bot, backtesting, hyperopt and every script that required configuration
"""
def __init__(self, args: Dict[str, Any], runmode: RunMode = None) -> None:
def __init__(self, args: Dict[str, Any], runmode: Optional[RunMode] = None) -> None:
self.args = args
self.config: Optional[Config] = None
self.runmode = runmode
@@ -462,6 +462,9 @@ class Configuration:
self._args_to_config(config, argname='indicator_list',
logstring='Analysis indicator list: {}')
self._args_to_config(config, argname='timerange',
logstring='Filter trades by timerange: {}')
def _process_runmode(self, config: Config) -> None:
self._args_to_config(config, argname='dry_run',

View File

@@ -32,7 +32,7 @@ def flat_vars_to_nested_dict(env_dict: Dict[str, Any], prefix: str) -> Dict[str,
:param prefix: Prefix to consider (usually FREQTRADE__)
:return: Nested dict based on available and relevant variables.
"""
no_convert = ['CHAT_ID']
no_convert = ['CHAT_ID', 'PASSWORD']
relevant_vars: Dict[str, Any] = {}
for env_var, val in sorted(env_dict.items()):

View File

@@ -6,7 +6,7 @@ import re
import sys
from copy import deepcopy
from pathlib import Path
from typing import Any, Dict, List
from typing import Any, Dict, List, Optional
import rapidjson
@@ -75,7 +75,8 @@ def load_config_file(path: str) -> Dict[str, Any]:
return config
def load_from_files(files: List[str], base_path: Path = None, level: int = 0) -> Dict[str, Any]:
def load_from_files(
files: List[str], base_path: Optional[Path] = None, level: int = 0) -> Dict[str, Any]:
"""
Recursively load configuration files if specified.
Sub-files are assumed to be relative to the initial config.

View File

@@ -5,7 +5,7 @@ bot constants
"""
from typing import Any, Dict, List, Literal, Tuple
from freqtrade.enums import CandleType, RPCMessageType
from freqtrade.enums import CandleType, PriceType, RPCMessageType
DEFAULT_CONFIG = 'config.json'
@@ -25,13 +25,14 @@ PRICING_SIDES = ['ask', 'bid', 'same', 'other']
ORDERTYPE_POSSIBILITIES = ['limit', 'market']
_ORDERTIF_POSSIBILITIES = ['GTC', 'FOK', 'IOC', 'PO']
ORDERTIF_POSSIBILITIES = _ORDERTIF_POSSIBILITIES + [t.lower() for t in _ORDERTIF_POSSIBILITIES]
STOPLOSS_PRICE_TYPES = [p for p in PriceType]
HYPEROPT_LOSS_BUILTIN = ['ShortTradeDurHyperOptLoss', 'OnlyProfitHyperOptLoss',
'SharpeHyperOptLoss', 'SharpeHyperOptLossDaily',
'SortinoHyperOptLoss', 'SortinoHyperOptLossDaily',
'CalmarHyperOptLoss',
'MaxDrawDownHyperOptLoss', 'MaxDrawDownRelativeHyperOptLoss',
'ProfitDrawDownHyperOptLoss']
AVAILABLE_PAIRLISTS = ['StaticPairList', 'VolumePairList', 'ProducerPairList',
AVAILABLE_PAIRLISTS = ['StaticPairList', 'VolumePairList', 'ProducerPairList', 'RemotePairList',
'AgeFilter', 'OffsetFilter', 'PerformanceFilter',
'PrecisionFilter', 'PriceFilter', 'RangeStabilityFilter',
'ShuffleFilter', 'SpreadFilter', 'VolatilityFilter']
@@ -61,6 +62,7 @@ USERPATH_FREQAIMODELS = 'freqaimodels'
TELEGRAM_SETTING_OPTIONS = ['on', 'off', 'silent']
WEBHOOK_FORMAT_OPTIONS = ['form', 'json', 'raw']
FULL_DATAFRAME_THRESHOLD = 100
ENV_VAR_PREFIX = 'FREQTRADE__'
@@ -228,6 +230,7 @@ CONF_SCHEMA = {
'default': 'market'},
'stoploss': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES},
'stoploss_on_exchange': {'type': 'boolean'},
'stoploss_price_type': {'type': 'string', 'enum': STOPLOSS_PRICE_TYPES},
'stoploss_on_exchange_interval': {'type': 'number'},
'stoploss_on_exchange_limit_ratio': {'type': 'number', 'minimum': 0.0,
'maximum': 1.0}
@@ -543,7 +546,7 @@ CONF_SCHEMA = {
"enabled": {"type": "boolean", "default": False},
"keras": {"type": "boolean", "default": False},
"write_metrics_to_disk": {"type": "boolean", "default": False},
"purge_old_models": {"type": "boolean", "default": True},
"purge_old_models": {"type": ["boolean", "number"], "default": 2},
"conv_width": {"type": "integer", "default": 1},
"train_period_days": {"type": "integer", "default": 0},
"backtest_period_days": {"type": "number", "default": 7},
@@ -565,7 +568,9 @@ CONF_SCHEMA = {
"shuffle": {"type": "boolean", "default": False},
"nu": {"type": "number", "default": 0.1}
},
}
},
"shuffle_after_split": {"type": "boolean", "default": False},
"buffer_train_data_candles": {"type": "integer", "default": 0}
},
"required": ["include_timeframes", "include_corr_pairlist", ]
},
@@ -578,9 +583,27 @@ CONF_SCHEMA = {
},
},
"model_training_parameters": {
"type": "object"
},
"rl_config": {
"type": "object",
"properties": {
"n_estimators": {"type": "integer", "default": 1000}
"train_cycles": {"type": "integer"},
"max_trade_duration_candles": {"type": "integer"},
"add_state_info": {"type": "boolean", "default": False},
"max_training_drawdown_pct": {"type": "number", "default": 0.02},
"cpu_count": {"type": "integer", "default": 1},
"model_type": {"type": "string", "default": "PPO"},
"policy_type": {"type": "string", "default": "MlpPolicy"},
"net_arch": {"type": "array", "default": [128, 128]},
"randomize_startinng_position": {"type": "boolean", "default": False},
"model_reward_parameters": {
"type": "object",
"properties": {
"rr": {"type": "number", "default": 1},
"profit_aim": {"type": "number", "default": 0.025}
}
}
},
},
},
@@ -590,9 +613,8 @@ CONF_SCHEMA = {
"backtest_period_days",
"identifier",
"feature_parameters",
"data_split_parameters",
"model_training_parameters"
]
"data_split_parameters"
]
},
},
}
@@ -618,7 +640,6 @@ SCHEMA_TRADE_REQUIRED = [
SCHEMA_BACKTEST_REQUIRED = [
'exchange',
'max_open_trades',
'stake_currency',
'stake_amount',
'dry_run_wallet',
@@ -628,6 +649,7 @@ SCHEMA_BACKTEST_REQUIRED = [
SCHEMA_BACKTEST_REQUIRED_FINAL = SCHEMA_BACKTEST_REQUIRED + [
'stoploss',
'minimal_roi',
'max_open_trades'
]
SCHEMA_MINIMAL_REQUIRED = [
@@ -661,5 +683,7 @@ EntryExit = Literal['entry', 'exit']
BuySell = Literal['buy', 'sell']
MakerTaker = Literal['maker', 'taker']
BidAsk = Literal['bid', 'ask']
OBLiteral = Literal['asks', 'bids']
Config = Dict[str, Any]
IntOrInf = float

View File

@@ -10,7 +10,7 @@ from typing import Any, Dict, List, Optional, Union
import numpy as np
import pandas as pd
from freqtrade.constants import LAST_BT_RESULT_FN
from freqtrade.constants import LAST_BT_RESULT_FN, IntOrInf
from freqtrade.exceptions import OperationalException
from freqtrade.misc import json_load
from freqtrade.optimize.backtest_caching import get_backtest_metadata_filename
@@ -20,8 +20,8 @@ from freqtrade.persistence import LocalTrade, Trade, init_db
logger = logging.getLogger(__name__)
# Newest format
BT_DATA_COLUMNS = ['pair', 'stake_amount', 'amount', 'open_date', 'close_date',
'open_rate', 'close_rate',
BT_DATA_COLUMNS = ['pair', 'stake_amount', 'max_stake_amount', 'amount',
'open_date', 'close_date', 'open_rate', 'close_rate',
'fee_open', 'fee_close', 'trade_duration',
'profit_ratio', 'profit_abs', 'exit_reason',
'initial_stop_loss_abs', 'initial_stop_loss_ratio', 'stop_loss_abs',
@@ -90,7 +90,8 @@ def get_latest_hyperopt_filename(directory: Union[Path, str]) -> str:
return 'hyperopt_results.pickle'
def get_latest_hyperopt_file(directory: Union[Path, str], predef_filename: str = None) -> Path:
def get_latest_hyperopt_file(
directory: Union[Path, str], predef_filename: Optional[str] = None) -> Path:
"""
Get latest hyperopt export based on '.last_result.json'.
:param directory: Directory to search for last result
@@ -193,7 +194,7 @@ def get_backtest_resultlist(dirname: Path):
def find_existing_backtest_stats(dirname: Union[Path, str], run_ids: Dict[str, str],
min_backtest_date: datetime = None) -> Dict[str, Any]:
min_backtest_date: Optional[datetime] = None) -> Dict[str, Any]:
"""
Find existing backtest stats that match specified run IDs and load them.
:param dirname: pathlib.Path object, or string pointing to the file.
@@ -241,6 +242,33 @@ def find_existing_backtest_stats(dirname: Union[Path, str], run_ids: Dict[str, s
return results
def _load_backtest_data_df_compatibility(df: pd.DataFrame) -> pd.DataFrame:
"""
Compatibility support for older backtest data.
"""
df['open_date'] = pd.to_datetime(df['open_date'],
utc=True,
infer_datetime_format=True
)
df['close_date'] = pd.to_datetime(df['close_date'],
utc=True,
infer_datetime_format=True
)
# Compatibility support for pre short Columns
if 'is_short' not in df.columns:
df['is_short'] = False
if 'leverage' not in df.columns:
df['leverage'] = 1.0
if 'enter_tag' not in df.columns:
df['enter_tag'] = df['buy_tag']
df = df.drop(['buy_tag'], axis=1)
if 'max_stake_amount' not in df.columns:
df['max_stake_amount'] = df['stake_amount']
if 'orders' not in df.columns:
df['orders'] = None
return df
def load_backtest_data(filename: Union[Path, str], strategy: Optional[str] = None) -> pd.DataFrame:
"""
Load backtest data file.
@@ -269,24 +297,7 @@ def load_backtest_data(filename: Union[Path, str], strategy: Optional[str] = Non
data = data['strategy'][strategy]['trades']
df = pd.DataFrame(data)
if not df.empty:
df['open_date'] = pd.to_datetime(df['open_date'],
utc=True,
infer_datetime_format=True
)
df['close_date'] = pd.to_datetime(df['close_date'],
utc=True,
infer_datetime_format=True
)
# Compatibility support for pre short Columns
if 'is_short' not in df.columns:
df['is_short'] = 0
if 'leverage' not in df.columns:
df['leverage'] = 1.0
if 'enter_tag' not in df.columns:
df['enter_tag'] = df['buy_tag']
df = df.drop(['buy_tag'], axis=1)
if 'orders' not in df.columns:
df['orders'] = None
df = _load_backtest_data_df_compatibility(df)
else:
# old format - only with lists.
@@ -322,7 +333,7 @@ def analyze_trade_parallelism(results: pd.DataFrame, timeframe: str) -> pd.DataF
def evaluate_result_multi(results: pd.DataFrame, timeframe: str,
max_open_trades: int) -> pd.DataFrame:
max_open_trades: IntOrInf) -> pd.DataFrame:
"""
Find overlapping trades by expanding each trade once per period it was open
and then counting overlaps

View File

@@ -9,14 +9,17 @@ from collections import deque
from datetime import datetime, timezone
from typing import Any, Dict, List, Optional, Tuple
from pandas import DataFrame
from pandas import DataFrame, Timedelta, Timestamp, to_timedelta
from freqtrade.configuration import TimeRange
from freqtrade.constants import Config, ListPairsWithTimeframes, PairWithTimeframe
from freqtrade.constants import (FULL_DATAFRAME_THRESHOLD, Config, ListPairsWithTimeframes,
PairWithTimeframe)
from freqtrade.data.history import load_pair_history
from freqtrade.enums import CandleType, RPCMessageType, RunMode
from freqtrade.exceptions import ExchangeError, OperationalException
from freqtrade.exchange import Exchange, timeframe_to_seconds
from freqtrade.exchange.types import OrderBook
from freqtrade.misc import append_candles_to_dataframe
from freqtrade.rpc import RPCManager
from freqtrade.util import PeriodicCache
@@ -104,13 +107,15 @@ class DataProvider:
def _emit_df(
self,
pair_key: PairWithTimeframe,
dataframe: DataFrame
dataframe: DataFrame,
new_candle: bool
) -> None:
"""
Send this dataframe as an ANALYZED_DF message to RPC
:param pair_key: PairWithTimeframe tuple
:param data: Tuple containing the DataFrame and the datetime it was cached
:param dataframe: Dataframe to emit
:param new_candle: This is a new candle
"""
if self.__rpc:
self.__rpc.send_msg(
@@ -118,13 +123,18 @@ class DataProvider:
'type': RPCMessageType.ANALYZED_DF,
'data': {
'key': pair_key,
'df': dataframe,
'df': dataframe.tail(1),
'la': datetime.now(timezone.utc)
}
}
)
if new_candle:
self.__rpc.send_msg({
'type': RPCMessageType.NEW_CANDLE,
'data': pair_key,
})
def _add_external_df(
def _replace_external_df(
self,
pair: str,
dataframe: DataFrame,
@@ -150,6 +160,87 @@ class DataProvider:
self.__producer_pairs_df[producer_name][pair_key] = (dataframe, _last_analyzed)
logger.debug(f"External DataFrame for {pair_key} from {producer_name} added.")
def _add_external_df(
self,
pair: str,
dataframe: DataFrame,
last_analyzed: datetime,
timeframe: str,
candle_type: CandleType,
producer_name: str = "default"
) -> Tuple[bool, int]:
"""
Append a candle to the existing external dataframe. The incoming dataframe
must have at least 1 candle.
:param pair: pair to get the data for
:param timeframe: Timeframe to get data for
:param candle_type: Any of the enum CandleType (must match trading mode!)
:returns: False if the candle could not be appended, or the int number of missing candles.
"""
pair_key = (pair, timeframe, candle_type)
if dataframe.empty:
# The incoming dataframe must have at least 1 candle
return (False, 0)
if len(dataframe) >= FULL_DATAFRAME_THRESHOLD:
# This is likely a full dataframe
# Add the dataframe to the dataprovider
self._replace_external_df(
pair,
dataframe,
last_analyzed=last_analyzed,
timeframe=timeframe,
candle_type=candle_type,
producer_name=producer_name
)
return (True, 0)
if (producer_name not in self.__producer_pairs_df
or pair_key not in self.__producer_pairs_df[producer_name]):
# We don't have data from this producer yet,
# or we don't have data for this pair_key
# return False and 1000 for the full df
return (False, 1000)
existing_df, _ = self.__producer_pairs_df[producer_name][pair_key]
# CHECK FOR MISSING CANDLES
# Convert the timeframe to a timedelta for pandas
timeframe_delta: Timedelta = to_timedelta(timeframe)
local_last: Timestamp = existing_df.iloc[-1]['date'] # We want the last date from our copy
# We want the first date from the incoming
incoming_first: Timestamp = dataframe.iloc[0]['date']
# Remove existing candles that are newer than the incoming first candle
existing_df1 = existing_df[existing_df['date'] < incoming_first]
candle_difference = (incoming_first - local_last) / timeframe_delta
# If the difference divided by the timeframe is 1, then this
# is the candle we want and the incoming data isn't missing any.
# If the candle_difference is more than 1, that means
# we missed some candles between our data and the incoming
# so return False and candle_difference.
if candle_difference > 1:
return (False, int(candle_difference))
if existing_df1.empty:
appended_df = dataframe
else:
appended_df = append_candles_to_dataframe(existing_df1, dataframe)
# Everything is good, we appended
self._replace_external_df(
pair,
appended_df,
last_analyzed=last_analyzed,
timeframe=timeframe,
candle_type=candle_type,
producer_name=producer_name
)
return (True, 0)
def get_producer_df(
self,
pair: str,
@@ -193,7 +284,7 @@ class DataProvider:
def historic_ohlcv(
self,
pair: str,
timeframe: str = None,
timeframe: Optional[str] = None,
candle_type: str = ''
) -> DataFrame:
"""
@@ -245,7 +336,7 @@ class DataProvider:
def get_pair_dataframe(
self,
pair: str,
timeframe: str = None,
timeframe: Optional[str] = None,
candle_type: str = ''
) -> DataFrame:
"""
@@ -327,16 +418,14 @@ class DataProvider:
def refresh(self,
pairlist: ListPairsWithTimeframes,
helping_pairs: ListPairsWithTimeframes = None) -> None:
helping_pairs: Optional[ListPairsWithTimeframes] = None) -> None:
"""
Refresh data, called with each cycle
"""
if self._exchange is None:
raise OperationalException(NO_EXCHANGE_EXCEPTION)
if helping_pairs:
self._exchange.refresh_latest_ohlcv(pairlist + helping_pairs)
else:
self._exchange.refresh_latest_ohlcv(pairlist)
final_pairs = (pairlist + helping_pairs) if helping_pairs else pairlist
self._exchange.refresh_latest_ohlcv(final_pairs)
@property
def available_pairs(self) -> ListPairsWithTimeframes:
@@ -351,7 +440,7 @@ class DataProvider:
def ohlcv(
self,
pair: str,
timeframe: str = None,
timeframe: Optional[str] = None,
copy: bool = True,
candle_type: str = ''
) -> DataFrame:
@@ -399,7 +488,7 @@ class DataProvider:
except ExchangeError:
return {}
def orderbook(self, pair: str, maximum: int) -> Dict[str, List]:
def orderbook(self, pair: str, maximum: int) -> OrderBook:
"""
Fetch latest l2 orderbook data
Warning: Does a network request - so use with common sense.

110
freqtrade/data/entryexitanalysis.py Executable file → Normal file
View File

@@ -1,11 +1,12 @@
import logging
from pathlib import Path
from typing import List, Optional
import joblib
import pandas as pd
from tabulate import tabulate
from freqtrade.configuration import TimeRange
from freqtrade.constants import Config
from freqtrade.data.btanalysis import (get_latest_backtest_filename, load_backtest_data,
load_backtest_stats)
from freqtrade.exceptions import OperationalException
@@ -51,7 +52,7 @@ def _process_candles_and_indicators(pairlist, strategy_name, trades, signal_cand
return analysed_trades_dict
def _analyze_candles_and_indicators(pair, trades, signal_candles):
def _analyze_candles_and_indicators(pair, trades: pd.DataFrame, signal_candles: pd.DataFrame):
buyf = signal_candles
if len(buyf) > 0:
@@ -119,7 +120,7 @@ def _do_group_table_output(bigdf, glist):
else:
agg_mask = {'profit_abs': ['count', 'sum', 'median', 'mean'],
'profit_ratio': ['sum', 'median', 'mean']}
'profit_ratio': ['median', 'mean', 'sum']}
agg_cols = ['num_buys', 'profit_abs_sum', 'profit_abs_median',
'profit_abs_mean', 'median_profit_pct', 'mean_profit_pct',
'total_profit_pct']
@@ -140,6 +141,12 @@ def _do_group_table_output(bigdf, glist):
# 4: profit summaries grouped by pair, enter_ and exit_tag (this can get quite large)
if g == "4":
group_mask = ['pair', 'enter_reason', 'exit_reason']
# 5: profit summaries grouped by exit_tag
if g == "5":
group_mask = ['exit_reason']
sortcols = ['exit_reason']
if group_mask:
new = bigdf.groupby(group_mask).agg(agg_mask).reset_index()
new.columns = group_mask + agg_cols
@@ -152,37 +159,55 @@ def _do_group_table_output(bigdf, glist):
logger.warning("Invalid group mask specified.")
def _print_results(analysed_trades, stratname, analysis_groups,
enter_reason_list, exit_reason_list,
indicator_list, columns=None):
if columns is None:
columns = ['pair', 'open_date', 'close_date', 'profit_abs', 'enter_reason', 'exit_reason']
def _select_rows_within_dates(df, timerange=None, df_date_col: str = 'date'):
if timerange:
if timerange.starttype == 'date':
df = df.loc[(df[df_date_col] >= timerange.startdt)]
if timerange.stoptype == 'date':
df = df.loc[(df[df_date_col] < timerange.stopdt)]
return df
bigdf = pd.DataFrame()
def _select_rows_by_tags(df, enter_reason_list, exit_reason_list):
if enter_reason_list and "all" not in enter_reason_list:
df = df.loc[(df['enter_reason'].isin(enter_reason_list))]
if exit_reason_list and "all" not in exit_reason_list:
df = df.loc[(df['exit_reason'].isin(exit_reason_list))]
return df
def prepare_results(analysed_trades, stratname,
enter_reason_list, exit_reason_list,
timerange=None):
res_df = pd.DataFrame()
for pair, trades in analysed_trades[stratname].items():
bigdf = pd.concat([bigdf, trades], ignore_index=True)
res_df = pd.concat([res_df, trades], ignore_index=True)
if bigdf.shape[0] > 0 and ('enter_reason' in bigdf.columns):
res_df = _select_rows_within_dates(res_df, timerange)
if res_df is not None and res_df.shape[0] > 0 and ('enter_reason' in res_df.columns):
res_df = _select_rows_by_tags(res_df, enter_reason_list, exit_reason_list)
return res_df
def print_results(res_df, analysis_groups, indicator_list):
if res_df.shape[0] > 0:
if analysis_groups:
_do_group_table_output(bigdf, analysis_groups)
if enter_reason_list and "all" not in enter_reason_list:
bigdf = bigdf.loc[(bigdf['enter_reason'].isin(enter_reason_list))]
if exit_reason_list and "all" not in exit_reason_list:
bigdf = bigdf.loc[(bigdf['exit_reason'].isin(exit_reason_list))]
_do_group_table_output(res_df, analysis_groups)
if "all" in indicator_list:
print(bigdf)
print(res_df)
elif indicator_list is not None:
available_inds = []
for ind in indicator_list:
if ind in bigdf:
if ind in res_df:
available_inds.append(ind)
ilist = ["pair", "enter_reason", "exit_reason"] + available_inds
_print_table(bigdf[ilist], sortcols=['exit_reason'], show_index=False)
_print_table(res_df[ilist], sortcols=['exit_reason'], show_index=False)
else:
print("\\_ No trades to show")
print("\\No trades to show")
def _print_table(df, sortcols=None, show_index=False):
@@ -201,27 +226,34 @@ def _print_table(df, sortcols=None, show_index=False):
)
def process_entry_exit_reasons(backtest_dir: Path,
pairlist: List[str],
analysis_groups: Optional[List[str]] = ["0", "1", "2"],
enter_reason_list: Optional[List[str]] = ["all"],
exit_reason_list: Optional[List[str]] = ["all"],
indicator_list: Optional[List[str]] = []):
def process_entry_exit_reasons(config: Config):
try:
backtest_stats = load_backtest_stats(backtest_dir)
analysis_groups = config.get('analysis_groups', [])
enter_reason_list = config.get('enter_reason_list', ["all"])
exit_reason_list = config.get('exit_reason_list', ["all"])
indicator_list = config.get('indicator_list', [])
timerange = TimeRange.parse_timerange(None if config.get(
'timerange') is None else str(config.get('timerange')))
backtest_stats = load_backtest_stats(config['exportfilename'])
for strategy_name, results in backtest_stats['strategy'].items():
trades = load_backtest_data(backtest_dir, strategy_name)
trades = load_backtest_data(config['exportfilename'], strategy_name)
if not trades.empty:
signal_candles = _load_signal_candles(backtest_dir)
analysed_trades_dict = _process_candles_and_indicators(pairlist, strategy_name,
trades, signal_candles)
_print_results(analysed_trades_dict,
strategy_name,
analysis_groups,
enter_reason_list,
exit_reason_list,
indicator_list)
signal_candles = _load_signal_candles(config['exportfilename'])
analysed_trades_dict = _process_candles_and_indicators(
config['exchange']['pair_whitelist'], strategy_name,
trades, signal_candles)
res_df = prepare_results(analysed_trades_dict, strategy_name,
enter_reason_list, exit_reason_list,
timerange=timerange)
print_results(res_df,
analysis_groups,
indicator_list)
except ValueError as e:
raise OperationalException(e) from e

View File

@@ -28,8 +28,8 @@ def load_pair_history(pair: str,
fill_up_missing: bool = True,
drop_incomplete: bool = False,
startup_candles: int = 0,
data_format: str = None,
data_handler: IDataHandler = None,
data_format: Optional[str] = None,
data_handler: Optional[IDataHandler] = None,
candle_type: CandleType = CandleType.SPOT
) -> DataFrame:
"""
@@ -69,7 +69,7 @@ def load_data(datadir: Path,
fail_without_data: bool = False,
data_format: str = 'json',
candle_type: CandleType = CandleType.SPOT,
user_futures_funding_rate: int = None,
user_futures_funding_rate: Optional[int] = None,
) -> Dict[str, DataFrame]:
"""
Load ohlcv history data for a list of pairs.
@@ -116,7 +116,7 @@ def refresh_data(*, datadir: Path,
timeframe: str,
pairs: List[str],
exchange: Exchange,
data_format: str = None,
data_format: Optional[str] = None,
timerange: Optional[TimeRange] = None,
candle_type: CandleType,
) -> None:
@@ -189,7 +189,7 @@ def _download_pair_history(pair: str, *,
timeframe: str = '5m',
process: str = '',
new_pairs_days: int = 30,
data_handler: IDataHandler = None,
data_handler: Optional[IDataHandler] = None,
timerange: Optional[TimeRange] = None,
candle_type: CandleType,
erase: bool = False,
@@ -272,7 +272,7 @@ def refresh_backtest_ohlcv_data(exchange: Exchange, pairs: List[str], timeframes
datadir: Path, trading_mode: str,
timerange: Optional[TimeRange] = None,
new_pairs_days: int = 30, erase: bool = False,
data_format: str = None,
data_format: Optional[str] = None,
prepend: bool = False,
) -> List[str]:
"""

View File

@@ -308,7 +308,7 @@ class IDataHandler(ABC):
timerange=timerange_startup,
candle_type=candle_type
)
if self._check_empty_df(pairdf, pair, timeframe, candle_type, warn_no_data, True):
if self._check_empty_df(pairdf, pair, timeframe, candle_type, warn_no_data):
return pairdf
else:
enddate = pairdf.iloc[-1]['date']
@@ -316,7 +316,7 @@ class IDataHandler(ABC):
if timerange_startup:
self._validate_pairdata(pair, pairdf, timeframe, candle_type, timerange_startup)
pairdf = trim_dataframe(pairdf, timerange_startup)
if self._check_empty_df(pairdf, pair, timeframe, candle_type, warn_no_data):
if self._check_empty_df(pairdf, pair, timeframe, candle_type, warn_no_data, True):
return pairdf
# incomplete candles should only be dropped if we didn't trim the end beforehand.
@@ -374,6 +374,21 @@ class IDataHandler(ABC):
logger.warning(f"{pair}, {candle_type}, {timeframe}, "
f"data ends at {pairdata.iloc[-1]['date']:%Y-%m-%d %H:%M:%S}")
def rename_futures_data(
self, pair: str, new_pair: str, timeframe: str, candle_type: CandleType):
"""
Temporary method to migrate data from old naming to new naming (BTC/USDT -> BTC/USDT:USDT)
Only used for binance to support the binance futures naming unification.
"""
file_old = self._pair_data_filename(self._datadir, pair, timeframe, candle_type)
file_new = self._pair_data_filename(self._datadir, new_pair, timeframe, candle_type)
# print(file_old, file_new)
if file_new.exists():
logger.warning(f"{file_new} exists already, can't migrate {pair}.")
return
file_old.rename(file_new)
def get_datahandlerclass(datatype: str) -> Type[IDataHandler]:
"""
@@ -403,8 +418,8 @@ def get_datahandlerclass(datatype: str) -> Type[IDataHandler]:
raise ValueError(f"No datahandler for datatype {datatype} available.")
def get_datahandler(datadir: Path, data_format: str = None,
data_handler: IDataHandler = None) -> IDataHandler:
def get_datahandler(datadir: Path, data_format: Optional[str] = None,
data_handler: Optional[IDataHandler] = None) -> IDataHandler:
"""
:param datadir: Folder to save data
:param data_format: dataformat to use

View File

@@ -1,4 +1,6 @@
import logging
import math
from datetime import datetime
from typing import Dict, Tuple
import numpy as np
@@ -190,3 +192,119 @@ def calculate_cagr(days_passed: int, starting_balance: float, final_balance: flo
:return: CAGR
"""
return (final_balance / starting_balance) ** (1 / (days_passed / 365)) - 1
def calculate_expectancy(trades: pd.DataFrame) -> float:
"""
Calculate expectancy
:param trades: DataFrame containing trades (requires columns close_date and profit_abs)
:return: expectancy
"""
if len(trades) == 0:
return 0
expectancy = 1
profit_sum = trades.loc[trades['profit_abs'] > 0, 'profit_abs'].sum()
loss_sum = abs(trades.loc[trades['profit_abs'] < 0, 'profit_abs'].sum())
nb_win_trades = len(trades.loc[trades['profit_abs'] > 0])
nb_loss_trades = len(trades.loc[trades['profit_abs'] < 0])
if (nb_win_trades > 0) and (nb_loss_trades > 0):
average_win = profit_sum / nb_win_trades
average_loss = loss_sum / nb_loss_trades
risk_reward_ratio = average_win / average_loss
winrate = nb_win_trades / len(trades)
expectancy = ((1 + risk_reward_ratio) * winrate) - 1
elif nb_win_trades == 0:
expectancy = 0
return expectancy
def calculate_sortino(trades: pd.DataFrame, min_date: datetime, max_date: datetime,
starting_balance: float) -> float:
"""
Calculate sortino
:param trades: DataFrame containing trades (requires columns profit_abs)
:return: sortino
"""
if (len(trades) == 0) or (min_date is None) or (max_date is None) or (min_date == max_date):
return 0
total_profit = trades['profit_abs'] / starting_balance
days_period = max(1, (max_date - min_date).days)
expected_returns_mean = total_profit.sum() / days_period
down_stdev = np.std(trades.loc[trades['profit_abs'] < 0, 'profit_abs'] / starting_balance)
if down_stdev != 0 and not np.isnan(down_stdev):
sortino_ratio = expected_returns_mean / down_stdev * np.sqrt(365)
else:
# Define high (negative) sortino ratio to be clear that this is NOT optimal.
sortino_ratio = -100
# print(expected_returns_mean, down_stdev, sortino_ratio)
return sortino_ratio
def calculate_sharpe(trades: pd.DataFrame, min_date: datetime, max_date: datetime,
starting_balance: float) -> float:
"""
Calculate sharpe
:param trades: DataFrame containing trades (requires column profit_abs)
:return: sharpe
"""
if (len(trades) == 0) or (min_date is None) or (max_date is None) or (min_date == max_date):
return 0
total_profit = trades['profit_abs'] / starting_balance
days_period = max(1, (max_date - min_date).days)
expected_returns_mean = total_profit.sum() / days_period
up_stdev = np.std(total_profit)
if up_stdev != 0:
sharp_ratio = expected_returns_mean / up_stdev * np.sqrt(365)
else:
# Define high (negative) sharpe ratio to be clear that this is NOT optimal.
sharp_ratio = -100
# print(expected_returns_mean, up_stdev, sharp_ratio)
return sharp_ratio
def calculate_calmar(trades: pd.DataFrame, min_date: datetime, max_date: datetime,
starting_balance: float) -> float:
"""
Calculate calmar
:param trades: DataFrame containing trades (requires columns close_date and profit_abs)
:return: calmar
"""
if (len(trades) == 0) or (min_date is None) or (max_date is None) or (min_date == max_date):
return 0
total_profit = trades['profit_abs'].sum() / starting_balance
days_period = max(1, (max_date - min_date).days)
# adding slippage of 0.1% per trade
# total_profit = total_profit - 0.0005
expected_returns_mean = total_profit / days_period * 100
# calculate max drawdown
try:
_, _, _, _, _, max_drawdown = calculate_max_drawdown(
trades, value_col="profit_abs", starting_balance=starting_balance
)
except ValueError:
max_drawdown = 0
if max_drawdown != 0:
calmar_ratio = expected_returns_mean / max_drawdown * math.sqrt(365)
else:
# Define high (negative) calmar ratio to be clear that this is NOT optimal.
calmar_ratio = -100
# print(expected_returns_mean, max_drawdown, calmar_ratio)
return calmar_ratio

View File

@@ -195,7 +195,7 @@ class Edge:
def stake_amount(self, pair: str, free_capital: float,
total_capital: float, capital_in_trade: float) -> float:
stoploss = self.stoploss(pair)
stoploss = self.get_stoploss(pair)
available_capital = (total_capital + capital_in_trade) * self._capital_ratio
allowed_capital_at_risk = available_capital * self._allowed_risk
max_position_size = abs(allowed_capital_at_risk / stoploss)
@@ -214,7 +214,7 @@ class Edge:
)
return round(position_size, 15)
def stoploss(self, pair: str) -> float:
def get_stoploss(self, pair: str) -> float:
if pair in self._cached_pairs:
return self._cached_pairs[pair].stoploss
else:

View File

@@ -6,7 +6,8 @@ from freqtrade.enums.exittype import ExitType
from freqtrade.enums.hyperoptstate import HyperoptState
from freqtrade.enums.marginmode import MarginMode
from freqtrade.enums.ordertypevalue import OrderTypeValues
from freqtrade.enums.rpcmessagetype import RPCMessageType, RPCRequestType
from freqtrade.enums.pricetype import PriceType
from freqtrade.enums.rpcmessagetype import NO_ECHO_MESSAGES, RPCMessageType, RPCRequestType
from freqtrade.enums.runmode import NON_UTIL_MODES, OPTIMIZE_MODES, TRADING_MODES, RunMode
from freqtrade.enums.signaltype import SignalDirection, SignalTagType, SignalType
from freqtrade.enums.state import State

View File

@@ -0,0 +1,8 @@
from enum import Enum
class PriceType(str, Enum):
"""Enum to distinguish possible trigger prices for stoplosses"""
LAST = "last"
MARK = "mark"
INDEX = "index"

View File

@@ -21,6 +21,7 @@ class RPCMessageType(str, Enum):
WHITELIST = 'whitelist'
ANALYZED_DF = 'analyzed_df'
NEW_CANDLE = 'new_candle'
def __repr__(self):
return self.value
@@ -35,3 +36,6 @@ class RPCRequestType(str, Enum):
WHITELIST = 'whitelist'
ANALYZED_DF = 'analyzed_df'
NO_ECHO_MESSAGES = (RPCMessageType.ANALYZED_DF, RPCMessageType.WHITELIST, RPCMessageType.NEW_CANDLE)

View File

@@ -3,7 +3,6 @@
from freqtrade.exchange.common import remove_credentials, MAP_EXCHANGE_CHILDCLASS
from freqtrade.exchange.exchange import Exchange
# isort: on
from freqtrade.exchange.bibox import Bibox
from freqtrade.exchange.binance import Binance
from freqtrade.exchange.bitpanda import Bitpanda
from freqtrade.exchange.bittrex import Bittrex
@@ -18,7 +17,7 @@ from freqtrade.exchange.exchange_utils import (amount_to_contract_precision, amo
timeframe_to_next_date, timeframe_to_prev_date,
timeframe_to_seconds, validate_exchange,
validate_exchanges)
from freqtrade.exchange.gateio import Gateio
from freqtrade.exchange.gate import Gate
from freqtrade.exchange.hitbtc import Hitbtc
from freqtrade.exchange.huobi import Huobi
from freqtrade.exchange.kraken import Kraken

View File

@@ -1,28 +0,0 @@
""" Bibox exchange subclass """
import logging
from typing import Dict
from freqtrade.exchange import Exchange
logger = logging.getLogger(__name__)
class Bibox(Exchange):
"""
Bibox exchange class. Contains adjustments needed for Freqtrade to work
with this exchange.
Please note that this exchange is not included in the list of exchanges
officially supported by the Freqtrade development team. So some features
may still not work as expected.
"""
# fetchCurrencies API point requires authentication for Bibox,
# so switch it off for Freqtrade load_markets()
@property
def _ccxt_config(self) -> Dict:
# Parameters to add directly to ccxt sync/async initialization.
config = {"has": {"fetchCurrencies": False}}
config.update(super()._ccxt_config)
return config

View File

@@ -7,11 +7,11 @@ from typing import Dict, List, Optional, Tuple
import arrow
import ccxt
from freqtrade.enums import CandleType, MarginMode, TradingMode
from freqtrade.enums import CandleType, MarginMode, PriceType, TradingMode
from freqtrade.exceptions import DDosProtection, OperationalException, TemporaryError
from freqtrade.exchange import Exchange
from freqtrade.exchange.common import retrier
from freqtrade.exchange.types import Tickers
from freqtrade.exchange.types import OHLCVResponse, Tickers
from freqtrade.misc import deep_merge_dicts, json_load
@@ -28,11 +28,16 @@ class Binance(Exchange):
"trades_pagination": "id",
"trades_pagination_arg": "fromId",
"l2_limit_range": [5, 10, 20, 50, 100, 500, 1000],
"ccxt_futures_name": "future"
}
_ft_has_futures: Dict = {
"stoploss_order_types": {"limit": "limit", "market": "market"},
"stoploss_order_types": {"limit": "stop", "market": "stop_market"},
"tickers_have_price": False,
"floor_leverage": True,
"stop_price_type_field": "workingType",
"stop_price_type_value_mapping": {
PriceType.LAST: "CONTRACT_PRICE",
PriceType.MARK: "MARK_PRICE",
},
}
_supported_trading_mode_margin_pairs: List[Tuple[TradingMode, MarginMode]] = [
@@ -78,33 +83,9 @@ class Binance(Exchange):
raise DDosProtection(e) from e
except (ccxt.NetworkError, ccxt.ExchangeError) as e:
raise TemporaryError(
f'Could not set leverage due to {e.__class__.__name__}. Message: {e}') from e
except ccxt.BaseError as e:
raise OperationalException(e) from e
f'Error in additional_exchange_init due to {e.__class__.__name__}. Message: {e}'
) from e
@retrier
def _set_leverage(
self,
leverage: float,
pair: Optional[str] = None,
trading_mode: Optional[TradingMode] = None
):
"""
Set's the leverage before making a trade, in order to not
have the same leverage on every trade
"""
trading_mode = trading_mode or self.trading_mode
if self._config['dry_run'] or trading_mode != TradingMode.FUTURES:
return
try:
self._api.set_leverage(symbol=pair, leverage=round(leverage))
except ccxt.DDoSProtection as e:
raise DDosProtection(e) from e
except (ccxt.NetworkError, ccxt.ExchangeError) as e:
raise TemporaryError(
f'Could not set leverage due to {e.__class__.__name__}. Message: {e}') from e
except ccxt.BaseError as e:
raise OperationalException(e) from e
@@ -112,7 +93,7 @@ class Binance(Exchange):
since_ms: int, candle_type: CandleType,
is_new_pair: bool = False, raise_: bool = False,
until_ms: Optional[int] = None
) -> Tuple[str, str, str, List]:
) -> OHLCVResponse:
"""
Overwrite to introduce "fast new pair" functionality by detecting the pair's listing date
Does not work for other exchanges, which don't return the earliest data when called with "0"
@@ -150,6 +131,7 @@ class Binance(Exchange):
is_short: bool,
amount: float,
stake_amount: float,
leverage: float,
wallet_balance: float, # Or margin balance
mm_ex_1: float = 0.0, # (Binance) Cross only
upnl_ex_1: float = 0.0, # (Binance) Cross only
@@ -159,11 +141,12 @@ class Binance(Exchange):
MARGIN: https://www.binance.com/en/support/faq/f6b010588e55413aa58b7d63ee0125ed
PERPETUAL: https://www.binance.com/en/support/faq/b3c689c1f50a44cabb3a84e663b81d93
:param exchange_name:
:param pair: Pair to calculate liquidation price for
:param open_rate: Entry price of position
:param is_short: True if the trade is a short, false otherwise
:param amount: Absolute value of position size incl. leverage (in base currency)
:param stake_amount: Stake amount - Collateral in settle currency.
:param leverage: Leverage used for this position.
:param trading_mode: SPOT, MARGIN, FUTURES, etc.
:param margin_mode: Either ISOLATED or CROSS
:param wallet_balance: Amount of margin_mode in the wallet being used to trade

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,16 @@
""" Bybit exchange subclass """
import logging
from typing import Dict, List, Tuple
from datetime import datetime
from typing import Any, Dict, List, Optional, Tuple
from freqtrade.enums import MarginMode, TradingMode
import ccxt
from freqtrade.constants import BuySell
from freqtrade.enums import MarginMode, PriceType, TradingMode
from freqtrade.exceptions import DDosProtection, OperationalException, TemporaryError
from freqtrade.exchange import Exchange
from freqtrade.exchange.common import retrier
from freqtrade.exchange.exchange_utils import timeframe_to_msecs
logger = logging.getLogger(__name__)
@@ -21,17 +28,27 @@ class Bybit(Exchange):
_ft_has: Dict = {
"ohlcv_candle_limit": 1000,
"ccxt_futures_name": "linear",
"ohlcv_has_history": False,
}
_ft_has_futures: Dict = {
"ohlcv_candle_limit": 200,
"ohlcv_has_history": True,
"mark_ohlcv_timeframe": "4h",
"funding_fee_timeframe": "8h",
"stoploss_on_exchange": True,
"stoploss_order_types": {"limit": "limit", "market": "market"},
"stop_price_type_field": "triggerBy",
"stop_price_type_value_mapping": {
PriceType.LAST: "LastPrice",
PriceType.MARK: "MarkPrice",
PriceType.INDEX: "IndexPrice",
},
}
_supported_trading_mode_margin_pairs: List[Tuple[TradingMode, MarginMode]] = [
# TradingMode.SPOT always supported and not required in this list
# (TradingMode.FUTURES, MarginMode.CROSS),
# (TradingMode.FUTURES, MarginMode.ISOLATED)
(TradingMode.FUTURES, MarginMode.ISOLATED)
]
@property
@@ -47,3 +64,158 @@ class Bybit(Exchange):
})
config.update(super()._ccxt_config)
return config
def market_is_future(self, market: Dict[str, Any]) -> bool:
main = super().market_is_future(market)
# For ByBit, we'll only support USDT markets for now.
return (
main and market['settle'] == 'USDT'
)
@retrier
def additional_exchange_init(self) -> None:
"""
Additional exchange initialization logic.
.api will be available at this point.
Must be overridden in child methods if required.
"""
try:
if self.trading_mode == TradingMode.FUTURES and not self._config['dry_run']:
position_mode = self._api.set_position_mode(False)
self._log_exchange_response('set_position_mode', position_mode)
except ccxt.DDoSProtection as e:
raise DDosProtection(e) from e
except (ccxt.NetworkError, ccxt.ExchangeError) as e:
raise TemporaryError(
f'Error in additional_exchange_init due to {e.__class__.__name__}. Message: {e}'
) from e
except ccxt.BaseError as e:
raise OperationalException(e) from e
async def _fetch_funding_rate_history(
self,
pair: str,
timeframe: str,
limit: int,
since_ms: Optional[int] = None,
) -> List[List]:
"""
Fetch funding rate history
Necessary workaround until https://github.com/ccxt/ccxt/issues/15990 is fixed.
"""
params = {}
if since_ms:
until = since_ms + (timeframe_to_msecs(timeframe) * self._ft_has['ohlcv_candle_limit'])
params.update({'until': until})
# Funding rate
data = await self._api_async.fetch_funding_rate_history(
pair, since=since_ms,
params=params)
# Convert funding rate to candle pattern
data = [[x['timestamp'], x['fundingRate'], 0, 0, 0, 0] for x in data]
return data
def _lev_prep(self, pair: str, leverage: float, side: BuySell):
if self.trading_mode != TradingMode.SPOT:
params = {'leverage': leverage}
self.set_margin_mode(pair, self.margin_mode, accept_fail=True, params=params)
self._set_leverage(leverage, pair, accept_fail=True)
def _get_params(
self,
side: BuySell,
ordertype: str,
leverage: float,
reduceOnly: bool,
time_in_force: str = 'GTC',
) -> Dict:
params = super()._get_params(
side=side,
ordertype=ordertype,
leverage=leverage,
reduceOnly=reduceOnly,
time_in_force=time_in_force,
)
if self.trading_mode == TradingMode.FUTURES and self.margin_mode:
params['position_idx'] = 0
return params
def dry_run_liquidation_price(
self,
pair: str,
open_rate: float, # Entry price of position
is_short: bool,
amount: float,
stake_amount: float,
leverage: float,
wallet_balance: float, # Or margin balance
mm_ex_1: float = 0.0, # (Binance) Cross only
upnl_ex_1: float = 0.0, # (Binance) Cross only
) -> Optional[float]:
"""
Important: Must be fetching data from cached values as this is used by backtesting!
PERPETUAL:
bybit:
https://www.bybithelp.com/HelpCenterKnowledge/bybitHC_Article?language=en_US&id=000001067
Long:
Liquidation Price = (
Entry Price * (1 - Initial Margin Rate + Maintenance Margin Rate)
- Extra Margin Added/ Contract)
Short:
Liquidation Price = (
Entry Price * (1 + Initial Margin Rate - Maintenance Margin Rate)
+ Extra Margin Added/ Contract)
Implementation Note: Extra margin is currently not used.
:param pair: Pair to calculate liquidation price for
:param open_rate: Entry price of position
:param is_short: True if the trade is a short, false otherwise
:param amount: Absolute value of position size incl. leverage (in base currency)
:param stake_amount: Stake amount - Collateral in settle currency.
:param leverage: Leverage used for this position.
:param trading_mode: SPOT, MARGIN, FUTURES, etc.
:param margin_mode: Either ISOLATED or CROSS
:param wallet_balance: Amount of margin_mode in the wallet being used to trade
Cross-Margin Mode: crossWalletBalance
Isolated-Margin Mode: isolatedWalletBalance
"""
market = self.markets[pair]
mm_ratio, _ = self.get_maintenance_ratio_and_amt(pair, stake_amount)
if self.trading_mode == TradingMode.FUTURES and self.margin_mode == MarginMode.ISOLATED:
if market['inverse']:
raise OperationalException(
"Freqtrade does not yet support inverse contracts")
initial_margin_rate = 1 / leverage
# See docstring - ignores extra margin!
if is_short:
return open_rate * (1 + initial_margin_rate - mm_ratio)
else:
return open_rate * (1 - initial_margin_rate + mm_ratio)
else:
raise OperationalException(
"Freqtrade only supports isolated futures for leverage trading")
def get_funding_fees(
self, pair: str, amount: float, is_short: bool, open_date: datetime) -> float:
"""
Fetch funding fees, either from the exchange (live) or calculates them
based on funding rate/mark price history
:param pair: The quote/base pair of the trade
:param is_short: trade direction
:param amount: Trade amount
:param open_date: Open date of the trade
:return: funding fee since open_date
:raises: ExchangeError if something goes wrong.
"""
# Bybit does not provide "applied" funding fees per position.
if self.trading_mode == TradingMode.FUTURES:
return self._fetch_and_calculate_funding_fees(
pair, amount, is_short, open_date)
return 0.0

View File

@@ -46,13 +46,13 @@ MAP_EXCHANGE_CHILDCLASS = {
'binanceje': 'binance',
'binanceusdm': 'binance',
'okex': 'okx',
'gate': 'gateio',
'gateio': 'gate',
}
SUPPORTED_EXCHANGES = [
'binance',
'bittrex',
'gateio',
'gate',
'huobi',
'kraken',
'okx',

View File

@@ -3,11 +3,11 @@
Cryptocurrency Exchanges support
"""
import asyncio
import http
import inspect
import logging
from copy import deepcopy
from datetime import datetime, timedelta, timezone
from math import floor
from threading import Lock
from typing import Any, Coroutine, Dict, List, Literal, Optional, Tuple, Union
@@ -21,9 +21,10 @@ from pandas import DataFrame, concat
from freqtrade.constants import (DEFAULT_AMOUNT_RESERVE_PERCENT, NON_OPEN_EXCHANGE_STATES, BidAsk,
BuySell, Config, EntryExit, ListPairsWithTimeframes, MakerTaker,
PairWithTimeframe)
OBLiteral, PairWithTimeframe)
from freqtrade.data.converter import clean_ohlcv_dataframe, ohlcv_to_dataframe, trades_dict_to_list
from freqtrade.enums import OPTIMIZE_MODES, CandleType, MarginMode, TradingMode
from freqtrade.enums.pricetype import PriceType
from freqtrade.exceptions import (DDosProtection, ExchangeError, InsufficientFundsError,
InvalidOrderException, OperationalException, PricingError,
RetryableOrderError, TemporaryError)
@@ -36,7 +37,7 @@ from freqtrade.exchange.exchange_utils import (CcxtModuleType, amount_to_contrac
price_to_precision, timeframe_to_minutes,
timeframe_to_msecs, timeframe_to_next_date,
timeframe_to_prev_date, timeframe_to_seconds)
from freqtrade.exchange.types import Ticker, Tickers
from freqtrade.exchange.types import OHLCVResponse, OrderBook, Ticker, Tickers
from freqtrade.misc import (chunks, deep_merge_dicts, file_dump_json, file_load_json,
safe_value_fallback2)
from freqtrade.plugins.pairlist.pairlist_helpers import expand_pairlist
@@ -45,12 +46,6 @@ from freqtrade.plugins.pairlist.pairlist_helpers import expand_pairlist
logger = logging.getLogger(__name__)
# Workaround for adding samesite support to pre 3.8 python
# Only applies to python3.7, and only on certain exchanges (kraken)
# Replicates the fix from starlette (which is actually causing this problem)
http.cookies.Morsel._reserved["samesite"] = "SameSite" # type: ignore
class Exchange:
# Parameters to add directly to buy/sell calls (like agreeing to trading agreement)
@@ -474,7 +469,7 @@ class Exchange:
try:
if self._api_async:
self.loop.run_until_complete(
self._api_async.load_markets(reload=reload))
self._api_async.load_markets(reload=reload, params={}))
except (asyncio.TimeoutError, ccxt.BaseError) as e:
logger.warning('Could not load async markets. Reason: %s', e)
@@ -483,7 +478,7 @@ class Exchange:
def _load_markets(self) -> None:
""" Initialize markets both sync and async """
try:
self._markets = self._api.load_markets()
self._markets = self._api.load_markets(params={})
self._load_async_markets()
self._last_markets_refresh = arrow.utcnow().int_timestamp
if self._ft_has['needs_trading_fees']:
@@ -501,7 +496,7 @@ class Exchange:
return None
logger.debug("Performing scheduled market reload..")
try:
self._markets = self._api.load_markets(reload=True)
self._markets = self._api.load_markets(reload=True, params={})
# Also reload async markets to avoid issues with newly listed pairs
self._load_async_markets(reload=True)
self._last_markets_refresh = arrow.utcnow().int_timestamp
@@ -606,12 +601,27 @@ class Exchange:
if not self.exchange_has('createMarketOrder'):
raise OperationalException(
f'Exchange {self.name} does not support market orders.')
self.validate_stop_ordertypes(order_types)
def validate_stop_ordertypes(self, order_types: Dict) -> None:
"""
Validate stoploss order types
"""
if (order_types.get("stoploss_on_exchange")
and not self._ft_has.get("stoploss_on_exchange", False)):
raise OperationalException(
f'On exchange stoploss is not supported for {self.name}.'
)
if self.trading_mode == TradingMode.FUTURES:
price_mapping = self._ft_has.get('stop_price_type_value_mapping', {}).keys()
if (
order_types.get("stoploss_on_exchange", False) is True
and 'stoploss_price_type' in order_types
and order_types['stoploss_price_type'] not in price_mapping
):
raise OperationalException(
f'On exchange stoploss price type is not supported for {self.name}.'
)
def validate_pricing(self, pricing: Dict) -> None:
if pricing.get('use_order_book', False) and not self.exchange_has('fetchL2OrderBook'):
@@ -682,7 +692,7 @@ class Exchange:
f"Freqtrade does not support {mm_value} {trading_mode.value} on {self.name}"
)
def get_option(self, param: str, default: Any = None) -> Any:
def get_option(self, param: str, default: Optional[Any] = None) -> Any:
"""
Get parameter value from _ft_has
"""
@@ -840,7 +850,7 @@ class Exchange:
'remaining': _amount,
'datetime': arrow.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ'),
'timestamp': arrow.utcnow().int_timestamp * 1000,
'status': "closed" if ordertype == "market" and not stop_loss else "open",
'status': "open",
'fee': None,
'info': {},
'leverage': leverage
@@ -850,20 +860,33 @@ class Exchange:
dry_order["stopPrice"] = dry_order["price"]
# Workaround to avoid filling stoploss orders immediately
dry_order["ft_order_type"] = "stoploss"
orderbook: Optional[OrderBook] = None
if self.exchange_has('fetchL2OrderBook'):
orderbook = self.fetch_l2_order_book(pair, 20)
if ordertype == "limit" and orderbook:
# Allow a 3% price difference
allowed_diff = 0.03
if self._dry_is_price_crossed(pair, side, rate, orderbook, allowed_diff):
logger.info(
f"Converted order {pair} to market order due to price {rate} crossing spread "
f"by more than {allowed_diff:.2%}.")
dry_order["type"] = "market"
if dry_order["type"] == "market" and not dry_order.get("ft_order_type"):
# Update market order pricing
average = self.get_dry_market_fill_price(pair, side, amount, rate)
average = self.get_dry_market_fill_price(pair, side, amount, rate, orderbook)
dry_order.update({
'average': average,
'filled': _amount,
'remaining': 0.0,
'status': "closed",
'cost': (dry_order['amount'] * average) / leverage
})
# market orders will always incurr taker fees
dry_order = self.add_dry_order_fee(pair, dry_order, 'taker')
dry_order = self.check_dry_limit_order_filled(dry_order, immediate=True)
dry_order = self.check_dry_limit_order_filled(
dry_order, immediate=True, orderbook=orderbook)
self._dry_run_open_orders[dry_order["id"]] = dry_order
# Copy order and close it - so the returned order is open unless it's a market order
@@ -885,20 +908,22 @@ class Exchange:
})
return dry_order
def get_dry_market_fill_price(self, pair: str, side: str, amount: float, rate: float) -> float:
def get_dry_market_fill_price(self, pair: str, side: str, amount: float, rate: float,
orderbook: Optional[OrderBook]) -> float:
"""
Get the market order fill price based on orderbook interpolation
"""
if self.exchange_has('fetchL2OrderBook'):
ob = self.fetch_l2_order_book(pair, 20)
ob_type = 'asks' if side == 'buy' else 'bids'
if not orderbook:
orderbook = self.fetch_l2_order_book(pair, 20)
ob_type: OBLiteral = 'asks' if side == 'buy' else 'bids'
slippage = 0.05
max_slippage_val = rate * ((1 + slippage) if side == 'buy' else (1 - slippage))
remaining_amount = amount
filled_amount = 0.0
book_entry_price = 0.0
for book_entry in ob[ob_type]:
for book_entry in orderbook[ob_type]:
book_entry_price = book_entry[0]
book_entry_coin_volume = book_entry[1]
if remaining_amount > 0:
@@ -926,20 +951,20 @@ class Exchange:
return rate
def _is_dry_limit_order_filled(self, pair: str, side: str, limit: float) -> bool:
def _dry_is_price_crossed(self, pair: str, side: str, limit: float,
orderbook: Optional[OrderBook] = None, offset: float = 0.0) -> bool:
if not self.exchange_has('fetchL2OrderBook'):
return True
ob = self.fetch_l2_order_book(pair, 1)
if not orderbook:
orderbook = self.fetch_l2_order_book(pair, 1)
try:
if side == 'buy':
price = ob['asks'][0][0]
logger.debug(f"{pair} checking dry buy-order: price={price}, limit={limit}")
if limit >= price:
price = orderbook['asks'][0][0]
if limit * (1 - offset) >= price:
return True
else:
price = ob['bids'][0][0]
logger.debug(f"{pair} checking dry sell-order: price={price}, limit={limit}")
if limit <= price:
price = orderbook['bids'][0][0]
if limit * (1 + offset) <= price:
return True
except IndexError:
# Ignore empty orderbooks when filling - can be filled with the next iteration.
@@ -947,7 +972,8 @@ class Exchange:
return False
def check_dry_limit_order_filled(
self, order: Dict[str, Any], immediate: bool = False) -> Dict[str, Any]:
self, order: Dict[str, Any], immediate: bool = False,
orderbook: Optional[OrderBook] = None) -> Dict[str, Any]:
"""
Check dry-run limit order fill and update fee (if it filled).
"""
@@ -955,7 +981,7 @@ class Exchange:
and order['type'] in ["limit"]
and not order.get('ft_order_type')):
pair = order['symbol']
if self._is_dry_limit_order_filled(pair, order['side'], order['price']):
if self._dry_is_price_crossed(pair, order['side'], order['price'], orderbook):
order.update({
'status': 'closed',
'filled': order['amount'],
@@ -1121,8 +1147,8 @@ class Exchange:
return params
@retrier(retries=0)
def stoploss(self, pair: str, amount: float, stop_price: float, order_types: Dict,
side: BuySell, leverage: float) -> Dict:
def create_stoploss(self, pair: str, amount: float, stop_price: float, order_types: Dict,
side: BuySell, leverage: float) -> Dict:
"""
creates a stoploss order.
requires `_ft_has['stoploss_order_types']` to be set as a dict mapping limit and market
@@ -1167,6 +1193,10 @@ class Exchange:
stop_price=stop_price_norm)
if self.trading_mode == TradingMode.FUTURES:
params['reduceOnly'] = True
if 'stoploss_price_type' in order_types and 'stop_price_type_field' in self._ft_has:
price_type = self._ft_has['stop_price_type_value_mapping'][
order_types.get('stoploss_price_type', PriceType.LAST)]
params[self._ft_has['stop_price_type_field']] = price_type
amount = self.amount_to_precision(pair, self._amount_to_contracts(pair, amount))
@@ -1357,7 +1387,7 @@ class Exchange:
raise OperationalException(e) from e
@retrier
def fetch_positions(self, pair: str = None) -> List[Dict]:
def fetch_positions(self, pair: Optional[str] = None) -> List[Dict]:
"""
Fetch positions from the exchange.
If no pair is given, all positions are returned.
@@ -1497,7 +1527,7 @@ class Exchange:
return result
@retrier
def fetch_l2_order_book(self, pair: str, limit: int = 100) -> dict:
def fetch_l2_order_book(self, pair: str, limit: int = 100) -> OrderBook:
"""
Get L2 order book from exchange.
Can be limited to a certain amount (if supported).
@@ -1540,7 +1570,7 @@ class Exchange:
def get_rate(self, pair: str, refresh: bool,
side: EntryExit, is_short: bool,
order_book: Optional[dict] = None, ticker: Optional[Ticker] = None) -> float:
order_book: Optional[OrderBook] = None, ticker: Optional[Ticker] = None) -> float:
"""
Calculates bid/ask target
bid rate - between current ask price and last price
@@ -1578,7 +1608,8 @@ class Exchange:
logger.debug('order_book %s', order_book)
# top 1 = index 0
try:
rate = order_book[f"{price_side}s"][order_book_top - 1][0]
obside: OBLiteral = 'bids' if price_side == 'bid' else 'asks'
rate = order_book[obside][order_book_top - 1][0]
except (IndexError, KeyError) as e:
logger.warning(
f"{pair} - {name} Price at location {order_book_top} from orderbook "
@@ -1705,7 +1736,7 @@ class Exchange:
return self._config['fee']
# validate that markets are loaded before trying to get fee
if self._api.markets is None or len(self._api.markets) == 0:
self._api.load_markets()
self._api.load_markets(params={})
return self._api.calculate_fee(symbol=symbol, type=type, side=side, amount=amount,
price=price, takerOrMaker=taker_or_maker)['rate']
@@ -1801,7 +1832,7 @@ class Exchange:
def get_historic_ohlcv(self, pair: str, timeframe: str,
since_ms: int, candle_type: CandleType,
is_new_pair: bool = False,
until_ms: int = None) -> List:
until_ms: Optional[int] = None) -> List:
"""
Get candle history using asyncio and returns the list of candles.
Handles all async work for this.
@@ -1813,32 +1844,18 @@ class Exchange:
:param candle_type: '', mark, index, premiumIndex, or funding_rate
:return: List with candle (OHLCV) data
"""
pair, _, _, data = self.loop.run_until_complete(
pair, _, _, data, _ = self.loop.run_until_complete(
self._async_get_historic_ohlcv(pair=pair, timeframe=timeframe,
since_ms=since_ms, until_ms=until_ms,
is_new_pair=is_new_pair, candle_type=candle_type))
logger.info(f"Downloaded data for {pair} with length {len(data)}.")
return data
def get_historic_ohlcv_as_df(self, pair: str, timeframe: str,
since_ms: int, candle_type: CandleType) -> DataFrame:
"""
Minimal wrapper around get_historic_ohlcv - converting the result into a dataframe
:param pair: Pair to download
:param timeframe: Timeframe to get data for
:param since_ms: Timestamp in milliseconds to get history from
:param candle_type: Any of the enum CandleType (must match trading mode!)
:return: OHLCV DataFrame
"""
ticks = self.get_historic_ohlcv(pair, timeframe, since_ms=since_ms, candle_type=candle_type)
return ohlcv_to_dataframe(ticks, timeframe, pair=pair, fill_missing=True,
drop_incomplete=self._ohlcv_partial_candle)
async def _async_get_historic_ohlcv(self, pair: str, timeframe: str,
since_ms: int, candle_type: CandleType,
is_new_pair: bool = False, raise_: bool = False,
until_ms: Optional[int] = None
) -> Tuple[str, str, str, List]:
) -> OHLCVResponse:
"""
Download historic ohlcv
:param is_new_pair: used by binance subclass to allow "fast" new pair downloading
@@ -1869,15 +1886,16 @@ class Exchange:
continue
else:
# Deconstruct tuple if it's not an exception
p, _, c, new_data = res
p, _, c, new_data, _ = res
if p == pair and c == candle_type:
data.extend(new_data)
# Sort data again after extending the result - above calls return in "async order"
data = sorted(data, key=lambda x: x[0])
return pair, timeframe, candle_type, data
return pair, timeframe, candle_type, data, self._ohlcv_partial_candle
def _build_coroutine(self, pair: str, timeframe: str, candle_type: CandleType,
since_ms: Optional[int], cache: bool) -> Coroutine:
def _build_coroutine(
self, pair: str, timeframe: str, candle_type: CandleType,
since_ms: Optional[int], cache: bool) -> Coroutine[Any, Any, OHLCVResponse]:
not_all_data = cache and self.required_candle_call_count > 1
if cache and (pair, timeframe, candle_type) in self._klines:
candle_limit = self.ohlcv_candle_limit(timeframe, candle_type)
@@ -1914,7 +1932,7 @@ class Exchange:
"""
Build Coroutines to execute as part of refresh_latest_ohlcv
"""
input_coroutines = []
input_coroutines: List[Coroutine[Any, Any, OHLCVResponse]] = []
cached_pairs = []
for pair, timeframe, candle_type in set(pair_list):
if (timeframe not in self.timeframes
@@ -1978,7 +1996,6 @@ class Exchange:
:return: Dict of [{(pair, timeframe): Dataframe}]
"""
logger.debug("Refreshing candle (OHLCV) data for %d pairs", len(pair_list))
drop_incomplete = self._ohlcv_partial_candle if drop_incomplete is None else drop_incomplete
# Gather coroutines to run
input_coroutines, cached_pairs = self._build_ohlcv_dl_jobs(pair_list, since_ms, cache)
@@ -1996,10 +2013,11 @@ class Exchange:
if isinstance(res, Exception):
logger.warning(f"Async code raised an exception: {repr(res)}")
continue
# Deconstruct tuple (has 4 elements)
pair, timeframe, c_type, ticks = res
# Deconstruct tuple (has 5 elements)
pair, timeframe, c_type, ticks, drop_hint = res
drop_incomplete_ = drop_hint if drop_incomplete is None else drop_incomplete
ohlcv_df = self._process_ohlcv_df(
pair, timeframe, c_type, ticks, cache, drop_incomplete)
pair, timeframe, c_type, ticks, cache, drop_incomplete_)
results_df[(pair, timeframe, c_type)] = ohlcv_df
@@ -2025,7 +2043,7 @@ class Exchange:
timeframe: str,
candle_type: CandleType,
since_ms: Optional[int] = None,
) -> Tuple[str, str, str, List]:
) -> OHLCVResponse:
"""
Asynchronously get candle history data using fetch_ohlcv
:param candle_type: '', mark, index, premiumIndex, or funding_rate
@@ -2035,8 +2053,8 @@ class Exchange:
# Fetch OHLCV asynchronously
s = '(' + arrow.get(since_ms // 1000).isoformat() + ') ' if since_ms is not None else ''
logger.debug(
"Fetching pair %s, interval %s, since %s %s...",
pair, timeframe, since_ms, s
"Fetching pair %s, %s, interval %s, since %s %s...",
pair, candle_type, timeframe, since_ms, s
)
params = deepcopy(self._ft_has.get('ohlcv_params', {}))
candle_limit = self.ohlcv_candle_limit(
@@ -2050,11 +2068,12 @@ class Exchange:
limit=candle_limit, params=params)
else:
# Funding rate
data = await self._api_async.fetch_funding_rate_history(
pair, since=since_ms,
limit=candle_limit)
# Convert funding rate to candle pattern
data = [[x['timestamp'], x['fundingRate'], 0, 0, 0, 0] for x in data]
data = await self._fetch_funding_rate_history(
pair=pair,
timeframe=timeframe,
limit=candle_limit,
since_ms=since_ms,
)
# Some exchanges sort OHLCV in ASC order and others in DESC.
# Ex: Bittrex returns the list of OHLCV in ASC order (oldest first, newest last)
# while GDAX returns the list of OHLCV in DESC order (newest first, oldest last)
@@ -2064,9 +2083,9 @@ class Exchange:
data = sorted(data, key=lambda x: x[0])
except IndexError:
logger.exception("Error loading %s. Result was %s.", pair, data)
return pair, timeframe, candle_type, []
return pair, timeframe, candle_type, [], self._ohlcv_partial_candle
logger.debug("Done fetching pair %s, interval %s ...", pair, timeframe)
return pair, timeframe, candle_type, data
return pair, timeframe, candle_type, data, self._ohlcv_partial_candle
except ccxt.NotSupported as e:
raise OperationalException(
@@ -2082,6 +2101,24 @@ class Exchange:
raise OperationalException(f'Could not fetch historical candle (OHLCV) data '
f'for pair {pair}. Message: {e}') from e
async def _fetch_funding_rate_history(
self,
pair: str,
timeframe: str,
limit: int,
since_ms: Optional[int] = None,
) -> List[List]:
"""
Fetch funding rate history - used to selectively override this by subclasses.
"""
# Funding rate
data = await self._api_async.fetch_funding_rate_history(
pair, since=since_ms,
limit=limit)
# Convert funding rate to candle pattern
data = [[x['timestamp'], x['fundingRate'], 0, 0, 0, 0] for x in data]
return data
# Fetch historic trades
@retrier_async
@@ -2485,7 +2522,8 @@ class Exchange:
self,
leverage: float,
pair: Optional[str] = None,
trading_mode: Optional[TradingMode] = None
trading_mode: Optional[TradingMode] = None,
accept_fail: bool = False,
):
"""
Set's the leverage before making a trade, in order to not
@@ -2494,12 +2532,18 @@ class Exchange:
if self._config['dry_run'] or not self.exchange_has("setLeverage"):
# Some exchanges only support one margin_mode type
return
if self._ft_has.get('floor_leverage', False) is True:
# Rounding for binance ...
leverage = floor(leverage)
try:
res = self._api.set_leverage(symbol=pair, leverage=leverage)
self._log_exchange_response('set_leverage', res)
except ccxt.DDoSProtection as e:
raise DDosProtection(e) from e
except ccxt.BadRequest as e:
if not accept_fail:
raise TemporaryError(
f'Could not set leverage due to {e.__class__.__name__}. Message: {e}') from e
except (ccxt.NetworkError, ccxt.ExchangeError) as e:
raise TemporaryError(
f'Could not set leverage due to {e.__class__.__name__}. Message: {e}') from e
@@ -2521,7 +2565,8 @@ class Exchange:
return open_date.minute > 0 or open_date.second > 0
@retrier
def set_margin_mode(self, pair: str, margin_mode: MarginMode, params: dict = {}):
def set_margin_mode(self, pair: str, margin_mode: MarginMode, accept_fail: bool = False,
params: dict = {}):
"""
Set's the margin mode on the exchange to cross or isolated for a specific pair
:param pair: base/quote currency pair (e.g. "ADA/USDT")
@@ -2535,6 +2580,10 @@ class Exchange:
self._log_exchange_response('set_margin_mode', res)
except ccxt.DDoSProtection as e:
raise DDosProtection(e) from e
except ccxt.BadRequest as e:
if not accept_fail:
raise TemporaryError(
f'Could not set margin mode due to {e.__class__.__name__}. Message: {e}') from e
except (ccxt.NetworkError, ccxt.ExchangeError) as e:
raise TemporaryError(
f'Could not set margin mode due to {e.__class__.__name__}. Message: {e}') from e
@@ -2668,7 +2717,7 @@ class Exchange:
:param amount: Trade amount
:param open_date: Open date of the trade
:return: funding fee since open_date
:raies: ExchangeError if something goes wrong.
:raises: ExchangeError if something goes wrong.
"""
if self.trading_mode == TradingMode.FUTURES:
if self._config['dry_run']:
@@ -2688,6 +2737,7 @@ class Exchange:
is_short: bool,
amount: float, # Absolute value of position size
stake_amount: float,
leverage: float,
wallet_balance: float,
mm_ex_1: float = 0.0, # (Binance) Cross only
upnl_ex_1: float = 0.0, # (Binance) Cross only
@@ -2709,6 +2759,7 @@ class Exchange:
open_rate=open_rate,
is_short=is_short,
amount=amount,
leverage=leverage,
stake_amount=stake_amount,
wallet_balance=wallet_balance,
mm_ex_1=mm_ex_1,
@@ -2720,7 +2771,7 @@ class Exchange:
pos = positions[0]
isolated_liq = pos['liquidationPrice']
if isolated_liq:
if isolated_liq is not None:
buffer_amount = abs(open_rate - isolated_liq) * self.liquidation_buffer
isolated_liq = (
isolated_liq - buffer_amount
@@ -2738,6 +2789,7 @@ class Exchange:
is_short: bool,
amount: float,
stake_amount: float,
leverage: float,
wallet_balance: float, # Or margin balance
mm_ex_1: float = 0.0, # (Binance) Cross only
upnl_ex_1: float = 0.0, # (Binance) Cross only
@@ -2745,22 +2797,28 @@ class Exchange:
"""
Important: Must be fetching data from cached values as this is used by backtesting!
PERPETUAL:
gateio: https://www.gate.io/help/futures/perpetual/22160/calculation-of-liquidation-price
gate: https://www.gate.io/help/futures/futures/27724/liquidation-price-bankruptcy-price
> Liquidation Price = (Entry Price ± Margin / Contract Multiplier / Size) /
[ 1 ± (Maintenance Margin Ratio + Taker Rate)]
Wherein, "+" or "-" depends on whether the contract goes long or short:
"-" for long, and "+" for short.
okex: https://www.okex.com/support/hc/en-us/articles/
360053909592-VI-Introduction-to-the-isolated-mode-of-Single-Multi-currency-Portfolio-margin
:param exchange_name:
:param pair: Pair to calculate liquidation price for
:param open_rate: Entry price of position
:param is_short: True if the trade is a short, false otherwise
:param amount: Absolute value of position size incl. leverage (in base currency)
:param stake_amount: Stake amount - Collateral in settle currency.
:param leverage: Leverage used for this position.
:param trading_mode: SPOT, MARGIN, FUTURES, etc.
:param margin_mode: Either ISOLATED or CROSS
:param wallet_balance: Amount of margin_mode in the wallet being used to trade
Cross-Margin Mode: crossWalletBalance
Isolated-Margin Mode: isolatedWalletBalance
# * Not required by Gateio or OKX
# * Not required by Gate or OKX
:param mm_ex_1:
:param upnl_ex_1:
"""
@@ -2789,7 +2847,7 @@ class Exchange:
def get_maintenance_ratio_and_amt(
self,
pair: str,
nominal_value: float = 0.0,
nominal_value: float,
) -> Tuple[float, Optional[float]]:
"""
Important: Must be fetching data from cached values as this is used by backtesting!

View File

@@ -15,18 +15,19 @@ from freqtrade.util import FtPrecise
CcxtModuleType = Any
def is_exchange_known_ccxt(exchange_name: str, ccxt_module: CcxtModuleType = None) -> bool:
def is_exchange_known_ccxt(
exchange_name: str, ccxt_module: Optional[CcxtModuleType] = None) -> bool:
return exchange_name in ccxt_exchanges(ccxt_module)
def ccxt_exchanges(ccxt_module: CcxtModuleType = None) -> List[str]:
def ccxt_exchanges(ccxt_module: Optional[CcxtModuleType] = None) -> List[str]:
"""
Return the list of all exchanges known to ccxt
"""
return ccxt_module.exchanges if ccxt_module is not None else ccxt.exchanges
def available_exchanges(ccxt_module: CcxtModuleType = None) -> List[str]:
def available_exchanges(ccxt_module: Optional[CcxtModuleType] = None) -> List[str]:
"""
Return exchanges available to the bot, i.e. non-bad exchanges in the ccxt list
"""
@@ -86,7 +87,7 @@ def timeframe_to_msecs(timeframe: str) -> int:
return ccxt.Exchange.parse_timeframe(timeframe) * 1000
def timeframe_to_prev_date(timeframe: str, date: datetime = None) -> datetime:
def timeframe_to_prev_date(timeframe: str, date: Optional[datetime] = None) -> datetime:
"""
Use Timeframe and determine the candle start date for this date.
Does not round when given a candle start date.
@@ -102,7 +103,7 @@ def timeframe_to_prev_date(timeframe: str, date: datetime = None) -> datetime:
return datetime.fromtimestamp(new_timestamp, tz=timezone.utc)
def timeframe_to_next_date(timeframe: str, date: datetime = None) -> datetime:
def timeframe_to_next_date(timeframe: str, date: Optional[datetime] = None) -> datetime:
"""
Use Timeframe and determine next candle.
:param timeframe: timeframe in string format (e.g. "5m")

View File

@@ -4,7 +4,7 @@ from datetime import datetime
from typing import Any, Dict, List, Optional, Tuple
from freqtrade.constants import BuySell
from freqtrade.enums import MarginMode, TradingMode
from freqtrade.enums import MarginMode, PriceType, TradingMode
from freqtrade.exceptions import OperationalException
from freqtrade.exchange import Exchange
from freqtrade.misc import safe_value_fallback2
@@ -13,7 +13,7 @@ from freqtrade.misc import safe_value_fallback2
logger = logging.getLogger(__name__)
class Gateio(Exchange):
class Gate(Exchange):
"""
Gate.io exchange class. Contains adjustments needed for Freqtrade to work
with this exchange.
@@ -34,6 +34,12 @@ class Gateio(Exchange):
"needs_trading_fees": True,
"fee_cost_in_contracts": False, # Set explicitly to false for clarity
"order_props_in_contracts": ['amount', 'filled', 'remaining'],
"stop_price_type_field": "price_type",
"stop_price_type_value_mapping": {
PriceType.LAST: 0,
PriceType.MARK: 1,
PriceType.INDEX: 2,
},
}
_supported_trading_mode_margin_pairs: List[Tuple[TradingMode, MarginMode]] = [
@@ -49,6 +55,7 @@ class Gateio(Exchange):
if any(v == 'market' for k, v in order_types.items()):
raise OperationalException(
f'Exchange {self.name} does not support market orders.')
super().validate_stop_ordertypes(order_types)
def _get_params(
self,
@@ -77,7 +84,7 @@ class Gateio(Exchange):
if self.trading_mode == TradingMode.FUTURES:
# Futures usually don't contain fees in the response.
# As such, futures orders on gateio will not contain a fee, which causes
# As such, futures orders on gate will not contain a fee, which causes
# a repeated "update fee" cycle and wrong calculations.
# Therefore we patch the response with fees if it's not available.
# An alternative also contianing fees would be

View File

@@ -19,5 +19,4 @@ class Hitbtc(Exchange):
_ft_has: Dict = {
"ohlcv_candle_limit": 1000,
"ohlcv_params": {"sort": "DESC"}
}

View File

@@ -97,8 +97,8 @@ class Kraken(Exchange):
))
@retrier(retries=0)
def stoploss(self, pair: str, amount: float, stop_price: float,
order_types: Dict, side: BuySell, leverage: float) -> Dict:
def create_stoploss(self, pair: str, amount: float, stop_price: float,
order_types: Dict, side: BuySell, leverage: float) -> Dict:
"""
Creates a stoploss market order.
Stoploss market orders is the only stoploss type supported by kraken.
@@ -158,7 +158,8 @@ class Kraken(Exchange):
self,
leverage: float,
pair: Optional[str] = None,
trading_mode: Optional[TradingMode] = None
trading_mode: Optional[TradingMode] = None,
accept_fail: bool = False,
):
"""
Kraken set's the leverage as an option in the order object, so we need to

View File

@@ -36,3 +36,34 @@ class Kucoin(Exchange):
'stop': 'loss'
})
return params
def create_order(
self,
*,
pair: str,
ordertype: str,
side: BuySell,
amount: float,
rate: float,
leverage: float,
reduceOnly: bool = False,
time_in_force: str = 'GTC',
) -> Dict:
res = super().create_order(
pair=pair,
ordertype=ordertype,
side=side,
amount=amount,
rate=rate,
leverage=leverage,
reduceOnly=reduceOnly,
time_in_force=time_in_force,
)
# Kucoin returns only the order-id.
# ccxt returns status = 'closed' at the moment - which is information ccxt invented.
# Since we rely on status heavily, we must set it to 'open' here.
# ref: https://github.com/ccxt/ccxt/pull/16674, (https://github.com/ccxt/ccxt/pull/16553)
res['type'] = ordertype
res['status'] = 'open'
return res

View File

@@ -5,6 +5,7 @@ import ccxt
from freqtrade.constants import BuySell
from freqtrade.enums import CandleType, MarginMode, TradingMode
from freqtrade.enums.pricetype import PriceType
from freqtrade.exceptions import DDosProtection, OperationalException, TemporaryError
from freqtrade.exchange import Exchange, date_minus_candles
from freqtrade.exchange.common import retrier
@@ -27,6 +28,12 @@ class Okx(Exchange):
_ft_has_futures: Dict = {
"tickers_have_quoteVolume": False,
"fee_cost_in_contracts": True,
"stop_price_type_field": "tpTriggerPxType",
"stop_price_type_value_mapping": {
PriceType.LAST: "last",
PriceType.MARK: "index",
PriceType.INDEX: "mark",
},
}
_supported_trading_mode_margin_pairs: List[Tuple[TradingMode, MarginMode]] = [
@@ -118,13 +125,15 @@ class Okx(Exchange):
if self.trading_mode != TradingMode.SPOT and self.margin_mode is not None:
try:
# TODO-lev: Test me properly (check mgnMode passed)
self._api.set_leverage(
res = self._api.set_leverage(
leverage=leverage,
symbol=pair,
params={
"mgnMode": self.margin_mode.value,
"posSide": self._get_posSide(side, False),
})
self._log_exchange_response('set_leverage', res)
except ccxt.DDoSProtection as e:
raise DDosProtection(e) from e
except (ccxt.NetworkError, ccxt.ExchangeError) as e:

View File

@@ -1,4 +1,6 @@
from typing import Dict, Optional, TypedDict
from typing import Dict, List, Optional, Tuple, TypedDict
from freqtrade.enums import CandleType
class Ticker(TypedDict):
@@ -13,4 +15,16 @@ class Ticker(TypedDict):
# Several more - only listing required.
class OrderBook(TypedDict):
symbol: str
bids: List[Tuple[float, float]]
asks: List[Tuple[float, float]]
timestamp: Optional[int]
datetime: Optional[str]
nonce: Optional[int]
Tickers = Dict[str, Ticker]
# pair, timeframe, candleType, OHLCV, drop last?,
OHLCVResponse = Tuple[str, str, CandleType, List, bool]

View File

@@ -0,0 +1,125 @@
import logging
from enum import Enum
from gym import spaces
from freqtrade.freqai.RL.BaseEnvironment import BaseEnvironment, Positions
logger = logging.getLogger(__name__)
class Actions(Enum):
Neutral = 0
Buy = 1
Sell = 2
class Base3ActionRLEnv(BaseEnvironment):
"""
Base class for a 3 action environment
"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.actions = Actions
def set_action_space(self):
self.action_space = spaces.Discrete(len(Actions))
def step(self, action: int):
"""
Logic for a single step (incrementing one candle in time)
by the agent
:param: action: int = the action type that the agent plans
to take for the current step.
:returns:
observation = current state of environment
step_reward = the reward from `calculate_reward()`
_done = if the agent "died" or if the candles finished
info = dict passed back to openai gym lib
"""
self._done = False
self._current_tick += 1
if self._current_tick == self._end_tick:
self._done = True
self._update_unrealized_total_profit()
step_reward = self.calculate_reward(action)
self.total_reward += step_reward
self.tensorboard_log(self.actions._member_names_[action])
trade_type = None
if self.is_tradesignal(action):
if action == Actions.Buy.value:
if self._position == Positions.Short:
self._update_total_profit()
self._position = Positions.Long
trade_type = "long"
self._last_trade_tick = self._current_tick
elif action == Actions.Sell.value and self.can_short:
if self._position == Positions.Long:
self._update_total_profit()
self._position = Positions.Short
trade_type = "short"
self._last_trade_tick = self._current_tick
elif action == Actions.Sell.value and not self.can_short:
self._update_total_profit()
self._position = Positions.Neutral
trade_type = "neutral"
self._last_trade_tick = None
else:
print("case not defined")
if trade_type is not None:
self.trade_history.append(
{'price': self.current_price(), 'index': self._current_tick,
'type': trade_type})
if (self._total_profit < self.max_drawdown or
self._total_unrealized_profit < self.max_drawdown):
self._done = True
self._position_history.append(self._position)
info = dict(
tick=self._current_tick,
action=action,
total_reward=self.total_reward,
total_profit=self._total_profit,
position=self._position.value,
trade_duration=self.get_trade_duration(),
current_profit_pct=self.get_unrealized_profit()
)
observation = self._get_observation()
self._update_history(info)
return observation, step_reward, self._done, info
def is_tradesignal(self, action: int) -> bool:
"""
Determine if the signal is a trade signal
e.g.: agent wants a Actions.Buy while it is in a Positions.short
"""
return (
(action == Actions.Buy.value and self._position == Positions.Neutral)
or (action == Actions.Sell.value and self._position == Positions.Long)
or (action == Actions.Sell.value and self._position == Positions.Neutral
and self.can_short)
or (action == Actions.Buy.value and self._position == Positions.Short
and self.can_short)
)
def _is_valid(self, action: int) -> bool:
"""
Determine if the signal is valid.
e.g.: agent wants a Actions.Sell while it is in a Positions.Long
"""
if self.can_short:
return action in [Actions.Buy.value, Actions.Sell.value, Actions.Neutral.value]
else:
if action == Actions.Sell.value and self._position != Positions.Long:
return False
return True

View File

@@ -0,0 +1,142 @@
import logging
from enum import Enum
from gym import spaces
from freqtrade.freqai.RL.BaseEnvironment import BaseEnvironment, Positions
logger = logging.getLogger(__name__)
class Actions(Enum):
Neutral = 0
Exit = 1
Long_enter = 2
Short_enter = 3
class Base4ActionRLEnv(BaseEnvironment):
"""
Base class for a 4 action environment
"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.actions = Actions
def set_action_space(self):
self.action_space = spaces.Discrete(len(Actions))
def step(self, action: int):
"""
Logic for a single step (incrementing one candle in time)
by the agent
:param: action: int = the action type that the agent plans
to take for the current step.
:returns:
observation = current state of environment
step_reward = the reward from `calculate_reward()`
_done = if the agent "died" or if the candles finished
info = dict passed back to openai gym lib
"""
self._done = False
self._current_tick += 1
if self._current_tick == self._end_tick:
self._done = True
self._update_unrealized_total_profit()
step_reward = self.calculate_reward(action)
self.total_reward += step_reward
self.tensorboard_log(self.actions._member_names_[action])
trade_type = None
if self.is_tradesignal(action):
"""
Action: Neutral, position: Long -> Close Long
Action: Neutral, position: Short -> Close Short
Action: Long, position: Neutral -> Open Long
Action: Long, position: Short -> Close Short and Open Long
Action: Short, position: Neutral -> Open Short
Action: Short, position: Long -> Close Long and Open Short
"""
if action == Actions.Neutral.value:
self._position = Positions.Neutral
trade_type = "neutral"
self._last_trade_tick = None
elif action == Actions.Long_enter.value:
self._position = Positions.Long
trade_type = "long"
self._last_trade_tick = self._current_tick
elif action == Actions.Short_enter.value:
self._position = Positions.Short
trade_type = "short"
self._last_trade_tick = self._current_tick
elif action == Actions.Exit.value:
self._update_total_profit()
self._position = Positions.Neutral
trade_type = "neutral"
self._last_trade_tick = None
else:
print("case not defined")
if trade_type is not None:
self.trade_history.append(
{'price': self.current_price(), 'index': self._current_tick,
'type': trade_type})
if (self._total_profit < self.max_drawdown or
self._total_unrealized_profit < self.max_drawdown):
self._done = True
self._position_history.append(self._position)
info = dict(
tick=self._current_tick,
action=action,
total_reward=self.total_reward,
total_profit=self._total_profit,
position=self._position.value,
trade_duration=self.get_trade_duration(),
current_profit_pct=self.get_unrealized_profit()
)
observation = self._get_observation()
self._update_history(info)
return observation, step_reward, self._done, info
def is_tradesignal(self, action: int) -> bool:
"""
Determine if the signal is a trade signal
e.g.: agent wants a Actions.Long_exit while it is in a Positions.short
"""
return not ((action == Actions.Neutral.value and self._position == Positions.Neutral) or
(action == Actions.Neutral.value and self._position == Positions.Short) or
(action == Actions.Neutral.value and self._position == Positions.Long) or
(action == Actions.Short_enter.value and self._position == Positions.Short) or
(action == Actions.Short_enter.value and self._position == Positions.Long) or
(action == Actions.Exit.value and self._position == Positions.Neutral) or
(action == Actions.Long_enter.value and self._position == Positions.Long) or
(action == Actions.Long_enter.value and self._position == Positions.Short))
def _is_valid(self, action: int) -> bool:
"""
Determine if the signal is valid.
e.g.: agent wants a Actions.Long_exit while it is in a Positions.short
"""
# Agent should only try to exit if it is in position
if action == Actions.Exit.value:
if self._position not in (Positions.Short, Positions.Long):
return False
# Agent should only try to enter if it is not in position
if action in (Actions.Short_enter.value, Actions.Long_enter.value):
if self._position != Positions.Neutral:
return False
return True

View File

@@ -0,0 +1,152 @@
import logging
from enum import Enum
from gym import spaces
from freqtrade.freqai.RL.BaseEnvironment import BaseEnvironment, Positions
logger = logging.getLogger(__name__)
class Actions(Enum):
Neutral = 0
Long_enter = 1
Long_exit = 2
Short_enter = 3
Short_exit = 4
class Base5ActionRLEnv(BaseEnvironment):
"""
Base class for a 5 action environment
"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.actions = Actions
def set_action_space(self):
self.action_space = spaces.Discrete(len(Actions))
def step(self, action: int):
"""
Logic for a single step (incrementing one candle in time)
by the agent
:param: action: int = the action type that the agent plans
to take for the current step.
:returns:
observation = current state of environment
step_reward = the reward from `calculate_reward()`
_done = if the agent "died" or if the candles finished
info = dict passed back to openai gym lib
"""
self._done = False
self._current_tick += 1
if self._current_tick == self._end_tick:
self._done = True
self._update_unrealized_total_profit()
step_reward = self.calculate_reward(action)
self.total_reward += step_reward
self.tensorboard_log(self.actions._member_names_[action])
trade_type = None
if self.is_tradesignal(action):
"""
Action: Neutral, position: Long -> Close Long
Action: Neutral, position: Short -> Close Short
Action: Long, position: Neutral -> Open Long
Action: Long, position: Short -> Close Short and Open Long
Action: Short, position: Neutral -> Open Short
Action: Short, position: Long -> Close Long and Open Short
"""
if action == Actions.Neutral.value:
self._position = Positions.Neutral
trade_type = "neutral"
self._last_trade_tick = None
elif action == Actions.Long_enter.value:
self._position = Positions.Long
trade_type = "long"
self._last_trade_tick = self._current_tick
elif action == Actions.Short_enter.value:
self._position = Positions.Short
trade_type = "short"
self._last_trade_tick = self._current_tick
elif action == Actions.Long_exit.value:
self._update_total_profit()
self._position = Positions.Neutral
trade_type = "neutral"
self._last_trade_tick = None
elif action == Actions.Short_exit.value:
self._update_total_profit()
self._position = Positions.Neutral
trade_type = "neutral"
self._last_trade_tick = None
else:
print("case not defined")
if trade_type is not None:
self.trade_history.append(
{'price': self.current_price(), 'index': self._current_tick,
'type': trade_type})
if (self._total_profit < self.max_drawdown or
self._total_unrealized_profit < self.max_drawdown):
self._done = True
self._position_history.append(self._position)
info = dict(
tick=self._current_tick,
action=action,
total_reward=self.total_reward,
total_profit=self._total_profit,
position=self._position.value,
trade_duration=self.get_trade_duration(),
current_profit_pct=self.get_unrealized_profit()
)
observation = self._get_observation()
self._update_history(info)
return observation, step_reward, self._done, info
def is_tradesignal(self, action: int) -> bool:
"""
Determine if the signal is a trade signal
e.g.: agent wants a Actions.Long_exit while it is in a Positions.short
"""
return not ((action == Actions.Neutral.value and self._position == Positions.Neutral) or
(action == Actions.Neutral.value and self._position == Positions.Short) or
(action == Actions.Neutral.value and self._position == Positions.Long) or
(action == Actions.Short_enter.value and self._position == Positions.Short) or
(action == Actions.Short_enter.value and self._position == Positions.Long) or
(action == Actions.Short_exit.value and self._position == Positions.Long) or
(action == Actions.Short_exit.value and self._position == Positions.Neutral) or
(action == Actions.Long_enter.value and self._position == Positions.Long) or
(action == Actions.Long_enter.value and self._position == Positions.Short) or
(action == Actions.Long_exit.value and self._position == Positions.Short) or
(action == Actions.Long_exit.value and self._position == Positions.Neutral))
def _is_valid(self, action: int) -> bool:
# trade signal
"""
Determine if the signal is valid.
e.g.: agent wants a Actions.Long_exit while it is in a Positions.short
"""
# Agent should only try to exit if it is in position
if action in (Actions.Short_exit.value, Actions.Long_exit.value):
if self._position not in (Positions.Short, Positions.Long):
return False
# Agent should only try to enter if it is not in position
if action in (Actions.Short_enter.value, Actions.Long_enter.value):
if self._position != Positions.Neutral:
return False
return True

View File

@@ -0,0 +1,365 @@
import logging
import random
from abc import abstractmethod
from enum import Enum
from typing import Optional, Type, Union
import gym
import numpy as np
import pandas as pd
from gym import spaces
from gym.utils import seeding
from pandas import DataFrame
logger = logging.getLogger(__name__)
class BaseActions(Enum):
"""
Default action space, mostly used for type handling.
"""
Neutral = 0
Long_enter = 1
Long_exit = 2
Short_enter = 3
Short_exit = 4
class Positions(Enum):
Short = 0
Long = 1
Neutral = 0.5
def opposite(self):
return Positions.Short if self == Positions.Long else Positions.Long
class BaseEnvironment(gym.Env):
"""
Base class for environments. This class is agnostic to action count.
Inherited classes customize this to include varying action counts/types,
See RL/Base5ActionRLEnv.py and RL/Base4ActionRLEnv.py
"""
def __init__(self, df: DataFrame = DataFrame(), prices: DataFrame = DataFrame(),
reward_kwargs: dict = {}, window_size=10, starting_point=True,
id: str = 'baseenv-1', seed: int = 1, config: dict = {}, live: bool = False,
fee: float = 0.0015, can_short: bool = False, pair: str = "",
df_raw: DataFrame = DataFrame()):
"""
Initializes the training/eval environment.
:param df: dataframe of features
:param prices: dataframe of prices to be used in the training environment
:param window_size: size of window (temporal) to pass to the agent
:param reward_kwargs: extra config settings assigned by user in `rl_config`
:param starting_point: start at edge of window or not
:param id: string id of the environment (used in backend for multiprocessed env)
:param seed: Sets the seed of the environment higher in the gym.Env object
:param config: Typical user configuration file
:param live: Whether or not this environment is active in dry/live/backtesting
:param fee: The fee to use for environmental interactions.
:param can_short: Whether or not the environment can short
"""
self.config: dict = config
self.rl_config: dict = config['freqai']['rl_config']
self.add_state_info: bool = self.rl_config.get('add_state_info', False)
self.id: str = id
self.max_drawdown: float = 1 - self.rl_config.get('max_training_drawdown_pct', 0.8)
self.compound_trades: bool = config['stake_amount'] == 'unlimited'
self.pair: str = pair
self.raw_features: DataFrame = df_raw
if self.config.get('fee', None) is not None:
self.fee = self.config['fee']
else:
self.fee = fee
# set here to default 5Ac, but all children envs can override this
self.actions: Type[Enum] = BaseActions
self.tensorboard_metrics: dict = {}
self.can_short: bool = can_short
self.live: bool = live
if not self.live and self.add_state_info:
self.add_state_info = False
logger.warning("add_state_info is not available in backtesting. Deactivating.")
self.seed(seed)
self.reset_env(df, prices, window_size, reward_kwargs, starting_point)
def reset_env(self, df: DataFrame, prices: DataFrame, window_size: int,
reward_kwargs: dict, starting_point=True):
"""
Resets the environment when the agent fails (in our case, if the drawdown
exceeds the user set max_training_drawdown_pct)
:param df: dataframe of features
:param prices: dataframe of prices to be used in the training environment
:param window_size: size of window (temporal) to pass to the agent
:param reward_kwargs: extra config settings assigned by user in `rl_config`
:param starting_point: start at edge of window or not
"""
self.signal_features: DataFrame = df
self.prices: DataFrame = prices
self.window_size: int = window_size
self.starting_point: bool = starting_point
self.rr: float = reward_kwargs["rr"]
self.profit_aim: float = reward_kwargs["profit_aim"]
# # spaces
if self.add_state_info:
self.total_features = self.signal_features.shape[1] + 3
else:
self.total_features = self.signal_features.shape[1]
self.shape = (window_size, self.total_features)
self.set_action_space()
self.observation_space = spaces.Box(
low=-1, high=1, shape=self.shape, dtype=np.float32)
# episode
self._start_tick: int = self.window_size
self._end_tick: int = len(self.prices) - 1
self._done: bool = False
self._current_tick: int = self._start_tick
self._last_trade_tick: Optional[int] = None
self._position = Positions.Neutral
self._position_history: list = [None]
self.total_reward: float = 0
self._total_profit: float = 1
self._total_unrealized_profit: float = 1
self.history: dict = {}
self.trade_history: list = []
@abstractmethod
def set_action_space(self):
"""
Unique to the environment action count. Must be inherited.
"""
def seed(self, seed: int = 1):
self.np_random, seed = seeding.np_random(seed)
return [seed]
def tensorboard_log(self, metric: str, value: Union[int, float] = 1, inc: bool = True):
"""
Function builds the tensorboard_metrics dictionary
to be parsed by the TensorboardCallback. This
function is designed for tracking incremented objects,
events, actions inside the training environment.
For example, a user can call this to track the
frequency of occurence of an `is_valid` call in
their `calculate_reward()`:
def calculate_reward(self, action: int) -> float:
if not self._is_valid(action):
self.tensorboard_log("is_valid")
return -2
:param metric: metric to be tracked and incremented
:param value: value to increment `metric` by
:param inc: sets whether the `value` is incremented or not
"""
if not inc or metric not in self.tensorboard_metrics:
self.tensorboard_metrics[metric] = value
else:
self.tensorboard_metrics[metric] += value
def reset_tensorboard_log(self):
self.tensorboard_metrics = {}
def reset(self):
"""
Reset is called at the beginning of every episode
"""
self.reset_tensorboard_log()
self._done = False
if self.starting_point is True:
if self.rl_config.get('randomize_starting_position', False):
length_of_data = int(self._end_tick / 4)
start_tick = random.randint(self.window_size + 1, length_of_data)
self._start_tick = start_tick
self._position_history = (self._start_tick * [None]) + [self._position]
else:
self._position_history = (self.window_size * [None]) + [self._position]
self._current_tick = self._start_tick
self._last_trade_tick = None
self._position = Positions.Neutral
self.total_reward = 0.
self._total_profit = 1. # unit
self.history = {}
self.trade_history = []
self.portfolio_log_returns = np.zeros(len(self.prices))
self._profits = [(self._start_tick, 1)]
self.close_trade_profit = []
self._total_unrealized_profit = 1
return self._get_observation()
@abstractmethod
def step(self, action: int):
"""
Step depeneds on action types, this must be inherited.
"""
return
def _get_observation(self):
"""
This may or may not be independent of action types, user can inherit
this in their custom "MyRLEnv"
"""
features_window = self.signal_features[(
self._current_tick - self.window_size):self._current_tick]
if self.add_state_info:
features_and_state = DataFrame(np.zeros((len(features_window), 3)),
columns=['current_profit_pct',
'position',
'trade_duration'],
index=features_window.index)
features_and_state['current_profit_pct'] = self.get_unrealized_profit()
features_and_state['position'] = self._position.value
features_and_state['trade_duration'] = self.get_trade_duration()
features_and_state = pd.concat([features_window, features_and_state], axis=1)
return features_and_state
else:
return features_window
def get_trade_duration(self):
"""
Get the trade duration if the agent is in a trade
"""
if self._last_trade_tick is None:
return 0
else:
return self._current_tick - self._last_trade_tick
def get_unrealized_profit(self):
"""
Get the unrealized profit if the agent is in a trade
"""
if self._last_trade_tick is None:
return 0.
if self._position == Positions.Neutral:
return 0.
elif self._position == Positions.Short:
current_price = self.add_entry_fee(self.prices.iloc[self._current_tick].open)
last_trade_price = self.add_exit_fee(self.prices.iloc[self._last_trade_tick].open)
return (last_trade_price - current_price) / last_trade_price
elif self._position == Positions.Long:
current_price = self.add_exit_fee(self.prices.iloc[self._current_tick].open)
last_trade_price = self.add_entry_fee(self.prices.iloc[self._last_trade_tick].open)
return (current_price - last_trade_price) / last_trade_price
else:
return 0.
@abstractmethod
def is_tradesignal(self, action: int) -> bool:
"""
Determine if the signal is a trade signal. This is
unique to the actions in the environment, and therefore must be
inherited.
"""
return True
def _is_valid(self, action: int) -> bool:
"""
Determine if the signal is valid.This is
unique to the actions in the environment, and therefore must be
inherited.
"""
return True
def add_entry_fee(self, price):
return price * (1 + self.fee)
def add_exit_fee(self, price):
return price / (1 + self.fee)
def _update_history(self, info):
if not self.history:
self.history = {key: [] for key in info.keys()}
for key, value in info.items():
self.history[key].append(value)
@abstractmethod
def calculate_reward(self, action: int) -> float:
"""
An example reward function. This is the one function that users will likely
wish to inject their own creativity into.
:param action: int = The action made by the agent for the current candle.
:return:
float = the reward to give to the agent for current step (used for optimization
of weights in NN)
"""
def _update_unrealized_total_profit(self):
"""
Update the unrealized total profit incase of episode end.
"""
if self._position in (Positions.Long, Positions.Short):
pnl = self.get_unrealized_profit()
if self.compound_trades:
# assumes unit stake and compounding
unrl_profit = self._total_profit * (1 + pnl)
else:
# assumes unit stake and no compounding
unrl_profit = self._total_profit + pnl
self._total_unrealized_profit = unrl_profit
def _update_total_profit(self):
pnl = self.get_unrealized_profit()
if self.compound_trades:
# assumes unit stake and compounding
self._total_profit = self._total_profit * (1 + pnl)
else:
# assumes unit stake and no compounding
self._total_profit += pnl
def current_price(self) -> float:
return self.prices.iloc[self._current_tick].open
def get_actions(self) -> Type[Enum]:
"""
Used by SubprocVecEnv to get actions from
initialized env for tensorboard callback
"""
return self.actions
# Keeping around incase we want to start building more complex environment
# templates in the future.
# def most_recent_return(self):
# """
# Calculate the tick to tick return if in a trade.
# Return is generated from rising prices in Long
# and falling prices in Short positions.
# The actions Sell/Buy or Hold during a Long position trigger the sell/buy-fee.
# """
# # Long positions
# if self._position == Positions.Long:
# current_price = self.prices.iloc[self._current_tick].open
# previous_price = self.prices.iloc[self._current_tick - 1].open
# if (self._position_history[self._current_tick - 1] == Positions.Short
# or self._position_history[self._current_tick - 1] == Positions.Neutral):
# previous_price = self.add_entry_fee(previous_price)
# return np.log(current_price) - np.log(previous_price)
# # Short positions
# if self._position == Positions.Short:
# current_price = self.prices.iloc[self._current_tick].open
# previous_price = self.prices.iloc[self._current_tick - 1].open
# if (self._position_history[self._current_tick - 1] == Positions.Long
# or self._position_history[self._current_tick - 1] == Positions.Neutral):
# previous_price = self.add_exit_fee(previous_price)
# return np.log(previous_price) - np.log(current_price)
# return 0
# def update_portfolio_log_returns(self, action):
# self.portfolio_log_returns[self._current_tick] = self.most_recent_return(action)

View File

@@ -0,0 +1,442 @@
import copy
import importlib
import logging
from abc import abstractmethod
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Callable, Dict, Optional, Tuple, Type, Union
import gym
import numpy as np
import numpy.typing as npt
import pandas as pd
import torch as th
import torch.multiprocessing
from pandas import DataFrame
from stable_baselines3.common.callbacks import EvalCallback
from stable_baselines3.common.monitor import Monitor
from stable_baselines3.common.utils import set_random_seed
from stable_baselines3.common.vec_env import SubprocVecEnv
from freqtrade.exceptions import OperationalException
from freqtrade.freqai.data_kitchen import FreqaiDataKitchen
from freqtrade.freqai.freqai_interface import IFreqaiModel
from freqtrade.freqai.RL.Base5ActionRLEnv import Actions, Base5ActionRLEnv
from freqtrade.freqai.RL.BaseEnvironment import BaseActions, Positions
from freqtrade.freqai.RL.TensorboardCallback import TensorboardCallback
from freqtrade.persistence import Trade
logger = logging.getLogger(__name__)
torch.multiprocessing.set_sharing_strategy('file_system')
SB3_MODELS = ['PPO', 'A2C', 'DQN']
SB3_CONTRIB_MODELS = ['TRPO', 'ARS', 'RecurrentPPO', 'MaskablePPO']
class BaseReinforcementLearningModel(IFreqaiModel):
"""
User created Reinforcement Learning Model prediction class
"""
def __init__(self, **kwargs) -> None:
super().__init__(config=kwargs['config'])
self.max_threads = min(self.freqai_info['rl_config'].get(
'cpu_count', 1), max(int(self.max_system_threads / 2), 1))
th.set_num_threads(self.max_threads)
self.reward_params = self.freqai_info['rl_config']['model_reward_parameters']
self.train_env: Union[SubprocVecEnv, Type[gym.Env]] = gym.Env()
self.eval_env: Union[SubprocVecEnv, Type[gym.Env]] = gym.Env()
self.eval_callback: Optional[EvalCallback] = None
self.model_type = self.freqai_info['rl_config']['model_type']
self.rl_config = self.freqai_info['rl_config']
self.df_raw: DataFrame = DataFrame()
self.continual_learning = self.freqai_info.get('continual_learning', False)
if self.model_type in SB3_MODELS:
import_str = 'stable_baselines3'
elif self.model_type in SB3_CONTRIB_MODELS:
import_str = 'sb3_contrib'
else:
raise OperationalException(f'{self.model_type} not available in stable_baselines3 or '
f'sb3_contrib. please choose one of {SB3_MODELS} or '
f'{SB3_CONTRIB_MODELS}')
mod = importlib.import_module(import_str, self.model_type)
self.MODELCLASS = getattr(mod, self.model_type)
self.policy_type = self.freqai_info['rl_config']['policy_type']
self.unset_outlier_removal()
self.net_arch = self.rl_config.get('net_arch', [128, 128])
self.dd.model_type = import_str
self.tensorboard_callback: TensorboardCallback = \
TensorboardCallback(verbose=1, actions=BaseActions)
def unset_outlier_removal(self):
"""
If user has activated any function that may remove training points, this
function will set them to false and warn them
"""
if self.ft_params.get('use_SVM_to_remove_outliers', False):
self.ft_params.update({'use_SVM_to_remove_outliers': False})
logger.warning('User tried to use SVM with RL. Deactivating SVM.')
if self.ft_params.get('use_DBSCAN_to_remove_outliers', False):
self.ft_params.update({'use_DBSCAN_to_remove_outliers': False})
logger.warning('User tried to use DBSCAN with RL. Deactivating DBSCAN.')
if self.freqai_info['data_split_parameters'].get('shuffle', False):
self.freqai_info['data_split_parameters'].update({'shuffle': False})
logger.warning('User tried to shuffle training data. Setting shuffle to False')
def train(
self, unfiltered_df: DataFrame, pair: str, dk: FreqaiDataKitchen, **kwargs
) -> Any:
"""
Filter the training data and train a model to it. Train makes heavy use of the datakitchen
for storing, saving, loading, and analyzing the data.
:param unfiltered_df: Full dataframe for the current training period
:param metadata: pair metadata from strategy.
:returns:
:model: Trained model which can be used to inference (self.predict)
"""
logger.info("--------------------Starting training " f"{pair} --------------------")
features_filtered, labels_filtered = dk.filter_features(
unfiltered_df,
dk.training_features_list,
dk.label_list,
training_filter=True,
)
data_dictionary: Dict[str, Any] = dk.make_train_test_datasets(
features_filtered, labels_filtered)
self.df_raw = copy.deepcopy(data_dictionary["train_features"])
dk.fit_labels() # FIXME useless for now, but just satiating append methods
# normalize all data based on train_dataset only
prices_train, prices_test = self.build_ohlc_price_dataframes(dk.data_dictionary, pair, dk)
data_dictionary = dk.normalize_data(data_dictionary)
# data cleaning/analysis
self.data_cleaning_train(dk)
logger.info(
f'Training model on {len(dk.data_dictionary["train_features"].columns)}'
f' features and {len(data_dictionary["train_features"])} data points'
)
self.set_train_and_eval_environments(data_dictionary, prices_train, prices_test, dk)
model = self.fit(data_dictionary, dk)
logger.info(f"--------------------done training {pair}--------------------")
return model
def set_train_and_eval_environments(self, data_dictionary: Dict[str, DataFrame],
prices_train: DataFrame, prices_test: DataFrame,
dk: FreqaiDataKitchen):
"""
User can override this if they are using a custom MyRLEnv
:param data_dictionary: dict = common data dictionary containing train and test
features/labels/weights.
:param prices_train/test: DataFrame = dataframe comprised of the prices to be used in the
environment during training or testing
:param dk: FreqaiDataKitchen = the datakitchen for the current pair
"""
train_df = data_dictionary["train_features"]
test_df = data_dictionary["test_features"]
env_info = self.pack_env_dict(dk.pair)
self.train_env = self.MyRLEnv(df=train_df,
prices=prices_train,
**env_info)
self.eval_env = Monitor(self.MyRLEnv(df=test_df,
prices=prices_test,
**env_info))
self.eval_callback = EvalCallback(self.eval_env, deterministic=True,
render=False, eval_freq=len(train_df),
best_model_save_path=str(dk.data_path))
actions = self.train_env.get_actions()
self.tensorboard_callback = TensorboardCallback(verbose=1, actions=actions)
def pack_env_dict(self, pair: str) -> Dict[str, Any]:
"""
Create dictionary of environment arguments
"""
env_info = {"window_size": self.CONV_WIDTH,
"reward_kwargs": self.reward_params,
"config": self.config,
"live": self.live,
"can_short": self.can_short,
"pair": pair,
"df_raw": self.df_raw}
if self.data_provider:
env_info["fee"] = self.data_provider._exchange \
.get_fee(symbol=self.data_provider.current_whitelist()[0]) # type: ignore
return env_info
@abstractmethod
def fit(self, data_dictionary: Dict[str, Any], dk: FreqaiDataKitchen, **kwargs):
"""
Agent customizations and abstract Reinforcement Learning customizations
go in here. Abstract method, so this function must be overridden by
user class.
"""
return
def get_state_info(self, pair: str) -> Tuple[float, float, int]:
"""
State info during dry/live (not backtesting) which is fed back
into the model.
:param pair: str = COIN/STAKE to get the environment information for
:return:
:market_side: float = representing short, long, or neutral for
pair
:current_profit: float = unrealized profit of the current trade
:trade_duration: int = the number of candles that the trade has
been open for
"""
open_trades = Trade.get_trades_proxy(is_open=True)
market_side = 0.5
current_profit: float = 0
trade_duration = 0
for trade in open_trades:
if trade.pair == pair:
if self.data_provider._exchange is None: # type: ignore
logger.error('No exchange available.')
return 0, 0, 0
else:
current_rate = self.data_provider._exchange.get_rate( # type: ignore
pair, refresh=False, side="exit", is_short=trade.is_short)
now = datetime.now(timezone.utc).timestamp()
trade_duration = int((now - trade.open_date_utc.timestamp()) / self.base_tf_seconds)
current_profit = trade.calc_profit_ratio(current_rate)
if trade.is_short:
market_side = 0
else:
market_side = 1
return market_side, current_profit, int(trade_duration)
def predict(
self, unfiltered_df: DataFrame, dk: FreqaiDataKitchen, **kwargs
) -> Tuple[DataFrame, npt.NDArray[np.int_]]:
"""
Filter the prediction features data and predict with it.
:param unfiltered_dataframe: Full dataframe for the current backtest period.
:return:
:pred_df: dataframe containing the predictions
:do_predict: np.array of 1s and 0s to indicate places where freqai needed to remove
data (NaNs) or felt uncertain about data (PCA and DI index)
"""
dk.find_features(unfiltered_df)
filtered_dataframe, _ = dk.filter_features(
unfiltered_df, dk.training_features_list, training_filter=False
)
filtered_dataframe = dk.normalize_data_from_metadata(filtered_dataframe)
dk.data_dictionary["prediction_features"] = filtered_dataframe
# optional additional data cleaning/analysis
self.data_cleaning_predict(dk)
pred_df = self.rl_model_predict(
dk.data_dictionary["prediction_features"], dk, self.model)
pred_df.fillna(0, inplace=True)
return (pred_df, dk.do_predict)
def rl_model_predict(self, dataframe: DataFrame,
dk: FreqaiDataKitchen, model: Any) -> DataFrame:
"""
A helper function to make predictions in the Reinforcement learning module.
:param dataframe: DataFrame = the dataframe of features to make the predictions on
:param dk: FreqaiDatakitchen = data kitchen for the current pair
:param model: Any = the trained model used to inference the features.
"""
output = pd.DataFrame(np.zeros(len(dataframe)), columns=dk.label_list)
def _predict(window):
observations = dataframe.iloc[window.index]
if self.live and self.rl_config.get('add_state_info', False):
market_side, current_profit, trade_duration = self.get_state_info(dk.pair)
observations['current_profit_pct'] = current_profit
observations['position'] = market_side
observations['trade_duration'] = trade_duration
res, _ = model.predict(observations, deterministic=True)
return res
output = output.rolling(window=self.CONV_WIDTH).apply(_predict)
return output
def build_ohlc_price_dataframes(self, data_dictionary: dict,
pair: str, dk: FreqaiDataKitchen) -> Tuple[DataFrame,
DataFrame]:
"""
Builds the train prices and test prices for the environment.
"""
pair = pair.replace(':', '')
train_df = data_dictionary["train_features"]
test_df = data_dictionary["test_features"]
# %-raw_volume_gen_shift-2_ETH/USDT_1h
# price data for model training and evaluation
tf = self.config['timeframe']
rename_dict = {'%-raw_open': 'open', '%-raw_low': 'low',
'%-raw_high': ' high', '%-raw_close': 'close'}
rename_dict_old = {f'%-{pair}raw_open_{tf}': 'open', f'%-{pair}raw_low_{tf}': 'low',
f'%-{pair}raw_high_{tf}': ' high', f'%-{pair}raw_close_{tf}': 'close'}
prices_train = train_df.filter(rename_dict.keys(), axis=1)
prices_train_old = train_df.filter(rename_dict_old.keys(), axis=1)
if prices_train.empty or not prices_train_old.empty:
if not prices_train_old.empty:
prices_train = prices_train_old
rename_dict = rename_dict_old
logger.warning('Reinforcement learning module didnt find the correct raw prices '
'assigned in feature_engineering_standard(). '
'Please assign them with:\n'
'dataframe["%-raw_close"] = dataframe["close"]\n'
'dataframe["%-raw_open"] = dataframe["open"]\n'
'dataframe["%-raw_high"] = dataframe["high"]\n'
'dataframe["%-raw_low"] = dataframe["low"]\n'
'inside `feature_engineering_standard()')
elif prices_train.empty:
raise OperationalException("No prices found, please follow log warning "
"instructions to correct the strategy.")
prices_train.rename(columns=rename_dict, inplace=True)
prices_train.reset_index(drop=True)
prices_test = test_df.filter(rename_dict.keys(), axis=1)
prices_test.rename(columns=rename_dict, inplace=True)
prices_test.reset_index(drop=True)
return prices_train, prices_test
def load_model_from_disk(self, dk: FreqaiDataKitchen) -> Any:
"""
Can be used by user if they are trying to limit_ram_usage *and*
perform continual learning.
For now, this is unused.
"""
exists = Path(dk.data_path / f"{dk.model_filename}_model").is_file()
if exists:
model = self.MODELCLASS.load(dk.data_path / f"{dk.model_filename}_model")
else:
logger.info('No model file on disk to continue learning from.')
return model
def _on_stop(self):
"""
Hook called on bot shutdown. Close SubprocVecEnv subprocesses for clean shutdown.
"""
if self.train_env:
self.train_env.close()
if self.eval_env:
self.eval_env.close()
# Nested class which can be overridden by user to customize further
class MyRLEnv(Base5ActionRLEnv):
"""
User can override any function in BaseRLEnv and gym.Env. Here the user
sets a custom reward based on profit and trade duration.
"""
def calculate_reward(self, action: int) -> float: # noqa: C901
"""
An example reward function. This is the one function that users will likely
wish to inject their own creativity into.
:param action: int = The action made by the agent for the current candle.
:return:
float = the reward to give to the agent for current step (used for optimization
of weights in NN)
"""
# first, penalize if the action is not valid
if not self._is_valid(action):
return -2
pnl = self.get_unrealized_profit()
factor = 100.
# you can use feature values from dataframe
rsi_now = self.raw_features[f"%-rsi-period-10_shift-1_{self.pair}_"
f"{self.config['timeframe']}"].iloc[self._current_tick]
# reward agent for entering trades
if (action in (Actions.Long_enter.value, Actions.Short_enter.value)
and self._position == Positions.Neutral):
if rsi_now < 40:
factor = 40 / rsi_now
else:
factor = 1
return 25 * factor
# discourage agent from not entering trades
if action == Actions.Neutral.value and self._position == Positions.Neutral:
return -1
max_trade_duration = self.rl_config.get('max_trade_duration_candles', 300)
if self._last_trade_tick:
trade_duration = self._current_tick - self._last_trade_tick
else:
trade_duration = 0
if trade_duration <= max_trade_duration:
factor *= 1.5
elif trade_duration > max_trade_duration:
factor *= 0.5
# discourage sitting in position
if (self._position in (Positions.Short, Positions.Long) and
action == Actions.Neutral.value):
return -1 * trade_duration / max_trade_duration
# close long
if action == Actions.Long_exit.value and self._position == Positions.Long:
if pnl > self.profit_aim * self.rr:
factor *= self.rl_config['model_reward_parameters'].get('win_reward_factor', 2)
return float(pnl * factor)
# close short
if action == Actions.Short_exit.value and self._position == Positions.Short:
if pnl > self.profit_aim * self.rr:
factor *= self.rl_config['model_reward_parameters'].get('win_reward_factor', 2)
return float(pnl * factor)
return 0.
def make_env(MyRLEnv: Type[gym.Env], env_id: str, rank: int,
seed: int, train_df: DataFrame, price: DataFrame,
monitor: bool = False,
env_info: Dict[str, Any] = {}) -> Callable:
"""
Utility function for multiprocessed env.
:param env_id: (str) the environment ID
:param num_env: (int) the number of environment you wish to have in subprocesses
:param seed: (int) the inital seed for RNG
:param rank: (int) index of the subprocess
:param env_info: (dict) all required arguments to instantiate the environment.
:return: (Callable)
"""
def _init() -> gym.Env:
env = MyRLEnv(df=train_df, prices=price, id=env_id, seed=seed + rank,
**env_info)
if monitor:
env = Monitor(env)
return env
set_random_seed(seed)
return _init

Some files were not shown because too many files have changed in this diff Show More