Compare commits

..

1139 Commits

Author SHA1 Message Date
Matthias
eea95f79aa Merge pull request #8862 from freqtrade/new_release
New release 2023.6
2023-07-07 20:08:27 +02:00
Matthias
7ba459db88 Version bump to 2023.6 2023-07-07 08:45:06 +02:00
Matthias
ab39144af8 Merge branch 'stable' into new_release 2023-07-07 08:44:49 +02:00
Matthias
092e30a159 Attempt CI without brew update 2023-07-06 21:22:03 +02:00
Matthias
5cd08ce554 Merge pull request #8825 from freqtrade/dependabot/pip/develop/ruff-0.0.275
Bump ruff from 0.0.272 to 0.0.275
2023-07-04 20:47:28 +02:00
Matthias
e51085ebc6 Merge pull request #8853 from freqtrade/dependabot/pip/develop/fastapi-0.99.1
Bump fastapi from 0.98.0 to 0.99.1
2023-07-03 16:13:18 +02:00
Matthias
817b6f9bde Merge pull request #8852 from freqtrade/dependabot/pip/develop/ast-comments-1.1.0
Bump ast-comments from 1.0.1 to 1.1.0
2023-07-03 11:09:03 +02:00
Matthias
b204a93d1c Merge pull request #8858 from freqtrade/dependabot/github_actions/develop/pypa/gh-action-pypi-publish-1.8.7
Bump pypa/gh-action-pypi-publish from 1.8.6 to 1.8.7
2023-07-03 10:49:22 +02:00
dependabot[bot]
977bfa08b7 Bump pypa/gh-action-pypi-publish from 1.8.6 to 1.8.7
Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.8.6 to 1.8.7.
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.8.6...v1.8.7)

---
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>
2023-07-03 03:42:51 +00:00
dependabot[bot]
ba6cba31be Bump fastapi from 0.98.0 to 0.99.1
Bumps [fastapi](https://github.com/tiangolo/fastapi) from 0.98.0 to 0.99.1.
- [Release notes](https://github.com/tiangolo/fastapi/releases)
- [Commits](https://github.com/tiangolo/fastapi/compare/0.98.0...0.99.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-03 03:29:53 +00:00
dependabot[bot]
1880f9ffa1 Bump ast-comments from 1.0.1 to 1.1.0
Bumps [ast-comments](https://github.com/t3rn0/ast-comments) from 1.0.1 to 1.1.0.
- [Commits](https://github.com/t3rn0/ast-comments/compare/1.0.1...1.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-03 03:29:48 +00:00
Matthias
0310a26b80 Fix documentation typo 2023-07-02 16:44:47 +00:00
Matthias
86956908d0 Merge branch 'develop' into dependabot/pip/develop/ruff-0.0.275 2023-07-02 18:35:43 +02:00
Matthias
e16c433cb8 Merge pull request #8829 from freqtrade/dependabot/pip/develop/mypy-1.4.1
Bump mypy from 1.3.0 to 1.4.1
2023-06-30 17:52:14 +02:00
Matthias
c5510491e5 Merge pull request #8830 from freqtrade/dependabot/pip/develop/sqlalchemy-2.0.17
Bump sqlalchemy from 2.0.16 to 2.0.17
2023-06-30 09:18:24 +02:00
Matthias
29725440c8 Simplify RPCMessageType schema definition 2023-06-29 12:28:25 +00:00
Matthias
accc1b509b Simplify class setups without inheritance 2023-06-29 12:16:10 +00:00
Matthias
4b06b4772d sqlalchemy - pre-commit 2023-06-29 11:53:58 +00:00
Matthias
a90b7c0bf5 Merge pull request #8835 from freqtrade/fix/pca-components
make sure default PCA behavior reduces parameter space size
2023-06-26 19:14:44 +02:00
Matthias
c4168055f9 Merge pull request #8831 from freqtrade/dependabot/pip/develop/fastapi-0.98.0
Bump fastapi from 0.97.0 to 0.98.0
2023-06-26 15:18:37 +02:00
dependabot[bot]
b12dbd2bea Bump ruff from 0.0.272 to 0.0.275
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.272 to 0.0.275.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.0.272...v0.0.275)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-26 13:17:59 +00:00
dependabot[bot]
be07ea5d4f Bump mypy from 1.3.0 to 1.4.1
Bumps [mypy](https://github.com/python/mypy) from 1.3.0 to 1.4.1.
- [Commits](https://github.com/python/mypy/compare/v1.3.0...v1.4.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-26 13:17:23 +00:00
Matthias
e729c5f9fd Merge pull request #8828 from freqtrade/dependabot/pip/develop/pytest-7.4.0
Bump pytest from 7.3.2 to 7.4.0
2023-06-26 15:17:02 +02:00
Matthias
5c8181fdd3 Merge pull request #8826 from freqtrade/dependabot/pip/develop/nbconvert-7.6.0
Bump nbconvert from 7.5.0 to 7.6.0
2023-06-26 15:16:11 +02:00
Matthias
3329279b71 Merge pull request #8827 from freqtrade/dependabot/pip/develop/mkdocs-material-9.1.17
Bump mkdocs-material from 9.1.16 to 9.1.17
2023-06-26 15:15:53 +02:00
robcaulk
6b201d525e make sure default PCA behavior reduces parameter space size 2023-06-26 14:42:59 +02:00
dependabot[bot]
8c2098c262 Bump fastapi from 0.97.0 to 0.98.0
Bumps [fastapi](https://github.com/tiangolo/fastapi) from 0.97.0 to 0.98.0.
- [Release notes](https://github.com/tiangolo/fastapi/releases)
- [Commits](https://github.com/tiangolo/fastapi/compare/0.97.0...0.98.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-06-26 03:58:27 +00:00
dependabot[bot]
6274197f85 Bump sqlalchemy from 2.0.16 to 2.0.17
Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 2.0.16 to 2.0.17.
- [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-06-26 03:58:21 +00:00
dependabot[bot]
ae42d57a26 Bump pytest from 7.3.2 to 7.4.0
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.3.2 to 7.4.0.
- [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.3.2...7.4.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-26 03:57:31 +00:00
dependabot[bot]
2d2699b0ad Bump mkdocs-material from 9.1.16 to 9.1.17
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.1.16 to 9.1.17.
- [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.1.16...9.1.17)

---
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-06-26 03:57:21 +00:00
dependabot[bot]
fec4cb3cf9 Bump nbconvert from 7.5.0 to 7.6.0
Bumps [nbconvert](https://github.com/jupyter/nbconvert) from 7.5.0 to 7.6.0.
- [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.5.0...v7.6.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-26 03:57:07 +00:00
Matthias
4a886e1b97 Merge pull request #8824 from freqtrade/refactor/optimize_reports
Refactor/optimize reports
2023-06-25 19:29:22 +02:00
Matthias
2c36a09b4f Merge pull request #8823 from freqtrade/fix/outlier-check
Fix/outlier check
2023-06-25 19:28:55 +02:00
Matthias
1717f86702 Extract edge output to proper module 2023-06-25 17:45:01 +02:00
Matthias
72504e62ad Extract btstorage methods 2023-06-25 17:42:58 +02:00
Matthias
65e8359908 Improve naming of new file 2023-06-25 17:11:13 +02:00
Matthias
794bca1379 Split optimize report generation from visualization 2023-06-25 17:09:57 +02:00
Matthias
5e084ad2e5 convert optimize_reports to a package 2023-06-25 17:08:41 +02:00
robcaulk
fca73531cf fix: use .shape instead of index for outliers 2023-06-25 16:34:44 +02:00
robcaulk
9da28e5328 bump datasieve 2023-06-25 15:44:24 +02:00
robcaulk
fd420738cd ensure outlier-check is returning as a numpy array from datasieve 2023-06-25 15:43:02 +02:00
Matthias
48e8965322 Don't add header if it's not needed 2023-06-25 15:35:57 +02:00
Matthias
5f98530ef9 Catch and send exceptions from websockets 2023-06-24 20:26:05 +02:00
Matthias
69087c30e7 Don't overwrite "type" with a variable 2023-06-24 20:18:24 +02:00
Matthias
6e143d4a5d Merge pull request #8818 from freqtrade/self
Use Self typing
2023-06-23 19:50:01 +02:00
Matthias
757c6dc5ca Use Self typing 2023-06-23 18:15:06 +02:00
Matthias
01dfca80ab Improve stop test behavior 2023-06-20 19:16:21 +02:00
Matthias
2f7b29ed34 Fix test_tsl_on_exchange_compatible_with_edge 2023-06-20 19:08:55 +02:00
Matthias
b49a118764 Fix exit_timeout test 2023-06-20 18:14:16 +02:00
Matthias
c7683a7b61 Improve docs wording 2023-06-20 06:57:48 +02:00
Matthias
5d60c62645 align list blocks 2023-06-20 06:55:19 +02:00
Matthias
96c2ca67e9 Add usage note for pairs.json file 2023-06-20 06:51:40 +02:00
Matthias
b0e5fb3940 Improve structure of download-data documentation 2023-06-20 06:50:59 +02:00
Matthias
8c54036fa5 Move Downloading tip from pairs file section 2023-06-20 06:45:56 +02:00
Matthias
859f7ff3de be explicit when loading pairs file. 2023-06-19 18:29:37 +02:00
Matthias
62f4bd27ec Merge pull request #8806 from freqtrade/dependabot/pip/develop/ccxt-3.1.44
Bump ccxt from 3.1.34 to 3.1.44
2023-06-19 17:59:05 +02:00
Robert Caulk
26c06e38be Merge pull request #8804 from freqtrade/dependabot/pip/develop/xgboost-1.7.6
Bump xgboost from 1.7.5 to 1.7.6
2023-06-19 14:35:34 +02:00
Matthias
78451447ac Merge pull request #8798 from freqtrade/dependabot/pip/develop/mkdocs-material-9.1.16
Bump mkdocs-material from 9.1.15 to 9.1.16
2023-06-19 14:25:58 +02:00
Matthias
0f7720dec0 Merge pull request #8801 from freqtrade/dependabot/pip/develop/pytest-mock-3.11.1
Bump pytest-mock from 3.10.0 to 3.11.1
2023-06-19 14:25:32 +02:00
Matthias
b9fe364d9c Merge pull request #8805 from freqtrade/dependabot/pip/develop/pre-commit-3.3.3
Bump pre-commit from 3.3.2 to 3.3.3
2023-06-19 13:06:07 +02:00
Matthias
97e7b60656 Merge pull request #8803 from freqtrade/dependabot/pip/develop/filelock-3.12.2
Bump filelock from 3.12.1 to 3.12.2
2023-06-19 13:05:42 +02:00
Matthias
936e49e8ee Merge pull request #8807 from freqtrade/dependabot/pip/develop/rich-13.4.2
Bump rich from 13.4.1 to 13.4.2
2023-06-19 13:05:11 +02:00
dependabot[bot]
6bc3439cb7 Bump pytest-mock from 3.10.0 to 3.11.1
Bumps [pytest-mock](https://github.com/pytest-dev/pytest-mock) from 3.10.0 to 3.11.1.
- [Release notes](https://github.com/pytest-dev/pytest-mock/releases)
- [Changelog](https://github.com/pytest-dev/pytest-mock/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-mock/compare/v3.10.0...v3.11.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-19 05:08:12 +00:00
Matthias
ec72c91b17 Merge pull request #8800 from freqtrade/dependabot/pip/develop/time-machine-2.10.0
Bump time-machine from 2.9.0 to 2.10.0
2023-06-19 07:01:56 +02:00
Matthias
2809379b56 Merge pull request #8799 from freqtrade/dependabot/pip/develop/nbconvert-7.5.0
Bump nbconvert from 7.4.0 to 7.5.0
2023-06-19 07:01:38 +02:00
dependabot[bot]
e965b2e454 Bump rich from 13.4.1 to 13.4.2
Bumps [rich](https://github.com/Textualize/rich) from 13.4.1 to 13.4.2.
- [Release notes](https://github.com/Textualize/rich/releases)
- [Changelog](https://github.com/Textualize/rich/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Textualize/rich/compare/v13.4.1...v13.4.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-19 03:58:02 +00:00
dependabot[bot]
d82a0ad7b5 Bump ccxt from 3.1.34 to 3.1.44
Bumps [ccxt](https://github.com/ccxt/ccxt) from 3.1.34 to 3.1.44.
- [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg)
- [Commits](https://github.com/ccxt/ccxt/compare/3.1.34...3.1.44)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-19 03:57:35 +00:00
dependabot[bot]
f04598c5e5 Bump pre-commit from 3.3.2 to 3.3.3
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 3.3.2 to 3.3.3.
- [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/v3.3.2...v3.3.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-19 03:57:29 +00:00
dependabot[bot]
f82d52c6d3 Bump xgboost from 1.7.5 to 1.7.6
Bumps [xgboost](https://github.com/dmlc/xgboost) from 1.7.5 to 1.7.6.
- [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.5...v1.7.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-19 03:57:17 +00:00
dependabot[bot]
fc0548ce0b Bump filelock from 3.12.1 to 3.12.2
Bumps [filelock](https://github.com/tox-dev/py-filelock) from 3.12.1 to 3.12.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.12.1...3.12.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-19 03:57:02 +00:00
dependabot[bot]
8cc763b664 Bump time-machine from 2.9.0 to 2.10.0
Bumps [time-machine](https://github.com/adamchainz/time-machine) from 2.9.0 to 2.10.0.
- [Changelog](https://github.com/adamchainz/time-machine/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/adamchainz/time-machine/compare/2.9.0...2.10.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-06-19 03:56:44 +00:00
dependabot[bot]
ed90e77ea0 Bump nbconvert from 7.4.0 to 7.5.0
Bumps [nbconvert](https://github.com/jupyter/nbconvert) from 7.4.0 to 7.5.0.
- [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.4.0...v7.5.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-19 03:56:40 +00:00
dependabot[bot]
1eb691d461 Bump mkdocs-material from 9.1.15 to 9.1.16
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.1.15 to 9.1.16.
- [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.1.15...9.1.16)

---
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-06-19 03:56:37 +00:00
Matthias
571dea6e9c Fix wrong final status on bg-tasks 2023-06-18 15:45:26 +02:00
Matthias
02071df8fa Merge pull request #8692 from freqtrade/feat/outsource-data-pipeline
Outsource data pipeline handling to improve flexibility
2023-06-18 13:39:36 +02:00
Robert Caulk
cca4fa1178 Update BaseClassifierModel.py 2023-06-18 11:31:03 +02:00
Robert Caulk
7e2f857aa5 Update BasePyTorchClassifier.py 2023-06-18 11:30:33 +02:00
Matthias
3d72d32845 Merge pull request #8369 from hippocritical/develop
backtest - lookahead_analysis
2023-06-18 08:29:08 +02:00
Matthias
52db6ac7d7 Use proper log level 2023-06-17 20:35:23 +02:00
Matthias
d94f3e7679 Add explicit tests for download-data
(without the command part)
2023-06-17 20:00:24 +02:00
Matthias
7af14d1985 Fix random test failure 2023-06-17 18:26:08 +02:00
Matthias
44a38e8362 Update download data tests 2023-06-17 18:22:47 +02:00
Matthias
0be4084eac Don't allow downloading wrong pairs
Prior to this, BTC/USDT:USDT could be downloaded to the spot directory, as it was filtered inproperly.
2023-06-17 18:14:58 +02:00
Matthias
937734365f Improve typehint for markets 2023-06-17 18:04:41 +02:00
Matthias
66b34edc0b Clarify variable name 2023-06-17 18:03:57 +02:00
Matthias
6f0f954686 Adjust mocks for new import location 2023-06-17 17:53:12 +02:00
Matthias
7453ff2fb5 Migrate download-data out of commands section 2023-06-17 17:53:12 +02:00
Matthias
b8ab6fe42b Improve wording of check command 2023-06-17 17:53:12 +02:00
Matthias
e0d5242a45 Reduce download-data verbosity 2023-06-17 17:53:12 +02:00
Robert Caulk
402a247c92 Merge pull request #8760 from initrv/rl-action-masks
Add MaskablePPO support
2023-06-17 16:28:43 +02:00
robcaulk
886b86f7c5 chore: bump datasieve 2023-06-17 16:14:48 +02:00
robcaulk
b0ab400ff3 fix: ensure test_size=0 is still accommodated 2023-06-17 15:39:33 +02:00
Matthias
bf872e8ed4 Simplify comparison depth 2023-06-17 14:25:46 +02:00
robcaulk
447feb16b4 Merge remote-tracking branch 'origin/develop' into use-datasieve 2023-06-17 13:26:35 +02:00
robcaulk
636f5753e1 Merge remote-tracking branch 'origin/feat/outsource-data-pipeline' into use-datasieve 2023-06-17 13:26:14 +02:00
robcaulk
11ff454b3b fix: ensure that a user setting up their own pipeline wont have conflicts with DI_values 2023-06-17 13:21:31 +02:00
Matthias
6bb75f0dd4 Simplify import if only one element is used 2023-06-17 10:12:36 +02:00
Matthias
1567cd2849 Use DOCS_LINK throughout 2023-06-17 09:10:54 +02:00
Matthias
34e7e3efea Simplify imports 2023-06-17 08:40:09 +02:00
Matthias
2c7aa9f721 Update doc wording 2023-06-17 08:37:38 +02:00
Matthias
24e806f081 Improve resiliance by using non-exchange controlled order attributes. 2023-06-16 19:58:35 +02:00
Matthias
b0396af4c4 Merge pull request #8791 from freqtrade/ci/catboost
Remove old version pin for catboost
2023-06-16 18:20:34 +02:00
Matthias
efaa959bfa Merge pull request #8790 from freqtrade/docs/link-to-articles
Add links to more FreqAI learning content
2023-06-16 18:20:05 +02:00
Matthias
7939716a5e Improve formatting of telegram /status messages 2023-06-16 18:00:22 +02:00
Matthias
4f834c8964 Remove old version pin for catboost 2023-06-16 15:15:40 +02:00
Robert Caulk
ffd7394adb Update freqai.md 2023-06-16 15:10:11 +02:00
Robert Caulk
2107dce2cd Update freqai-feature-engineering.md 2023-06-16 15:03:49 +02:00
robcaulk
72101f059d feat: ensure full backwards compatibility 2023-06-16 13:20:35 +02:00
robcaulk
75ec19062c chore: make DOCS_LINK in constants.py, ensure datasieve is added to setup.py 2023-06-16 13:06:21 +02:00
Matthias
64fcb1ed11 Better pin scikit-learn
caused by #7896
2023-06-16 10:15:45 +02:00
Matthias
dec3c0f374 Remove environment.yml completely 2023-06-16 07:02:40 +02:00
Matthias
1b86bf8a1d Don't include non-used parameters in command structure 2023-06-16 06:58:34 +02:00
Matthias
2cd9043c51 Make documentation discoverable / linked 2023-06-16 06:44:55 +02:00
Matthias
b3ef024e9e Don't use PurePosixPath 2023-06-15 20:43:05 +02:00
Matthias
964bf76469 Invert parameters for initialize_single_lookahead_analysis
otherwise their order is reversed before calling LookaheadAnalysis for no good reason
2023-06-15 20:42:26 +02:00
Matthias
ad74e65673 Simplify configuration setup 2023-06-15 20:26:45 +02:00
Matthias
ac36ba6592 Improve arguments file formatting 2023-06-15 20:15:44 +02:00
Matthias
ca88cac08b Remove unused code file 2023-06-15 06:39:00 +02:00
Matthias
d211bf47f1 Merge pull request #8767 from freqtrade/dependabot/pip/develop/stable-baselines3-2.0.0a13
Bump stable-baselines3 from 2.0.0a10 to 2.0.0a13
2023-06-15 06:06:44 +02:00
Matthias
11d7e7925e Fix random test failures 2023-06-14 20:34:18 +02:00
hippocritical
bc4d1c5326 Merge branch 'freqtrade:develop' into develop 2023-06-13 18:59:31 +02:00
Matthias
10b93f080a Merge pull request #8770 from freqtrade/dependabot/pip/develop/fastapi-0.97.0
Bump fastapi from 0.96.0 to 0.97.0
2023-06-13 10:56:02 +02:00
hippocritical
876ce85cd8 Merge branch 'freqtrade:develop' into develop 2023-06-12 23:04:02 +02:00
Matthias
9a7794c520 Improve behavior for when stoploss cancels without content
closes #8761
2023-06-12 20:29:23 +02:00
Matthias
1a4d94a6f3 OKX stop should convert contracts to amount 2023-06-12 20:01:26 +02:00
Matthias
1e44cfe2fc Improve stoploss test 2023-06-12 18:20:36 +02:00
Matthias
502090c199 Merge pull request #8765 from freqtrade/dependabot/pip/develop/ccxt-3.1.34
Bump ccxt from 3.1.23 to 3.1.34
2023-06-12 13:44:15 +02:00
Matthias
385d9d30b7 Merge pull request #8775 from freqtrade/dependabot/pip/develop/plotly-5.15.0
Bump plotly from 5.14.1 to 5.15.0
2023-06-12 13:33:33 +02:00
dependabot[bot]
e763e2ad35 Bump ccxt from 3.1.23 to 3.1.34
Bumps [ccxt](https://github.com/ccxt/ccxt) from 3.1.23 to 3.1.34.
- [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg)
- [Commits](https://github.com/ccxt/ccxt/compare/3.1.23...3.1.34)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-12 08:08:05 +00:00
Matthias
a89c647255 Merge pull request #8769 from freqtrade/dependabot/pip/develop/sqlalchemy-2.0.16
Bump sqlalchemy from 2.0.15 to 2.0.16
2023-06-12 10:01:59 +02:00
dependabot[bot]
1beaf6f05c Bump plotly from 5.14.1 to 5.15.0
Bumps [plotly](https://github.com/plotly/plotly.py) from 5.14.1 to 5.15.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.14.1...v5.15.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-06-12 07:26:38 +00:00
Matthias
21949c0446 bump sqlalchemy pre-commit 2023-06-12 09:23:58 +02:00
Matthias
6e6bccfd3e Merge pull request #8773 from freqtrade/dependabot/pip/develop/urllib3-2.0.3
Bump urllib3 from 2.0.2 to 2.0.3
2023-06-12 08:48:10 +02:00
Matthias
a7f882a7fe Merge pull request #8772 from freqtrade/dependabot/pip/develop/ruff-0.0.272
Bump ruff from 0.0.270 to 0.0.272
2023-06-12 08:47:50 +02:00
Matthias
0c4dab37d7 Merge pull request #8771 from freqtrade/dependabot/pip/develop/pytest-7.3.2
Bump pytest from 7.3.1 to 7.3.2
2023-06-12 08:47:32 +02:00
Matthias
1af4fa0419 Merge pull request #8774 from freqtrade/dependabot/pip/develop/orjson-3.9.1
Bump orjson from 3.9.0 to 3.9.1
2023-06-12 08:46:49 +02:00
Matthias
37495884d4 Merge pull request #8768 from freqtrade/dependabot/pip/develop/filelock-3.12.1
Bump filelock from 3.12.0 to 3.12.1
2023-06-12 08:13:32 +02:00
dependabot[bot]
2e087750e0 Bump fastapi from 0.96.0 to 0.97.0
Bumps [fastapi](https://github.com/tiangolo/fastapi) from 0.96.0 to 0.97.0.
- [Release notes](https://github.com/tiangolo/fastapi/releases)
- [Commits](https://github.com/tiangolo/fastapi/compare/0.96.0...0.97.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-06-12 05:12:52 +00:00
Matthias
64e803356a Merge pull request #8766 from freqtrade/dependabot/pip/develop/pydantic-1.10.9
Bump pydantic from 1.10.8 to 1.10.9
2023-06-12 07:07:03 +02:00
dependabot[bot]
7172bc0af3 Bump orjson from 3.9.0 to 3.9.1
Bumps [orjson](https://github.com/ijl/orjson) from 3.9.0 to 3.9.1.
- [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.9.0...3.9.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-12 03:58:02 +00:00
dependabot[bot]
feb6e5c466 Bump urllib3 from 2.0.2 to 2.0.3
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.0.2 to 2.0.3.
- [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/2.0.2...2.0.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-12 03:58:01 +00:00
dependabot[bot]
8b27b408c7 Bump ruff from 0.0.270 to 0.0.272
Bumps [ruff](https://github.com/charliermarsh/ruff) from 0.0.270 to 0.0.272.
- [Release notes](https://github.com/charliermarsh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/charliermarsh/ruff/compare/v0.0.270...v0.0.272)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-12 03:57:45 +00:00
dependabot[bot]
a9515dee81 Bump pytest from 7.3.1 to 7.3.2
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.3.1 to 7.3.2.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.3.1...7.3.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-12 03:57:33 +00:00
dependabot[bot]
71064c02e5 Bump sqlalchemy from 2.0.15 to 2.0.16
Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 2.0.15 to 2.0.16.
- [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-06-12 03:57:05 +00:00
dependabot[bot]
66dc1fd339 Bump filelock from 3.12.0 to 3.12.1
Bumps [filelock](https://github.com/tox-dev/py-filelock) from 3.12.0 to 3.12.1.
- [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.12.0...3.12.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-12 03:56:52 +00:00
dependabot[bot]
7542909e18 Bump stable-baselines3 from 2.0.0a10 to 2.0.0a13
Bumps [stable-baselines3](https://github.com/DLR-RM/stable-baselines3) from 2.0.0a10 to 2.0.0a13.
- [Release notes](https://github.com/DLR-RM/stable-baselines3/releases)
- [Commits](https://github.com/DLR-RM/stable-baselines3/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-12 03:56:48 +00:00
dependabot[bot]
a39f23a5c7 Bump pydantic from 1.10.8 to 1.10.9
Bumps [pydantic](https://github.com/pydantic/pydantic) from 1.10.8 to 1.10.9.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/main/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v1.10.8...v1.10.9)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-12 03:56:43 +00:00
hippocritical
d748cf6531 Merge branch 'freqtrade:develop' into develop 2023-06-11 22:55:03 +02:00
hippocritical
663cfc6211 fixing tests 2023-06-11 22:53:21 +02:00
steam
bdb535d0e6 add maskable eval callback multiproc 2023-06-11 22:20:15 +03:00
steam
5dee86eda7 fix action_masks typing list 2023-06-11 21:44:57 +03:00
steam
c36547a563 add maskable eval callback 2023-06-11 20:05:53 +03:00
steam
afd54d39a5 add action_masks 2023-06-11 20:00:12 +03:00
Matthias
5844756ba1 Add test and fix for stop-price == limit price
closes #8758
2023-06-11 17:20:35 +02:00
Matthias
4a800fe467 Add explicit test for get_stop_limit_rate 2023-06-11 17:17:41 +02:00
Matthias
fd940dbba2 Merge pull request #8530 from freqtrade/feat/pairlistconfig
Provide pairlists via API
2023-06-11 12:43:38 +02:00
Matthias
320b3e20a6 Use correct variable for candle-type when loading data
closes #8757
2023-06-11 11:58:18 +02:00
Matthias
fc11c79b77 Fix not working date format output 2023-06-11 08:51:20 +02:00
Matthias
87e144a95a Update webserver tags 2023-06-11 08:24:16 +02:00
Matthias
9ef814689e Update endpoint in rest-client 2023-06-11 08:18:01 +02:00
hippocritical
2bd66fbb47 Merge branch 'freqtrade:develop' into develop 2023-06-11 00:21:04 +02:00
hippocritical
9eceb2f38c Merge remote-tracking branch 'origin/develop' into develop 2023-06-11 00:20:02 +02:00
hippocritical
1da1972c18 added test for config overrides 2023-06-11 00:18:34 +02:00
Matthias
e332fbfb47 Add explicit test for okx get_stop_params 2023-06-10 16:56:41 +02:00
Matthias
2806110869 Add explicit test for okx cancel_stop 2023-06-10 16:56:41 +02:00
Matthias
cfe88f06d2 Improve behavior of okx rebuys when using stop on exchange
closes #8755
2023-06-10 16:56:41 +02:00
robcaulk
ad8a4897ce remove unnecessary example in feature_engineering.md 2023-06-10 16:13:28 +02:00
Matthias
4f15b30339 Merge pull request #8590 from AchmadFathoni/develop
Fix disrepancy in freqai doc code example
2023-06-10 15:27:01 +02:00
robcaulk
229ee643cd revert change to deal with FT pinning old scikit-learn version 2023-06-10 13:24:09 +02:00
robcaulk
41e37f9d32 improve docs, update doc strings 2023-06-10 13:11:47 +02:00
robcaulk
d9bdd879ab improve migration doc 2023-06-10 13:00:59 +02:00
robcaulk
f8d7c2e21d add migration guide, add protections and migration assistance 2023-06-10 12:48:27 +02:00
robcaulk
4cdd6bc6c3 avoid using ram for unnecessary train_df, fix some deprecation warnings 2023-06-10 12:07:03 +02:00
robcaulk
e246259792 avoid manual pipeline validation 2023-06-10 11:40:57 +02:00
Matthias
3523f564bd Improve Log reduction and corresponding test 2023-06-10 09:44:20 +02:00
Matthias
265d782af8 Implement the requested changes. 2023-06-10 09:30:34 +02:00
hippocritical
94ca2988a0 updated docs 2023-06-09 23:32:58 +02:00
hippocritical
6656740f21 Moved config overrides to its' own function
Added config overrides to dry_run_wallet and max_open_trades to avoid false positives.
2023-06-09 22:11:30 +02:00
Matthias
99842402f7 Further reduce unnecessary output 2023-06-09 07:18:35 +02:00
Matthias
16b3363970 Fix type problem 2023-06-09 07:16:06 +02:00
Matthias
b89390c06b Reduce log verbosity during bias tester runs 2023-06-09 07:15:36 +02:00
Matthias
c8e827d483 Merge branch 'develop' into pr/hippocritical/8369 2023-06-09 07:03:25 +02:00
Matthias
fc8c6b06ad Extract set-log-levels from main logging module 2023-06-09 06:59:08 +02:00
Matthias
e3056b141a Move logging tests to dedicated test file 2023-06-09 06:51:12 +02:00
Matthias
05ea36f03b Fix performance when running tons of backtests 2023-06-09 06:45:34 +02:00
Matthias
61f1701e56 Bump version to 2023.5.1 2023-06-08 22:02:33 +02:00
Matthias
beaaa94406 Improve test for reload-markets timings, fix bug
closes #8714
2023-06-08 21:03:12 +02:00
Matthias
6b736c49d4 Dont persist Backtesting to avoid memory leak 2023-06-08 20:13:28 +02:00
robcaulk
33b028b104 ensure data kitchen thread count is propagated to pipeline 2023-06-08 12:33:08 +02:00
robcaulk
88337b6c5e convert to using constants in data_drawer. Remove unneeded check_if_pred_in_spaces function 2023-06-08 12:19:42 +02:00
robcaulk
e39e40dc60 improve documentation of pipeline building/customization 2023-06-08 11:56:31 +02:00
Matthias
317e0b5f2b Avoid nested loops in telegram for force* scenarios
closes #8731
2023-06-08 07:08:06 +02:00
Matthias
4404d112a9 Merge pull request #8749 from freqtrade/dependabot/docker/python-3.11.4-slim-bullseye
Bump python from 3.10.11-slim-bullseye to 3.11.4-slim-bullseye
2023-06-08 06:30:36 +02:00
dependabot[bot]
f81139b97c Bump python from 3.10.11-slim-bullseye to 3.11.4-slim-bullseye
Bumps python from 3.10.11-slim-bullseye to 3.11.4-slim-bullseye.

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-08 03:56:43 +00:00
robcaulk
14557f2d32 merge develop into outsource-data-pipeline 2023-06-07 19:24:21 +02:00
robcaulk
f10f00f5e8 Merge remote-tracking branch 'origin' into use-datasieve 2023-06-07 19:23:36 +02:00
hippocritical
675a97c1cb Merge branch 'freqtrade:develop' into develop 2023-06-07 19:22:42 +02:00
robcaulk
c066f014e3 fix docs 2023-06-07 18:36:07 +02:00
robcaulk
6d39adc739 bump datasieve version 2023-06-07 18:29:49 +02:00
robcaulk
135aaa2be2 update docs, improve the interaction with define_data_pipeline 2023-06-07 18:26:49 +02:00
robcaulk
dc577d2a1a update to new datasieve interface, add noise to pipeline 2023-06-07 17:58:27 +02:00
robcaulk
4d4589becd fix isort in tests 2023-06-07 14:00:00 +02:00
robcaulk
f7f88aa14d fix pickle file name 2023-06-07 09:28:56 +02:00
robcaulk
17d74429b5 Merge remote-tracking branch 'origin/feat/outsource-data-pipeline' into use-datasieve 2023-06-07 09:08:09 +02:00
robcaulk
5ac141f72b convert to new datasieve api 2023-06-06 21:05:51 +02:00
Matthias
0b8ef1b880 Fix devcontainer invalid key 2023-06-05 21:13:52 +02:00
Matthias
c269eef77e Remove unnecessary calc_profit_ratio call 2023-06-05 21:10:29 +02:00
Matthias
21172802de Devcontainer image should contain as many dependencies as possible 2023-06-05 20:30:46 +02:00
Matthias
17b8cb2f7c Merge pull request #8738 from freqtrade/dependabot/pip/develop/ccxt-3.1.23
Bump ccxt from 3.1.13 to 3.1.23
2023-06-05 18:06:29 +02:00
dependabot[bot]
6ec91d11ae Bump ccxt from 3.1.13 to 3.1.23
Bumps [ccxt](https://github.com/ccxt/ccxt) from 3.1.13 to 3.1.23.
- [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg)
- [Commits](https://github.com/ccxt/ccxt/compare/3.1.13...3.1.23)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-05 07:40:33 +00:00
Matthias
984dec12df Merge pull request #8739 from freqtrade/dependabot/pip/develop/pandas-2.0.2
Bump pandas from 2.0.1 to 2.0.2
2023-06-05 09:39:55 +02:00
Matthias
11f2bbdd08 Merge pull request #8740 from freqtrade/dependabot/pip/develop/types-requests-2.31.0.1
Bump types-requests from 2.31.0.0 to 2.31.0.1
2023-06-05 09:39:37 +02:00
Matthias
41f5c32526 Merge pull request #8741 from freqtrade/dependabot/pip/develop/mkdocs-material-9.1.15
Bump mkdocs-material from 9.1.14 to 9.1.15
2023-06-05 08:25:52 +02:00
Matthias
4dcb6395ef Bump pre-commit requests types 2023-06-05 07:13:09 +02:00
Matthias
46ad8afeb9 Merge pull request #8736 from freqtrade/dependabot/pip/develop/orjson-3.9.0
Bump orjson from 3.8.14 to 3.9.0
2023-06-05 07:10:27 +02:00
Matthias
49891967f2 Merge pull request #8734 from freqtrade/dependabot/pip/develop/fastapi-0.96.0
Bump fastapi from 0.95.2 to 0.96.0
2023-06-05 07:07:38 +02:00
Matthias
4acb0830e3 Merge pull request #8735 from freqtrade/dependabot/pip/develop/rich-13.4.1
Bump rich from 13.3.5 to 13.4.1
2023-06-05 07:07:20 +02:00
dependabot[bot]
e61659a2bc Bump mkdocs-material from 9.1.14 to 9.1.15
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.1.14 to 9.1.15.
- [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.1.14...9.1.15)

---
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-06-05 03:57:43 +00:00
dependabot[bot]
c2125698a7 Bump types-requests from 2.31.0.0 to 2.31.0.1
Bumps [types-requests](https://github.com/python/typeshed) from 2.31.0.0 to 2.31.0.1.
- [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-06-05 03:57:22 +00:00
dependabot[bot]
093181e8f2 Bump pandas from 2.0.1 to 2.0.2
Bumps [pandas](https://github.com/pandas-dev/pandas) from 2.0.1 to 2.0.2.
- [Release notes](https://github.com/pandas-dev/pandas/releases)
- [Commits](https://github.com/pandas-dev/pandas/compare/v2.0.1...v2.0.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-05 03:57:15 +00:00
dependabot[bot]
bdaf230bd1 Bump orjson from 3.8.14 to 3.9.0
Bumps [orjson](https://github.com/ijl/orjson) from 3.8.14 to 3.9.0.
- [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.14...3.9.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-05 03:56:45 +00:00
dependabot[bot]
9dcab313b5 Bump rich from 13.3.5 to 13.4.1
Bumps [rich](https://github.com/Textualize/rich) from 13.3.5 to 13.4.1.
- [Release notes](https://github.com/Textualize/rich/releases)
- [Changelog](https://github.com/Textualize/rich/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Textualize/rich/compare/v13.3.5...v13.4.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-05 03:56:40 +00:00
dependabot[bot]
c9bbeedd88 Bump fastapi from 0.95.2 to 0.96.0
Bumps [fastapi](https://github.com/tiangolo/fastapi) from 0.95.2 to 0.96.0.
- [Release notes](https://github.com/tiangolo/fastapi/releases)
- [Commits](https://github.com/tiangolo/fastapi/compare/0.95.2...0.96.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-06-05 03:56:37 +00:00
Robert Caulk
94bc91ef57 Update tests/freqai/test_freqai_datakitchen.py
Co-authored-by: Matthias <xmatthias@outlook.com>
2023-06-04 21:50:13 +02:00
Matthias
7a726da691 Update cached binance leverage tiers 2023-06-04 20:28:08 +02:00
Matthias
71b81ee7cd Add margin_mode to pairlists callback 2023-06-04 13:25:39 +02:00
Matthias
f61ae9c7e2 Merge branch 'develop' into feat/pairlistconfig 2023-06-04 08:33:45 +02:00
Matthias
12e31208e1 Update typedDict type used with pydantic 2023-06-03 12:33:44 +02:00
Matthias
ac7419e975 Split trademode response value into trade_mode and margin-mode 2023-06-03 11:58:55 +02:00
Matthias
72f4e1475c Bump api version 2023-06-03 11:58:55 +02:00
Matthias
74254bb893 Add /exchanges endpoint to list available exchanges 2023-06-03 11:58:55 +02:00
Matthias
54bf1634c7 Refactor validExchangesType to separate types package 2023-06-03 11:58:55 +02:00
Matthias
6f928b826f Update types for build_exchange_list_entry 2023-06-03 11:58:55 +02:00
Matthias
cc04f3279a bump pre-commit mypy version 2023-06-03 11:58:55 +02:00
Matthias
fcb960185e Clarify function naming 2023-06-03 11:58:55 +02:00
Matthias
250ae2d006 Enhance list-exchanges with more information 2023-06-03 11:58:55 +02:00
Matthias
b5d1017779 Update list_exchanges to use a dict internally 2023-06-03 11:58:55 +02:00
Matthias
26ed17fa02 Merge pull request #8725 from freqtrade/dependabot/pip/cryptography-41.0.0
Bump cryptography from 40.0.1 to 41.0.1
2023-06-03 11:32:51 +02:00
Matthias
e890bc0718 Don't bump pi version, but bump regular version 2023-06-03 08:30:38 +02:00
Matthias
10ea2b44c7 Update test line length 2023-06-03 06:59:22 +02:00
Matthias
d9d1735333 Extract ExchangePayload updating 2023-06-03 06:57:25 +02:00
Matthias
48328fb29d reset candle_type_def 2023-06-03 06:52:25 +02:00
dependabot[bot]
49c0fdf367 Bump cryptography from 40.0.1 to 41.0.0
Bumps [cryptography](https://github.com/pyca/cryptography) from 40.0.1 to 41.0.0.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/40.0.1...41.0.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-02 20:23:40 +00:00
Matthias
ac046d6a2d Allow setting the exchange explicitly 2023-06-02 10:14:11 +02:00
Matthias
af16ce874c Allow webserver mode to cache multiple exchanges 2023-06-02 09:50:40 +02:00
Matthias
e2594e7494 Align tests to use webserver mode 2023-06-01 20:46:28 +02:00
Matthias
77e3e9e899 Move pairlists and background tasks API's to separate file 2023-06-01 20:40:12 +02:00
Matthias
cafc9479b7 Merge branch 'develop' into feat/pairlistconfig 2023-06-01 20:33:28 +02:00
Matthias
8f02050fde Merge pull request #8721 from freqtrade/robcaulk-patch-1
Update freqai.md
2023-06-01 20:12:52 +02:00
Matthias
565c0496d9 Bump httpx min requirement 2023-06-01 20:10:57 +02:00
Matthias
d0f900f567 set HTTPX level to warning
closes #8717
2023-06-01 20:09:59 +02:00
Robert Caulk
30dd63fcb9 Update freqai.md 2023-06-01 15:54:05 +02:00
Matthias
8aee368f60 auto-inject webserver mode dependency 2023-06-01 07:07:02 +02:00
Matthias
e0d9603e99 Raise correct httperrorcode for webserver-only endpoitns 2023-06-01 07:03:35 +02:00
Matthias
88ecb935b9 Add "failed" state to bgjob task response 2023-05-31 20:22:22 +02:00
Matthias
9c6fee3841 Enable gate futures for spread-filter again
closes #8687
2023-05-31 17:14:22 +02:00
Matthias
5fc8426b9b Improve handling of order cancelation failures with force_exit
closes #8708
2023-05-31 17:06:51 +02:00
Matthias
430cd24bbc Invert order (exit trade 3 before trade 4) 2023-05-31 15:00:09 +02:00
Matthias
08d040db14 Slightly update force_exit test 2023-05-31 14:59:41 +02:00
Matthias
5311614d54 Update force exit wording 2023-05-31 14:33:09 +02:00
Matthias
193d88c9c8 Double-check cancelling stop order didn't close the trade 2023-05-31 14:12:03 +02:00
Matthias
1f543666f4 Improve test for reload-markets timings, fix bug
closes #8714
2023-05-31 11:46:31 +02:00
Matthias
fd955028a8 Update tests for new background method 2023-05-31 07:08:27 +02:00
Matthias
7bccf2129f Introduce background_job endpoints 2023-05-31 07:00:20 +02:00
robcaulk
f6a32f4ffd bump version 2023-05-29 23:35:24 +02:00
Matthias
b666c418bb Don't use variables for simple debug values 2023-05-29 17:33:11 +02:00
Matthias
af1dbf7dff Extract get_rate_from_ticker from get_rate method 2023-05-29 17:31:57 +02:00
Matthias
f074383d6a Extract orderbook logic into separate method 2023-05-29 17:24:04 +02:00
robcaulk
785f0d396f bump datasieve version 2023-05-29 16:44:53 +02:00
Matthias
6315516d50 Improve volumepairlist defaults 2023-05-29 15:18:46 +02:00
robcaulk
6237806817 bump datasieve to 0.0.8 2023-05-29 15:18:28 +02:00
robcaulk
e572653616 bring classifier/rl up to new paradigm. ensure tests pass. remove old code. add documentation, add new example transform 2023-05-29 13:33:29 +02:00
Matthias
12e8e29b4e Merge pull request #8703 from freqtrade/dependabot/pip/develop/types-requests-2.31.0.0
Bump types-requests from 2.30.0.0 to 2.31.0.0
2023-05-29 08:39:51 +02:00
Matthias
5ecf93e84b Merge pull request #8705 from freqtrade/dependabot/pip/develop/ccxt-3.1.13
Bump ccxt from 3.1.5 to 3.1.13
2023-05-29 08:39:32 +02:00
Matthias
9f1bdc19aa Bump ruff pre-commit version 2023-05-29 08:10:29 +02:00
Matthias
35836479de Bump requests pre-commit dependency 2023-05-29 08:09:56 +02:00
Matthias
e03e8547c0 Merge pull request #8707 from freqtrade/dependabot/pip/develop/orjson-3.8.14
Bump orjson from 3.8.12 to 3.8.14
2023-05-29 08:08:36 +02:00
Matthias
bcd27f5517 Merge pull request #8706 from freqtrade/dependabot/pip/develop/ruff-0.0.270
Bump ruff from 0.0.269 to 0.0.270
2023-05-29 08:08:21 +02:00
Matthias
ce02a3ff33 Merge pull request #8704 from freqtrade/dependabot/pip/develop/cachetools-5.3.1
Bump cachetools from 5.3.0 to 5.3.1
2023-05-29 08:08:06 +02:00
Matthias
85de8ca63f Merge pull request #8702 from freqtrade/dependabot/pip/develop/pytest-cov-4.1.0
Bump pytest-cov from 4.0.0 to 4.1.0
2023-05-29 08:07:46 +02:00
Matthias
4c54640800 Merge pull request #8701 from freqtrade/dependabot/pip/develop/pydantic-1.10.8
Bump pydantic from 1.10.7 to 1.10.8
2023-05-29 08:07:29 +02:00
dependabot[bot]
cb7a0f9bff Bump orjson from 3.8.12 to 3.8.14
Bumps [orjson](https://github.com/ijl/orjson) from 3.8.12 to 3.8.14.
- [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.12...3.8.14)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-29 03:57:23 +00:00
dependabot[bot]
90808683e2 Bump ruff from 0.0.269 to 0.0.270
Bumps [ruff](https://github.com/charliermarsh/ruff) from 0.0.269 to 0.0.270.
- [Release notes](https://github.com/charliermarsh/ruff/releases)
- [Changelog](https://github.com/charliermarsh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/charliermarsh/ruff/compare/v0.0.269...v0.0.270)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-29 03:57:13 +00:00
dependabot[bot]
8fdec5f3a6 Bump ccxt from 3.1.5 to 3.1.13
Bumps [ccxt](https://github.com/ccxt/ccxt) from 3.1.5 to 3.1.13.
- [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg)
- [Commits](https://github.com/ccxt/ccxt/compare/3.1.5...3.1.13)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-29 03:57:05 +00:00
dependabot[bot]
4e9a43ebf6 Bump cachetools from 5.3.0 to 5.3.1
Bumps [cachetools](https://github.com/tkem/cachetools) from 5.3.0 to 5.3.1.
- [Changelog](https://github.com/tkem/cachetools/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/tkem/cachetools/compare/v5.3.0...v5.3.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-29 03:56:56 +00:00
dependabot[bot]
3bc390cb2e Bump types-requests from 2.30.0.0 to 2.31.0.0
Bumps [types-requests](https://github.com/python/typeshed) from 2.30.0.0 to 2.31.0.0.
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-29 03:56:53 +00:00
dependabot[bot]
12af6ea766 Bump pytest-cov from 4.0.0 to 4.1.0
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 4.0.0 to 4.1.0.
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v4.0.0...v4.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-29 03:56:50 +00:00
dependabot[bot]
51ba4d14e9 Bump pydantic from 1.10.7 to 1.10.8
Bumps [pydantic](https://github.com/pydantic/pydantic) from 1.10.7 to 1.10.8.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/v1.10.8/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v1.10.7...v1.10.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-29 03:56:46 +00:00
hippocritical
6b3b5f201d export_to_csv: Added forced conversion of float64 to int to remove the .0 values once and for all ... 2023-05-28 22:13:29 +02:00
hippocritical
fc887efd4b Merge branch 'freqtrade:develop' into develop 2023-05-28 20:53:39 +02:00
hippocritical
0874b1a959 Merge remote-tracking branch 'origin/develop' into develop 2023-05-28 20:53:16 +02:00
hippocritical
eec7837167 - modified help-string for the cli-option lookahead_analysis_exportfilename
- moved doc from utils.md to lookahead-analysis.md and modified it (unfinished)
- added a check to automatically edit the config['backtest_cache'] to be 'none'
- adjusted test_lookahead_helper_export_to_csv to catch the new catching of errors
- adjusted test_lookahead_helper_text_table_lookahead_analysis_instances to catch the new catching of errors
- changed lookahead_analysis.start result-reporting to show that not enough trades were caught including x of y
2023-05-28 20:52:58 +02:00
Matthias
43f1537383 Merge pull request #8697 from freqtrade/new_release
New release 2023.5
2023-05-28 19:59:33 +02:00
Matthias
1317de8c1c Add rudimentary description per pairlist 2023-05-28 18:21:23 +02:00
Matthias
dbb92f686f Merge pull request #8696 from freqtrade/feat/no_roi
allow no / empty minimal_roi
2023-05-28 15:36:01 +02:00
hippocritical
aa8eb14461 Merge branch 'freqtrade:develop' into develop 2023-05-28 12:11:29 +02:00
Matthias
3d05669f61 Merge branch 'develop' into feat/pairlistconfig 2023-05-28 10:01:43 +02:00
Matthias
c9f78afe65 Bump version to 2023.5 2023-05-28 10:00:39 +02:00
Matthias
a3473f3f60 Better handling of shift 2023-05-28 10:00:39 +02:00
Matthias
4eb4275331 Fix volatilityfilter behavior
closes #8698
2023-05-28 10:00:38 +02:00
Matthias
8a86169256 Better handling of shift 2023-05-28 09:59:57 +02:00
Matthias
8ec0469b11 Fix volatilityfilter behavior
closes #8698
2023-05-28 09:53:53 +02:00
hippocritical
9bb25be880 modified help-string for the cli-option lookahead_analysis_exportfilename
moved doc from utils.md to lookahead-analysis.md and modified it (unfinished)
added a check to automatically edit the config['backtest_cache'] to be 'none'
2023-05-27 22:31:47 +02:00
hippocritical
0ed84fbcc1 added test_initialize_single_lookahead_analysis
A check for a random variable should be enough, right? :)
2023-05-27 20:47:59 +02:00
hippocritical
a7426755bc added a check for bias1.
Looking at has_bias should be enough to statisfy the test.
The tests could be extended with thecking the buy/sell signals and the dataframe itself -
but this should be sufficient for now.
2023-05-27 20:35:45 +02:00
Matthias
df5e6409a4 Bump develop version to 2023.6-dev 2023-05-27 20:18:39 +02:00
Matthias
b9121274fb Merge branch 'stable' into new_release 2023-05-27 20:01:51 +02:00
Matthias
5649d1d4da Convert minimal_roi to list comprehension 2023-05-27 19:57:12 +02:00
Matthias
36c82ad67c Update documentation for min_roi 2023-05-27 19:40:02 +02:00
Matthias
35a388bf9a Don't force min_roi to have content 2023-05-27 19:39:00 +02:00
hippocritical
ee37693729 Merge branch 'freqtrade:develop' into develop 2023-05-27 19:23:01 +02:00
hippocritical
05f0b32e3b Merge remote-tracking branch 'origin/develop' into develop 2023-05-27 19:22:23 +02:00
hippocritical
636298bb71 added test_lookahead_helper_export_to_csv 2023-05-27 19:15:35 +02:00
Matthias
bd266f654e Properly handle invalid pairlists type before config validation
closes #8695
2023-05-27 08:19:56 +02:00
robcaulk
31e19add27 start transition toward outsourcing the data pipeline with objective of improving pipeline flexibility 2023-05-26 18:40:14 +02:00
hippocritical
eb31b574c1 added returns to text_table_lookahead_analysis_instances
filled in test_lookahead_helper_text_table_lookahead_analysis_instances
2023-05-26 12:55:54 +02:00
hippocritical
9366c77e42 Merge branch 'freqtrade:develop' into develop 2023-05-26 08:38:32 +02:00
Matthias
af7afa80a9 remove gone-wrong import 2023-05-26 06:44:48 +02:00
Matthias
c23a045de4 Merge pull request #8622 from freqtrade/frog-forceenter-price
Add check for None prices in forceenter REST API script
2023-05-25 19:22:03 +02:00
Matthias
61ee77e07e Merge pull request #8690 from freqtrade/remove-tb-warning
Update base_tensorboard.py
2023-05-25 18:21:05 +02:00
Robert Caulk
f647fb342b Update base_tensorboard.py
Remove incorrect warning message.
2023-05-25 16:35:06 +02:00
Robert Caulk
d4183b3fcb Merge pull request #8688 from freqtrade/dependabot/pip/develop/stable-baselines3-2.0.0a10
Bump stable-baselines3 from 2.0.0a9 to 2.0.0a10
2023-05-25 09:24:55 +02:00
Matthias
6b0b62dadf Merge pull request #8686 from freqtrade/fix/8681
okx stop improvements
2023-05-25 06:43:22 +02:00
dependabot[bot]
9e9f9b21e5 Bump stable-baselines3 from 2.0.0a9 to 2.0.0a10
Bumps [stable-baselines3](https://github.com/DLR-RM/stable-baselines3) from 2.0.0a9 to 2.0.0a10.
- [Release notes](https://github.com/DLR-RM/stable-baselines3/releases)
- [Commits](https://github.com/DLR-RM/stable-baselines3/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-25 04:24:42 +00:00
Matthias
91e009bf6d Merge pull request #8677 from richardjozsa/develop
Stable baselines 3 seeding update
2023-05-25 06:23:34 +02:00
Matthias
9e75c768c0 Improve responses for evaluate get endpoints 2023-05-24 21:01:39 +02:00
Matthias
4c52109fa3 Handle pairlist evaluation errors gracefully 2023-05-24 20:37:23 +02:00
Matthias
b5ed693bee Extrac OKX convert stop order, call for regular orders, too 2023-05-24 20:15:36 +02:00
Matthias
b8220ee0f7 Improve recovery detection by skipping open orders 2023-05-24 18:19:14 +02:00
Matthias
a0336c83c3 Update method casing in tests 2023-05-23 19:22:58 +02:00
Matthias
6efc62e4cd Add test which verifies #8680 won't happen again 2023-05-23 19:10:10 +02:00
Matthias
6292d1af6d Use camelcase version of private fapi method
closes #8680
2023-05-23 19:07:58 +02:00
Matthias
9ffdaceef3 Bybit - use Proxy 2023-05-23 07:15:41 +02:00
Matthias
b2d9b914ea Merge pull request #8679 from freqtrade/dependabot/pip/requests-2.31.0
Bump requests from 2.30.0 to 2.31.0
2023-05-23 07:15:35 +02:00
dependabot[bot]
1e10b25e3d Bump requests from 2.30.0 to 2.31.0
Bumps [requests](https://github.com/psf/requests) from 2.30.0 to 2.31.0.
- [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.30.0...v2.31.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-22 21:58:08 +00:00
Matthias
c2010d160f Merge branch 'develop' into feat/pairlistconfig 2023-05-22 19:59:20 +02:00
Matthias
5b29e710dc Merge pull request #8004 from wizrds/fix/dataframe_json
Revert DataFrame serialization in Producer mode (>pandas 2.0)
2023-05-22 19:58:05 +02:00
Matthias
33e25434b4 Change statuscode to 202 2023-05-22 19:43:27 +02:00
Matthias
e70cafe578 Merge branch 'develop' into pr/wizrds/8004 2023-05-22 18:24:32 +02:00
Matthias
44bdac5e8c Improve developer docs with some minor improvements 2023-05-22 18:23:33 +02:00
Matthias
85c14578e2 Merge pull request #8661 from freqtrade/feat/datetimehelpers
Add datetime helpers, reduce arrow usage to a minimum
2023-05-22 18:22:29 +02:00
Matthias
09aaf894c6 Merge pull request #8673 from freqtrade/dependabot/pip/develop/ruff-0.0.269
Bump ruff from 0.0.267 to 0.0.269
2023-05-22 11:51:27 +02:00
Matthias
795e3e324f Merge pull request #8674 from freqtrade/dependabot/pip/develop/sqlalchemy-2.0.15
Bump sqlalchemy from 2.0.13 to 2.0.15
2023-05-22 11:33:55 +02:00
Richard Jozsa
39f4fb8797 Merge branch 'freqtrade:develop' into develop 2023-05-22 08:36:25 +00:00
Richard Jozsa
d26aa231fc Stable baselines updates, and fix
There was a seeding error in SB3 after the gymnasium update, the stable baselines team has patched and fixed the issue, but the reset function has to be aligned.
2023-05-22 10:36:07 +02:00
Matthias
6d9b8a4a99 Merge pull request #8669 from freqtrade/dependabot/pip/develop/ccxt-3.1.5
Bump ccxt from 3.0.103 to 3.1.5
2023-05-22 09:23:56 +02:00
dependabot[bot]
2242d544fc Bump ruff from 0.0.267 to 0.0.269
Bumps [ruff](https://github.com/charliermarsh/ruff) from 0.0.267 to 0.0.269.
- [Release notes](https://github.com/charliermarsh/ruff/releases)
- [Changelog](https://github.com/charliermarsh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/charliermarsh/ruff/compare/v0.0.267...v0.0.269)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-22 07:21:19 +00:00
Matthias
ad5f0307b7 bump sqlalchemy precommit 2023-05-22 09:21:18 +02:00
Matthias
8fccd98eca Merge pull request #8676 from freqtrade/dependabot/pip/develop/mkdocs-material-9.1.14
Bump mkdocs-material from 9.1.12 to 9.1.14
2023-05-22 09:20:31 +02:00
Matthias
e71b66f5c2 Merge pull request #8670 from freqtrade/dependabot/pip/develop/fastapi-0.95.2
Bump fastapi from 0.95.1 to 0.95.2
2023-05-22 09:19:38 +02:00
Matthias
0e99fe349c Merge pull request #8671 from freqtrade/dependabot/pip/develop/pre-commit-3.3.2
Bump pre-commit from 3.3.1 to 3.3.2
2023-05-22 09:19:18 +02:00
dependabot[bot]
96eb109b4e Bump mkdocs-material from 9.1.12 to 9.1.14
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.1.12 to 9.1.14.
- [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.1.12...9.1.14)

---
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-05-22 03:59:01 +00:00
dependabot[bot]
ae52ce8cda Bump sqlalchemy from 2.0.13 to 2.0.15
Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 2.0.13 to 2.0.15.
- [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-05-22 03:58:23 +00:00
dependabot[bot]
811198cc3e Bump pre-commit from 3.3.1 to 3.3.2
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 3.3.1 to 3.3.2.
- [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/v3.3.1...v3.3.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-22 03:57:15 +00:00
dependabot[bot]
4e3de64c57 Bump fastapi from 0.95.1 to 0.95.2
Bumps [fastapi](https://github.com/tiangolo/fastapi) from 0.95.1 to 0.95.2.
- [Release notes](https://github.com/tiangolo/fastapi/releases)
- [Commits](https://github.com/tiangolo/fastapi/compare/0.95.1...0.95.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-22 03:57:01 +00:00
dependabot[bot]
8c866abad8 Bump ccxt from 3.0.103 to 3.1.5
Bumps [ccxt](https://github.com/ccxt/ccxt) from 3.0.103 to 3.1.5.
- [Changelog](https://github.com/ccxt/ccxt/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ccxt/ccxt/compare/3.0.103...3.1.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-22 03:56:52 +00:00
Matthias
a2d03c4e2c Merge pull request #8047 from freqtrade/dependabot/pip/develop/cachetools-5.3.0
Bump cachetools from 4.2.2 to 5.3.0
2023-05-21 21:59:12 +02:00
dependabot[bot]
68ab147f57 Bump cachetools from 4.2.2 to 5.3.0
Bumps [cachetools](https://github.com/tkem/cachetools) from 4.2.2 to 5.3.0.
- [Release notes](https://github.com/tkem/cachetools/releases)
- [Changelog](https://github.com/tkem/cachetools/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/tkem/cachetools/compare/v4.2.2...v5.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-21 12:52:49 +00:00
Matthias
abc82a3fdf Simplify api backtesting by extracting the background_method 2023-05-21 12:04:18 +02:00
Matthias
756e1f5d5b Test pairlist evaluation 2023-05-21 10:08:32 +02:00
Matthias
01984a06af Extract pairlist evaluation from sub-method 2023-05-21 09:58:38 +02:00
Matthias
7cc8da23c2 Update test for available pairlist 2023-05-21 09:56:46 +02:00
Matthias
bf9a6dd6e7 Merge branch 'develop' into feat/pairlistconfig 2023-05-21 09:54:17 +02:00
Matthias
a87b215d67 Fix odd import 2023-05-21 09:50:59 +02:00
Matthias
818a3342b9 move pairlist evaluation to the background 2023-05-21 09:38:14 +02:00
Matthias
680e7ba98f Get exchange through DI 2023-05-21 09:21:22 +02:00
Matthias
5ad6652e55 Merge branch 'develop' into feat/pairlistconfig 2023-05-21 09:15:50 +02:00
Matthias
914195acf4 Ensure one test can't fail 20 others 2023-05-21 09:14:00 +02:00
Matthias
96d74063fc Don't have public attributes marked as private 2023-05-21 09:12:02 +02:00
Matthias
5316227219 Extract api backtest logic from ApiServer class 2023-05-21 09:08:52 +02:00
Matthias
70a0c2e625 Fix test mishap 2023-05-21 08:21:08 +02:00
Matthias
3e6a2bf9b0 Add parameters for analysis tests ... 2023-05-20 20:12:04 +02:00
Matthias
104fa9e32d Use logger, not the logging module 2023-05-20 19:58:14 +02:00
Matthias
e73cd1487e Add somewhat sensible assert 2023-05-20 19:57:26 +02:00
Matthias
9869a21951 Move strategy to it's own directory to avoid having other 2023-05-20 19:51:54 +02:00
Matthias
3f5c18a035 Add some tests as todo 2023-05-20 19:51:54 +02:00
Matthias
e183707979 Further test lookahead_helpers 2023-05-20 19:51:54 +02:00
Matthias
ceddcd9242 Move most of the logic to lookahead_analysis helper 2023-05-20 19:51:54 +02:00
Matthias
d8af0dc9c4 Slightly improve testcase 2023-05-20 19:51:54 +02:00
Matthias
1c4a7c7a05 Split Lookahead helper to separate file 2023-05-20 19:51:54 +02:00
Matthias
7b9f82c71a Remove needless check for "None" list 2023-05-20 19:51:54 +02:00
hippocritical
5142b6bc0d Merge branch 'freqtrade:develop' into develop 2023-05-20 19:50:31 +02:00
Matthias
209eb63ede Add startup test case 2023-05-20 11:28:52 +02:00
Matthias
2e675efa13 Initial fix - test 2023-05-20 11:15:30 +02:00
Matthias
073dac8d5f Move lookahead analysis tests to optimize subdir 2023-05-20 11:08:22 +02:00
Matthias
a0edbe4797 Switch to using config instead of args. 2023-05-20 11:06:50 +02:00
Matthias
2e79aaae00 Remove usage of args.
It's clumsy to use and prevents specifying settings in the configuration.
2023-05-20 11:02:13 +02:00
Matthias
5488789bc4 Arguments should be in the configuration. 2023-05-20 11:01:42 +02:00
Matthias
fcb75560c4 Merge pull request #8565 from vinistation/develop
GPU Enable in docker-compose
2023-05-20 07:30:30 +02:00
robcaulk
c4c0371ed3 add docker comment to docker usage freqai doc section 2023-05-19 14:48:17 +00:00
robcaulk
dd1a0156b9 resolve conflict, ensure gpu works with transformer 2023-05-19 14:39:16 +00:00
Matthias
7ecc2f76a2 Merge pull request #8650 from freqtrade/feat/secure_keys
Better secure the user's exchange keys during runtime
2023-05-19 08:45:17 +02:00
Matthias
a2cbe5df04 Remove trailing spaces 2023-05-19 07:26:11 +02:00
Matthias
0d4010a0be Add sample docker-compose file for freqAI, comment about that 2023-05-19 07:25:02 +02:00
Matthias
9d0f488de7 Some more edits due to arrow 2023-05-19 07:15:24 +02:00
Matthias
707c6744b9 Fix doc and example indentation 2023-05-19 07:02:54 +02:00
Matthias
ebfc9a6039 Remove some humanize occurances 2023-05-18 19:29:37 +02:00
hippocritical
b2ecfd28a7 Merge branch 'freqtrade:develop' into develop 2023-05-18 19:12:25 +02:00
Matthias
5d0cff2f76 Add dt_humanize helper 2023-05-18 07:07:22 +02:00
Matthias
f657d06e91 Move shorten_date to datetime helpers 2023-05-18 07:00:36 +02:00
Matthias
b40c45ee42 Timerange -> datetime 2023-05-18 07:00:36 +02:00
Matthias
adcf751340 Bump min-requirement of arrow 2023-05-18 07:00:36 +02:00
Matthias
261822147c Fix remaining arrow testcases 2023-05-18 07:00:36 +02:00
Matthias
3ec55885bd Remove arrow from more tests 2023-05-18 07:00:36 +02:00
Matthias
9421ca2628 Remove arrow from test_persistence 2023-05-18 07:00:36 +02:00
Matthias
3a4d103bc8 Properly check wallets with new type 2023-05-18 07:00:36 +02:00
Matthias
7a2ff60255 Fix more tests 2023-05-18 07:00:36 +02:00
Matthias
915cb5ffbd add dt_utc helper 2023-05-18 07:00:36 +02:00
Matthias
c0713eb77f More tests to dt_helpers 2023-05-18 07:00:36 +02:00
Matthias
29fdcdbf56 reduce arrow in tests 2023-05-18 07:00:36 +02:00
Matthias
d131dd4050 Fix wrong transition 2023-05-18 07:00:36 +02:00
Matthias
cfae98ae00 dt_now for tests 2023-05-18 07:00:36 +02:00
Matthias
e4f701fd0d Don't use arrow for everything 2023-05-18 07:00:36 +02:00
Matthias
5b66ef4bea Implement datetime.floor 2023-05-18 07:00:36 +02:00
Matthias
7f73e99437 Simplify exchange_utils 2023-05-18 07:00:36 +02:00
Matthias
55ce58d79f Reduce some arrow usages in favor of dt helpers 2023-05-18 07:00:36 +02:00
Matthias
000f72942a Improve dt_now_ts helper 2023-05-18 07:00:36 +02:00
Matthias
aa949153eb Add now ts helper 2023-05-18 07:00:36 +02:00
Matthias
5c6f3ea439 Improve wallets time handling 2023-05-18 07:00:36 +02:00
Matthias
261df527d9 dt_now 2023-05-18 07:00:36 +02:00
Matthias
6b735bc683 Implement dt_now 2023-05-18 07:00:36 +02:00
Matthias
6044bbb6b1 Add datetime helpers to unify code 2023-05-18 07:00:36 +02:00
Matthias
2477ef57f9 Reduce arrow usage throughout code 2023-05-18 07:00:36 +02:00
Matthias
1d03e8bc5f Reduce arrow usage further 2023-05-18 07:00:36 +02:00
Matthias
d3382fbe04 Reduce usage of arrow 2023-05-18 07:00:36 +02:00
Matthias
292bd62973 Reduce verbosity of httpx (we don't need to see telegram calls) 2023-05-18 07:00:18 +02:00
Matthias
c54f28ada8 Merge pull request #8623 from freqtrade/feat/tensorboard-logger
Add Tensorboard logger for PyTorch and XGBoost
2023-05-18 06:41:15 +02:00
hippocritical
7a5f457b2f Merge branch 'freqtrade:develop' into develop 2023-05-17 22:14:51 +02:00
robcaulk
adeab13bdf cleanup tests, cross fingers that mac will pass 2023-05-17 07:21:48 +00:00
Matthias
2ab732480f Ensure pi image can be built 2023-05-17 06:26:57 +02:00
Matthias
45ee12e257 reload_trade should be a post endpoint 2023-05-16 20:27:07 +02:00
Matthias
63294c4d3a Merge pull request #8652 from freqtrade/dependabot/pip/docs/pymdown-extensions-10.0
Bump pymdown-extensions from 9.11 to 10.0 in /docs
2023-05-16 11:03:20 +02:00
Matthias
bb760a47d5 Bump pymdown-extensions to 10.0.1 2023-05-16 10:15:46 +02:00
dependabot[bot]
61ea3d817a Bump pymdown-extensions from 9.11 to 10.0 in /docs
Bumps [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions) from 9.11 to 10.0.
- [Release notes](https://github.com/facelessuser/pymdown-extensions/releases)
- [Commits](https://github.com/facelessuser/pymdown-extensions/compare/9.11...10.0)

---
updated-dependencies:
- dependency-name: pymdown-extensions
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-16 07:45:08 +00:00
Matthias
7d15c379cb Fix faulty removed import 2023-05-15 19:26:51 +02:00
Matthias
c7f7dd1d4b Avoid unnecessary type ignore 2023-05-15 18:27:12 +02:00
Matthias
1b714fdb00 Fix wrong "first trade" date in UI, improve interface
closes https://github.com/freqtrade/freqtrade-strategies/issues/301
2023-05-15 18:06:17 +02:00
Matthias
9b10287899 Improve typing 2023-05-15 17:53:18 +02:00
Matthias
2a388e2db3 Merge pull request #8643 from freqtrade/dependabot/pip/develop/sqlalchemy-2.0.13
Bump sqlalchemy from 2.0.12 to 2.0.13
2023-05-15 11:52:41 +02:00
Robert Caulk
f5b570663a Merge pull request #8647 from freqtrade/dependabot/pip/develop/torch-2.0.1
Bump torch from 2.0.0 to 2.0.1
2023-05-15 10:34:38 +02:00
Matthias
78f9e09a4a Merge branch 'develop' into dependabot/pip/develop/sqlalchemy-2.0.13 2023-05-15 09:53:13 +02:00
Matthias
3a0e123c67 Bump pre-commit sqlalchemy 2023-05-15 09:39:55 +02:00
Matthias
f5c851fa84 Merge pull request #8645 from freqtrade/dependabot/pip/develop/types-python-dateutil-2.8.19.13
Bump types-python-dateutil from 2.8.19.12 to 2.8.19.13
2023-05-15 09:25:57 +02:00
Matthias
ef15b7b3d8 pre-commit dateutil types 2023-05-15 08:42:28 +02:00
Matthias
901bd74077 Merge pull request #8644 from freqtrade/dependabot/pip/develop/ruff-0.0.267
Bump ruff from 0.0.265 to 0.0.267
2023-05-15 08:21:02 +02:00
dependabot[bot]
28905885e5 Bump sqlalchemy from 2.0.12 to 2.0.13
Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 2.0.12 to 2.0.13.
- [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-05-15 06:18:13 +00:00
Matthias
cebdb421a3 Merge pull request #8641 from freqtrade/dependabot/pip/develop/ccxt-3.0.103
Bump ccxt from 3.0.97 to 3.0.103
2023-05-15 08:17:15 +02:00
Matthias
00168425c2 Merge pull request #8646 from freqtrade/dependabot/pip/develop/pyjwt-2.7.0
Bump pyjwt from 2.6.0 to 2.7.0
2023-05-15 08:14:15 +02:00
Matthias
68f67c5ae8 Test proper removal of exchange keys 2023-05-15 07:22:40 +02:00
Matthias
c242d89cda Improve test format 2023-05-15 07:22:40 +02:00
Matthias
66c3eb2820 Remove keys from config before loading strategy 2023-05-15 07:22:40 +02:00
Matthias
b2a631e93a refactor remove_exchange_credentials 2023-05-15 07:22:40 +02:00
Matthias
fe36e77412 Split exchange_config before passing through the strategy 2023-05-15 07:22:40 +02:00
Matthias
fffb056ad3 load_exchange - force kwargs for non-required arguments 2023-05-15 07:22:40 +02:00
Matthias
0ea47118e1 Create test Utils package 2023-05-15 07:21:26 +02:00
Matthias
c1ac0f186c Merge pull request #8642 from freqtrade/dependabot/pip/develop/mkdocs-material-9.1.12
Bump mkdocs-material from 9.1.10 to 9.1.12
2023-05-15 07:00:15 +02:00
dependabot[bot]
dd76245393 Bump ruff from 0.0.265 to 0.0.267
Bumps [ruff](https://github.com/charliermarsh/ruff) from 0.0.265 to 0.0.267.
- [Release notes](https://github.com/charliermarsh/ruff/releases)
- [Changelog](https://github.com/charliermarsh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/charliermarsh/ruff/compare/v0.0.265...v0.0.267)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-15 04:31:22 +00:00
Matthias
ed6958d05f Merge pull request #8640 from freqtrade/dependabot/pip/develop/mypy-1.3.0
Bump mypy from 1.2.0 to 1.3.0
2023-05-15 06:30:38 +02:00
dependabot[bot]
acdd50aada Bump torch from 2.0.0 to 2.0.1
Bumps [torch](https://github.com/pytorch/pytorch) from 2.0.0 to 2.0.1.
- [Release notes](https://github.com/pytorch/pytorch/releases)
- [Changelog](https://github.com/pytorch/pytorch/blob/main/RELEASE.md)
- [Commits](https://github.com/pytorch/pytorch/compare/v2.0.0...v2.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-15 03:57:51 +00:00
dependabot[bot]
33a0ed67df Bump pyjwt from 2.6.0 to 2.7.0
Bumps [pyjwt](https://github.com/jpadilla/pyjwt) from 2.6.0 to 2.7.0.
- [Release notes](https://github.com/jpadilla/pyjwt/releases)
- [Changelog](https://github.com/jpadilla/pyjwt/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/jpadilla/pyjwt/compare/2.6.0...2.7.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-15 03:57:33 +00:00
dependabot[bot]
f21a7a25d2 Bump types-python-dateutil from 2.8.19.12 to 2.8.19.13
Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.8.19.12 to 2.8.19.13.
- [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-05-15 03:57:21 +00:00
dependabot[bot]
5f01b823da Bump mkdocs-material from 9.1.10 to 9.1.12
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.1.10 to 9.1.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.1.10...9.1.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-05-15 03:56:55 +00:00
dependabot[bot]
b0e7b43958 Bump ccxt from 3.0.97 to 3.0.103
Bumps [ccxt](https://github.com/ccxt/ccxt) from 3.0.97 to 3.0.103.
- [Changelog](https://github.com/ccxt/ccxt/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ccxt/ccxt/compare/3.0.97...3.0.103)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-15 03:56:45 +00:00
dependabot[bot]
675ab840f2 Bump mypy from 1.2.0 to 1.3.0
Bumps [mypy](https://github.com/python/mypy) from 1.2.0 to 1.3.0.
- [Commits](https://github.com/python/mypy/compare/v1.2.0...v1.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-15 03:56:38 +00:00
robcaulk
a225ab71e4 revert file count 2023-05-14 16:18:33 +00:00
robcaulk
9242dfa355 try reactivating tb for some tests 2023-05-14 16:05:49 +00:00
robcaulk
505f36a95f try even more deactivation 2023-05-14 15:49:24 +00:00
robcaulk
1ed084557a try even more deactivation 2023-05-14 15:44:41 +00:00
robcaulk
73e9047cd5 try to deactivate any test that has a callback 2023-05-14 14:53:12 +00:00
robcaulk
340d2191ff deactivate tensorboard by default 2023-05-14 14:39:23 +00:00
robcaulk
55a1a3afd6 add config option for activating and deactivating tensorboard logger, ensure the various flavors are never activated simultaneously 2023-05-14 14:08:00 +00:00
robcaulk
ab7a474ab6 try limiting tb_logger to pytorch only (XGBoost still gets its callback) 2023-05-14 12:03:15 +00:00
robcaulk
8a9b2fc16f fix merge conflicts with develop 2023-05-14 12:00:03 +00:00
Matthias
af8fbad281 Improve Date timezone useage 2023-05-14 08:54:26 +02:00
Matthias
bbce738523 Improve tests around timezone 2023-05-14 08:42:30 +02:00
hippocritical
36f14249d4 Merge branch 'freqtrade:develop' into develop 2023-05-13 22:41:02 +02:00
hippocritical
7d871faf04 added exportfilename to args_to_config
introduced strategy_test_v3_with_lookahead_bias.py for checking lookahead_bias#
introduced test_lookahead_analysis which currently is broken
2023-05-13 22:40:11 +02:00
Matthias
66a97ff45d Remove some utcnow usages 2023-05-13 20:43:37 +02:00
Matthias
7266279768 Improve docs around pytho 3.11 2023-05-13 20:22:15 +02:00
Matthias
59d6ae17be Merge pull request #8327 from skinner12/develop
Support for python 3.11 via setup.sh script
2023-05-13 19:57:44 +02:00
Matthias
1aa9dd02d6 Merge pull request #8588 from freqtrade/catboost_1.2
Bump catboost to 1.2, disable some constraints
2023-05-13 19:56:56 +02:00
Matthias
784087384c darwin excludes must use "sys_platform" 2023-05-13 17:22:11 +02:00
Matthias
838fbb76ab Improve version constraints 2023-05-13 16:43:45 +02:00
Matthias
7bba034efd Merge pull request #8560 from freqtrade/feat/recoverTrades
Recover trades after selling on exchange
2023-05-13 16:35:08 +02:00
Matthias
106db716f8 Force smaller catboost version on 3.8 macos 2023-05-13 16:32:46 +02:00
Matthias
e76356aff5 Bump catboost to 1.2, disable some constraints 2023-05-13 16:25:25 +02:00
Matthias
0db1869356 Update cached binance leverage tiers 2023-05-13 16:22:04 +02:00
Matthias
dc4268b6e7 Convert Exchange arguments to be kw only 2023-05-13 16:17:26 +02:00
Matthias
af95d56ceb Import deepcopy specifically 2023-05-13 16:16:35 +02:00
Matthias
0d4010c38c maint: Remove faulty config setting from default_conf 2023-05-13 16:16:20 +02:00
Matthias
90ac387444 Merge pull request #8634 from freqtrade/bug-fix/continual_learning
fix bug in continual_learning for PyTorch* models
2023-05-13 15:32:49 +02:00
robcaulk
18c1eda09b remove commented lines 2023-05-13 11:27:36 +00:00
robcaulk
2ec1302c10 add warnings in the doc for users to better understand the limitations of continual_learning 2023-05-13 11:23:57 +00:00
robcaulk
fad1c19856 add warnings in the doc for users to better understand the limitations of continual_learning 2023-05-13 11:21:43 +00:00
robcaulk
3ae3cc63df fix bug in continual_learning for PyTorch* models 2023-05-13 11:14:16 +00:00
Matthias
d50e221e62 Update active ccxt.futures test init 2023-05-13 11:03:26 +02:00
Matthias
1552d81f45 Simplify load_exchange interface 2023-05-13 11:03:26 +02:00
Matthias
b2a3fe6879 Improve remove credentials 2023-05-13 11:03:26 +02:00
Matthias
6541782758 Merge pull request #8631 from freqtrade/add-disclaimers-everwhere
Clarify expectations about the FreqAI + Freqtrade tool
2023-05-13 10:56:46 +02:00
Matthias
ab0f9d78ee Mock tensorboard callbacks for all freqAI tests 2023-05-13 08:08:30 +02:00
Matthias
23e8932a44 Mock tensorboard callbacks 2023-05-12 20:20:17 +02:00
Matthias
400cbd1836 Fix types 2023-05-12 19:47:53 +02:00
Matthias
871f1aabb7 Use tensorboard fallback for mac tests 2023-05-12 18:33:46 +02:00
Matthias
6d7172ac44 Re-add init file 2023-05-12 18:26:34 +02:00
Matthias
49b9b463b4 Move tensorboard callback exports to freqai.tensorboard. 2023-05-12 18:26:01 +02:00
Matthias
43213cc6ff Revert testing Reinforcement lerning on Mac 2023-05-12 18:07:28 +02:00
robcaulk
6e5a9fe4c9 mac strikes again 2023-05-12 13:55:41 +00:00
robcaulk
ca7ad8a49b good old macos 2023-05-12 12:50:11 +00:00
robcaulk
8261c988b9 try to fix mac CI 2023-05-12 09:11:14 +00:00
robcaulk
db0645ed1b add helpful hints for reward creation 2023-05-12 08:32:52 +00:00
robcaulk
31d15da49e add disclaimers everywhere about how example strategies are meant as examples 2023-05-12 08:16:48 +00:00
robcaulk
692fa390c6 fix the import logic, fix tests, put all tensorboard in a single folder 2023-05-12 07:56:44 +00:00
Matthias
ad2080ab3e Merge pull request #8630 from freqtrade/maint/test_user_data
Maint/test user data
2023-05-12 06:37:38 +02:00
Matthias
6000e68420 bump ccxt min dependency 2023-05-11 20:51:33 +02:00
Matthias
1d36878938 Bump min-requirements for python-telegram bot 2023-05-11 20:50:52 +02:00
Matthias
b970ddeb66 Fix unused import 2023-05-11 20:44:41 +02:00
Matthias
f7179f7c93 Fix last test with dependency on local user_data dir 2023-05-11 20:30:24 +02:00
Matthias
a00f0ff687 Merge pull request #8626 from freqtrade/ci/repochange
Check for repository changes
2023-05-11 20:11:31 +02:00
Matthias
1c1005247e Don't hardcode user_data in tests 2023-05-11 20:09:24 +02:00
Matthias
963ff8c620 Run Repo check on windows, too. 2023-05-11 10:57:24 +02:00
Matthias
395bf49198 Run Repo-check for macOS, too 2023-05-11 10:55:29 +02:00
Matthias
2ecd63234d Remove git status again 2023-05-11 10:54:46 +02:00
Matthias
bd6d4d5d2d Event-name for concurrency group? 2023-05-11 10:50:09 +02:00
Matthias
1ec1abdc33 Fix syntax 2023-05-11 10:45:52 +02:00
Matthias
800c6223ed Quote concurrency group 2023-05-11 10:45:30 +02:00
Matthias
3ba1eb6baa Improve concurrency group 2023-05-11 10:45:17 +02:00
Matthias
c60c4b9abb Update user_dir fixture to return user_data path 2023-05-11 07:10:34 +02:00
Matthias
7e023419de Auto-mock user_dir to tmpdir
This will avoid depending on the user directory being present for tests
2023-05-11 07:05:43 +02:00
Matthias
a74a081e61 Check for repository changes 2023-05-11 06:58:57 +02:00
hippocritical
91ce1cb2ae removed overwrite_existing_exportfilename_content (won't use it myself, wouldn't make sense for others to not overwrite something they re-calculated)
switched from args to config (args still work)
renamed exportfilename to lookahead_analysis_exportfilename so if users decide to put something into it then it won't compete with other configurations
2023-05-10 22:41:27 +02:00
robcaulk
6df5cb8878 add install requirement to tensorboard doc 2023-05-10 10:18:52 +00:00
robcaulk
b01aaa4d03 ensure backtesting also produces tb_logs, make sure tests are working 2023-05-10 10:11:33 +00:00
Robert Davey
242247be47 Fix var name 2023-05-10 10:56:14 +01:00
robcaulk
172b2587ab Merge remote-tracking branch 'originssh/develop' into develop 2023-05-10 09:48:54 +00:00
robcaulk
ffc4d87263 add tensorboard integration to XGBoost and PyTorch et al 2023-05-10 09:48:36 +00:00
Robert Davey
3a7e41e177 Update rest_client.py
Add fix for forceenter to avoid passing None prices back to the API
2023-05-10 10:32:00 +01:00
Robert Caulk
deeca484d8 Merge pull request #8619 from freqtrade/bug-fix-live_retrain_hours
Bug fix `live_retrain_hours`
2023-05-10 09:02:13 +02:00
Matthias
1f6a6ae86f Merge pull request #8620 from freqtrade/pytorch_tests_fix
Properly enable pytorch tests
2023-05-09 20:40:36 +02:00
Matthias
d9cc45851e Properly enable pytorch tests 2023-05-09 19:42:15 +02:00
Matthias
6731d6c505 Merge pull request #8616 from freqtrade/dependabot/pip/develop/pyarrow-12.0.0
Bump pyarrow from 11.0.0 to 12.0.0
2023-05-09 16:35:19 +02:00
robcaulk
2c0230ba93 avoid mutating new_trained_timerange 2023-05-09 12:42:02 +00:00
robcaulk
35ce88f1e5 ensure that the buffered timerange is not the trained timestamp so that live_retrain_hours functions properly 2023-05-09 10:00:33 +00:00
Matthias
55777eba73 Add pre-build arm wheel for pyarrow 2023-05-09 07:09:46 +02:00
hippocritical
9aac367534 Merge remote-tracking branch 'origin/develop' into develop 2023-05-08 22:58:30 +02:00
hippocritical
b8357c36ca Merge branch 'freqtrade:develop' into develop 2023-05-08 22:58:03 +02:00
hippocritical
b252bdd3c7 made purging of config.freqai.identifier variable 2023-05-08 22:35:13 +02:00
Matthias
d02cf8f0b7 Merge pull request #8613 from freqtrade/dependabot/pip/develop/nbconvert-7.4.0
Bump nbconvert from 7.3.1 to 7.4.0
2023-05-08 20:15:49 +02:00
Matthias
2f25206fd5 Merge pull request #8615 from freqtrade/dependabot/pip/develop/urllib3-2.0.2
Bump urllib3 from 1.26.15 to 2.0.2
2023-05-08 19:54:16 +02:00
Matthias
f47db6e9fa Merge pull request #8617 from freqtrade/dependabot/pip/develop/ccxt-3.0.97
Bump ccxt from 3.0.85 to 3.0.97
2023-05-08 19:53:21 +02:00
Matthias
45c5b503c0 Merge pull request #8603 from freqtrade/dependabot/pip/develop/pre-commit-3.3.1
Bump pre-commit from 3.2.2 to 3.3.1
2023-05-08 19:47:40 +02:00
Matthias
33c2e754af Merge pull request #8611 from freqtrade/torch_ci_11
Run Torch tests on 3.11
2023-05-08 19:47:04 +02:00
Matthias
f9d16b5bbb Merge pull request #8614 from freqtrade/dependabot/pip/develop/mkdocs-material-9.1.10
Bump mkdocs-material from 9.1.9 to 9.1.10
2023-05-08 19:30:46 +02:00
dependabot[bot]
f2a65437a6 Bump ccxt from 3.0.85 to 3.0.97
Bumps [ccxt](https://github.com/ccxt/ccxt) from 3.0.85 to 3.0.97.
- [Changelog](https://github.com/ccxt/ccxt/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ccxt/ccxt/compare/3.0.85...3.0.97)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-08 16:18:57 +00:00
dependabot[bot]
5a27245fcc Bump pyarrow from 11.0.0 to 12.0.0
Bumps [pyarrow](https://github.com/apache/arrow) from 11.0.0 to 12.0.0.
- [Commits](https://github.com/apache/arrow/compare/go/v11.0.0...go/v12.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-05-08 16:18:40 +00:00
dependabot[bot]
3e39453905 Bump urllib3 from 1.26.15 to 2.0.2
Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.15 to 2.0.2.
- [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.15...2.0.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-08 16:17:19 +00:00
dependabot[bot]
7e31cc4100 Bump mkdocs-material from 9.1.9 to 9.1.10
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.1.9 to 9.1.10.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.1.9...9.1.10)

---
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-05-08 16:17:04 +00:00
dependabot[bot]
591a51e4bc Bump nbconvert from 7.3.1 to 7.4.0
Bumps [nbconvert](https://github.com/jupyter/nbconvert) from 7.3.1 to 7.4.0.
- [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.3.1...v7.4.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-08 16:16:45 +00:00
Matthias
081a8b0ed0 Merge pull request #8609 from freqtrade/dependabot/pip/develop/types-requests-2.30.0.0
Bump types-requests from 2.29.0.0 to 2.30.0.0
2023-05-08 10:42:35 +02:00
dependabot[bot]
9d7c90e9da Bump pre-commit from 3.2.2 to 3.3.1
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 3.2.2 to 3.3.1.
- [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/v3.2.2...v3.3.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-08 08:11:43 +00:00
Matthias
0336e5275c Merge pull request #8608 from freqtrade/dependabot/pip/develop/mkdocs-material-9.1.9
Bump mkdocs-material from 9.1.8 to 9.1.9
2023-05-08 10:01:37 +02:00
Matthias
c9533fc9fd Merge pull request #8610 from freqtrade/dependabot/pip/develop/ruff-0.0.265
Bump ruff from 0.0.263 to 0.0.265
2023-05-08 09:59:34 +02:00
Matthias
3952232214 Bump pre-commit requests types 2023-05-08 08:59:15 +02:00
Matthias
335f763c80 Merge pull request #8606 from freqtrade/dependabot/pip/develop/tensorboard-2.13.0
Bump tensorboard from 2.12.2 to 2.13.0
2023-05-08 08:48:56 +02:00
Matthias
8b8604b6e2 Merge pull request #8607 from freqtrade/dependabot/pip/develop/python-telegram-bot-20.3
Bump python-telegram-bot from 20.2 to 20.3
2023-05-08 08:43:20 +02:00
Matthias
225ae7fe6a Merge pull request #8605 from freqtrade/dependabot/pip/develop/requests-2.30.0
Bump requests from 2.29.0 to 2.30.0
2023-05-08 08:42:25 +02:00
Matthias
60b666feee Merge pull request #8604 from freqtrade/dependabot/github_actions/develop/pypa/gh-action-pypi-publish-1.8.6
Bump pypa/gh-action-pypi-publish from 1.8.5 to 1.8.6
2023-05-08 08:42:01 +02:00
dependabot[bot]
e0c63e12e4 Bump mkdocs-material from 9.1.8 to 9.1.9
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.1.8 to 9.1.9.
- [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.1.8...9.1.9)

---
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-05-08 05:15:49 +00:00
Matthias
e386d60831 Merge pull request #8602 from freqtrade/dependabot/pip/develop/mkdocs-1.4.3
Bump mkdocs from 1.4.2 to 1.4.3
2023-05-08 07:06:23 +02:00
Matthias
b0b0eb66df Merge pull request #8601 from freqtrade/dependabot/pip/develop/websockets-11.0.3
Bump websockets from 11.0.2 to 11.0.3
2023-05-08 07:06:06 +02:00
Matthias
10604bf49c Run Torch tests on 3.11 2023-05-08 06:46:30 +02:00
Matthias
a64cec2bdc Merge pull request #8600 from freqtrade/dependabot/pip/develop/orjson-3.8.12
Bump orjson from 3.8.11 to 3.8.12
2023-05-08 06:27:13 +02:00
dependabot[bot]
75e5f325a9 Bump ruff from 0.0.263 to 0.0.265
Bumps [ruff](https://github.com/charliermarsh/ruff) from 0.0.263 to 0.0.265.
- [Release notes](https://github.com/charliermarsh/ruff/releases)
- [Changelog](https://github.com/charliermarsh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/charliermarsh/ruff/compare/v0.0.263...v0.0.265)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-08 03:59:08 +00:00
dependabot[bot]
bf7c52a9ee Bump types-requests from 2.29.0.0 to 2.30.0.0
Bumps [types-requests](https://github.com/python/typeshed) from 2.29.0.0 to 2.30.0.0.
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-08 03:58:37 +00:00
dependabot[bot]
7bd33be8f7 Bump python-telegram-bot from 20.2 to 20.3
Bumps [python-telegram-bot](https://github.com/python-telegram-bot/python-telegram-bot) from 20.2 to 20.3.
- [Release notes](https://github.com/python-telegram-bot/python-telegram-bot/releases)
- [Changelog](https://github.com/python-telegram-bot/python-telegram-bot/blob/master/CHANGES.rst)
- [Commits](https://github.com/python-telegram-bot/python-telegram-bot/compare/v20.2...v20.3)

---
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>
2023-05-08 03:58:16 +00:00
dependabot[bot]
68a37cb71b Bump tensorboard from 2.12.2 to 2.13.0
Bumps [tensorboard](https://github.com/tensorflow/tensorboard) from 2.12.2 to 2.13.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.12.2...2.13.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-05-08 03:58:05 +00:00
dependabot[bot]
ecd34ce470 Bump requests from 2.29.0 to 2.30.0
Bumps [requests](https://github.com/psf/requests) from 2.29.0 to 2.30.0.
- [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.29.0...v2.30.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-08 03:57:54 +00:00
dependabot[bot]
4a911bbe90 Bump pypa/gh-action-pypi-publish from 1.8.5 to 1.8.6
Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.8.5 to 1.8.6.
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.8.5...v1.8.6)

---
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>
2023-05-08 03:57:44 +00:00
dependabot[bot]
3bb872a5e7 Bump mkdocs from 1.4.2 to 1.4.3
Bumps [mkdocs](https://github.com/mkdocs/mkdocs) from 1.4.2 to 1.4.3.
- [Release notes](https://github.com/mkdocs/mkdocs/releases)
- [Commits](https://github.com/mkdocs/mkdocs/compare/1.4.2...1.4.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-08 03:57:22 +00:00
dependabot[bot]
fa40e4e888 Bump websockets from 11.0.2 to 11.0.3
Bumps [websockets](https://github.com/aaugustin/websockets) from 11.0.2 to 11.0.3.
- [Release notes](https://github.com/aaugustin/websockets/releases)
- [Commits](https://github.com/aaugustin/websockets/compare/11.0.2...11.0.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-08 03:57:11 +00:00
dependabot[bot]
4b1cb96446 Bump orjson from 3.8.11 to 3.8.12
Bumps [orjson](https://github.com/ijl/orjson) from 3.8.11 to 3.8.12.
- [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.11...3.8.12)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-08 03:56:59 +00:00
Robert Caulk
950eaf230e Merge pull request #8580 from freqtrade/feat/add-transformer
Add transformer to FreqAI
2023-05-07 11:32:38 +02:00
Matthias
89c60bbee6 Merge pull request #8598 from freqtrade/bug-fix-backtesting
bug fix backtest feature validation
2023-05-07 08:14:34 +02:00
hippocritical
ac4aa8ed2b Merge branch 'freqtrade:develop' into develop 2023-05-06 21:59:04 +02:00
hippocritical
2306c74dc1 adjusted code to matthias' specifications
did not change the code so that it only loads data once yet.
2023-05-06 21:56:11 +02:00
robcaulk
36e1e58dad fix arch 2023-05-06 17:40:04 +00:00
robcaulk
3bbb7e38ea improve transformer architecture, remove 3.10 install constraint, add documentation for torch.compile() 2023-05-06 16:12:10 +00:00
robcaulk
c2beeb4c79 bug fix backtest feature validation 2023-05-06 15:53:58 +00:00
Robert Caulk
e365e913c7 Merge pull request #8596 from autoscatto/bugfix/tensor-to-numpy
Bugfix/tensor to numpy
2023-05-06 17:31:49 +02:00
Matthias
efb5cd6545 Merge pull request #7861 from froggleston/reject_report
Add support for collating and analysing rejected signals in backtest
2023-05-06 14:28:24 +02:00
Tommaso Falchi
908a2e817a Align BasePyTorchRegressor tensors to cpu as in BasePyTorchClassifier 2023-05-05 15:43:48 +02:00
Tommaso Falchi
306dfc4ae8 refactor(BasePyTorchClassifier.py): convert tensor to list before creating DataFrame to avoid TypeError.
docs(BasePyTorchClassifier.py): add missing parameter description in predict method
2023-05-05 13:04:53 +02:00
Matthias
e3ff2ccc97 Slightly reword documentation to be more clear 2023-05-05 06:45:39 +02:00
Matthias
24804f066c Update test comment, uncomment last test section 2023-05-03 20:24:59 +02:00
Matthias
775ea1c8c6 Improve type safety 2023-05-03 06:25:02 +00:00
Matthias
80930d72a6 Dont loop trades twice
closes #8591
2023-05-03 07:03:14 +02:00
Matthias
0adac268ee Add test for #8591 2023-05-03 07:01:57 +02:00
Matthias
976cc1ab15 Extract order_obj existence check to separate function 2023-05-03 06:48:17 +02:00
Matthias
1cc5b6126d Bump pre-commit ruff version 2023-05-03 06:48:02 +02:00
Matthias
0d1d25e868 Improve error-handling 2023-05-02 21:44:19 +02:00
Matthias
13974d2508 Reduce error severity when maintenance-ratio fails 2023-05-02 21:44:19 +02:00
Matthias
f419d7870d Add freqaimodel to pair history endpoint
closes #8566
2023-05-02 20:07:16 +02:00
Matthias
fb5fac164d add Packaging dependency explicitly 2023-05-02 19:28:09 +02:00
Matthias
a935f1e4de Remove no longer necessary dependency from setup.py 2023-05-02 19:27:01 +02:00
Matthias
f61bf346c0 Merge pull request #8589 from alxtrkhv/fix/update-setup-py
Add missing dependencies to setup.py
2023-05-02 19:25:55 +02:00
Matthias
d8a9c9422a Update missing "requirements" install in documentation 2023-05-02 18:17:35 +02:00
Achmad Fathoni
5abd616ae9 Fix disrepancy in freqai doc code example 2023-05-02 23:01:51 +07:00
Matthias
12a64c0ffc Merge pull request #8587 from freqtrade/maint/cleanup_gym_workarounds
Remove dependency workarounds in place for gym
2023-05-02 14:21:27 +02:00
Alexander Terekhov
220f8c6b5f Add missing freqai-rl dependencies 2023-05-02 09:16:12 +03:00
Alexander Terekhov
e3f983729f Update freqai dependencies 2023-05-02 09:11:31 +03:00
Alexander Terekhov
8f5fb4e32b Add missing dev dependencies 2023-05-02 09:09:38 +03:00
Alexander Terekhov
75daa44c5a Add missing core dependencies 2023-05-02 09:02:52 +03:00
Matthias
1c2dd884e9 Remove dependency workarounds in place for gym 2023-05-02 07:12:46 +02:00
Matthias
238581ee7a Remove <3.11 pin for tqdm 2023-05-02 07:08:47 +02:00
Matthias
127b0a2e50 Merge pull request #8582 from freqtrade/dependabot/pip/develop/ccxt-3.0.85
Bump ccxt from 3.0.84 to 3.0.85
2023-05-01 20:31:51 +02:00
dependabot[bot]
3f58c19976 Bump ccxt from 3.0.84 to 3.0.85
Bumps [ccxt](https://github.com/ccxt/ccxt) from 3.0.84 to 3.0.85.
- [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/3.0.84...3.0.85)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-01 17:48:30 +00:00
Matthias
5e32182c72 Bump types requests 2023-05-01 19:34:21 +02:00
Matthias
009db49502 Merge pull request #8578 from freqtrade/dependabot/pip/develop/types-requests-2.29.0.0
Bump types-requests from 2.28.11.17 to 2.29.0.0
2023-05-01 19:33:48 +02:00
Matthias
01124292b1 Merge pull request #8575 from freqtrade/dependabot/pip/develop/sqlalchemy-2.0.12
Bump sqlalchemy from 2.0.10 to 2.0.12
2023-05-01 19:24:36 +02:00
Matthias
103f27cfd0 Bump sqlalchemy pre-commit 2023-05-01 17:54:21 +02:00
dependabot[bot]
a31ceb51a0 Bump sqlalchemy from 2.0.10 to 2.0.12
Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 2.0.10 to 2.0.12.
- [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-05-01 15:54:14 +00:00
Matthias
d778beacbb Merge pull request #8576 from freqtrade/dependabot/pip/develop/ccxt-3.0.84
Bump ccxt from 3.0.75 to 3.0.84
2023-05-01 17:53:32 +02:00
Matthias
94488c86af Merge pull request #8573 from freqtrade/dependabot/pip/develop/ruff-0.0.263
Bump ruff from 0.0.262 to 0.0.263
2023-05-01 17:51:32 +02:00
Matthias
0800ed725f Merge pull request #8577 from freqtrade/dependabot/pip/develop/mkdocs-material-9.1.8
Bump mkdocs-material from 9.1.7 to 9.1.8
2023-05-01 17:50:51 +02:00
Matthias
2fd5fd8e49 Merge pull request #8574 from freqtrade/dependabot/pip/develop/uvicorn-0.22.0
Bump uvicorn from 0.21.1 to 0.22.0
2023-05-01 17:50:31 +02:00
Matthias
9e2d83f542 Merge pull request #8571 from freqtrade/dependabot/pip/develop/requests-2.29.0
Bump requests from 2.28.2 to 2.29.0
2023-05-01 17:50:10 +02:00
Matthias
cb8c91ea8e Merge pull request #8572 from freqtrade/dependabot/pip/develop/orjson-3.8.11
Bump orjson from 3.8.10 to 3.8.11
2023-05-01 17:49:51 +02:00
Matthias
2893af870e Merge pull request #8570 from freqtrade/dependabot/pip/develop/rich-13.3.5
Bump rich from 13.3.4 to 13.3.5
2023-05-01 17:49:27 +02:00
robcaulk
af139ffbab add transformer with positional encoding, fix some odds and ends in pytorch, upgrade to PyTorch 2.0 2023-05-01 13:18:03 +00:00
Robert Caulk
c26099280f Merge pull request #8336 from richardjozsa/develop
Added the latest Gymnasium version 0.28(will be released shortly),
2023-05-01 07:32:37 +02:00
dependabot[bot]
fe9f2d005e Bump types-requests from 2.28.11.17 to 2.29.0.0
Bumps [types-requests](https://github.com/python/typeshed) from 2.28.11.17 to 2.29.0.0.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-01 03:59:14 +00:00
dependabot[bot]
1d73c7c27d Bump mkdocs-material from 9.1.7 to 9.1.8
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.1.7 to 9.1.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.1.7...9.1.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-05-01 03:59:08 +00:00
dependabot[bot]
d023e75920 Bump ccxt from 3.0.75 to 3.0.84
Bumps [ccxt](https://github.com/ccxt/ccxt) from 3.0.75 to 3.0.84.
- [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/3.0.75...3.0.84)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-01 03:58:44 +00:00
dependabot[bot]
063ddd62e6 Bump uvicorn from 0.21.1 to 0.22.0
Bumps [uvicorn](https://github.com/encode/uvicorn) from 0.21.1 to 0.22.0.
- [Release notes](https://github.com/encode/uvicorn/releases)
- [Changelog](https://github.com/encode/uvicorn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/encode/uvicorn/compare/0.21.1...0.22.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-01 03:58:00 +00:00
dependabot[bot]
7f9a6ffc53 Bump ruff from 0.0.262 to 0.0.263
Bumps [ruff](https://github.com/charliermarsh/ruff) from 0.0.262 to 0.0.263.
- [Release notes](https://github.com/charliermarsh/ruff/releases)
- [Changelog](https://github.com/charliermarsh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/charliermarsh/ruff/compare/v0.0.262...v0.0.263)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-01 03:57:51 +00:00
dependabot[bot]
7dda3f5803 Bump orjson from 3.8.10 to 3.8.11
Bumps [orjson](https://github.com/ijl/orjson) from 3.8.10 to 3.8.11.
- [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.10...3.8.11)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-01 03:57:24 +00:00
dependabot[bot]
d928792eb4 Bump requests from 2.28.2 to 2.29.0
Bumps [requests](https://github.com/psf/requests) from 2.28.2 to 2.29.0.
- [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.2...v2.29.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-01 03:57:14 +00:00
dependabot[bot]
9dd077d69e Bump rich from 13.3.4 to 13.3.5
Bumps [rich](https://github.com/Textualize/rich) from 13.3.4 to 13.3.5.
- [Release notes](https://github.com/Textualize/rich/releases)
- [Changelog](https://github.com/Textualize/rich/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Textualize/rich/compare/v13.3.4...v13.3.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-01 03:57:08 +00:00
Richard Jozsa
ceb2631a56 Merge branch 'freqtrade:develop' into develop 2023-05-01 01:00:34 +02:00
hippocritical
ce979b21f9 Merge branch 'freqtrade:develop' into develop 2023-04-30 10:20:40 +02:00
vinistation
a66e8768c9 Update docker-compose.yml
Enable GPU Image and GPU Resources
2023-04-28 15:21:56 -05:00
vinistation
d1eb6d4fed Update BasePyTorchRegressor.py
Denormalization of prediction added to te PytorchMLP Model
2023-04-28 14:48:16 -05:00
Matthias
023c155a25 Extract signals generation from backtesting class 2023-04-28 16:14:16 +02:00
Matthias
6e395ad7c9 Refactor methods in backtesting 2023-04-28 16:09:09 +02:00
Matthias
0753f427b1 Simplify storage 2023-04-28 15:29:15 +02:00
Matthias
e20d9c8f98 Impoved errorhandling, better typesafety 2023-04-28 15:25:25 +02:00
Matthias
fc2a3c9f17 Implement further improvements, improve typehinting 2023-04-28 15:17:35 +02:00
Matthias
703ec3ccc4 Fix help text to show correct format 2023-04-28 15:01:47 +02:00
Matthias
8dd8c24595 Merge branch 'develop' into pr/froggleston/7861 2023-04-28 14:59:03 +02:00
Matthias
76ae539e61 Minor edit 2023-04-28 14:59:00 +02:00
Matthias
8e0788cf5f Merge branch 'develop' into feat/pairlistconfig 2023-04-27 20:40:55 +02:00
Matthias
877d53f439 Add airlists test endpoint (so pairlist configurations can be tested) 2023-04-27 20:35:24 +02:00
Matthias
2a9e50a6a9 Add test testing create-table statement creation for different sql dialects
closes #8561
2023-04-27 19:43:33 +02:00
Matthias
daf564b62f Invert logic for webhook
closes #8562
2023-04-27 18:27:09 +02:00
Matthias
1d9933412a improve /version output formatting 2023-04-27 06:43:57 +02:00
Matthias
395ac5f6dc Update integration test 2023-04-27 06:23:34 +02:00
Matthias
491d2cb024 Explicit test for handle_onexchange_order 2023-04-26 20:32:51 +02:00
Matthias
8cf0e4a316 Fix mypy typing errors 2023-04-26 19:43:42 +02:00
Matthias
6d3c94a739 type: ignore the offending tensorflow call 2023-04-26 18:08:55 +02:00
robcaulk
c6f3a3bbca avoid typing issues in the tensorboard callback 2023-04-26 14:11:26 +02:00
robcaulk
e86980befa remove typing from callback init 2023-04-26 13:42:10 +02:00
robcaulk
e29ce218eb fix typing in TensorboardCallback 2023-04-26 10:54:54 +02:00
Matthias
e88e259033 explicitly test check_exit_amount 2023-04-26 07:12:54 +02:00
Matthias
d29a425baa Update parameter type in RPC modules 2023-04-26 07:03:28 +02:00
Matthias
b0b036c457 Fix logic lapsus in check_exit_amount 2023-04-26 07:02:46 +02:00
Matthias
d0b5c7d216 update telegram/api documentation with new endpoint 2023-04-25 19:40:05 +02:00
Matthias
25bed7bb87 Update telegram help with reload_trade 2023-04-25 19:39:52 +02:00
Matthias
7287e9da1d Add telegram endpoint for reload_trade 2023-04-25 19:34:37 +02:00
Matthias
0c22710ddd Add API endpoint to force trade reloading 2023-04-25 19:30:29 +02:00
Matthias
f2696c9609 Force special exit reason for "recovered" exits 2023-04-25 18:09:46 +02:00
Matthias
24cab00479 Extract amount checking to wallets, implement for futures 2023-04-25 17:49:20 +02:00
Matthias
974cf6c365 Move comment to more appropriate spot 2023-04-25 17:41:59 +02:00
Matthias
95b35e452d Emulate fetch_orders if it ain't supported natively 2023-04-25 17:13:02 +02:00
Matthias
81633b7c2e Add "handle_onexchange_order" functionality 2023-04-25 16:19:14 +02:00
Matthias
d14f50f50d temporary comment fetch_orders logic 2023-04-25 16:19:14 +02:00
Matthias
531b5727f2 add fetch_orders exchange wrapper 2023-04-25 16:19:14 +02:00
Matthias
8364fc1bd2 Merge pull request #8553 from freqtrade/new_release
New release 2023.4
2023-04-25 16:15:47 +02:00
Matthias
c4a0910908 Handle special case where exit order is for more than the trade amount ... 2023-04-25 15:56:51 +02:00
Matthias
1b228e3705 Improve test resiliance by removing unneeded MagicMock 2023-04-25 15:52:10 +02:00
Matthias
e8fedb685b Update missleading docstring 2023-04-25 11:52:13 +02:00
Matthias
11c9f96d23 Use lock for trade entries, too 2023-04-25 11:45:35 +02:00
Matthias
59f9f4d467 Fix exception typos due to newlines 2023-04-25 09:27:33 +02:00
Matthias
1e9fa4c041 Improve test to cover to_ccxt better 2023-04-25 09:04:02 +02:00
Matthias
6a271317bc use stop_price_param for dry stops
closes #8555
2023-04-25 08:53:02 +02:00
Matthias
1df01a2634 Merge pull request #8554 from freqtrade/dependabot/pip/develop/pandas-2.0.1
Bump pandas from 1.5.3 to 2.0.1
2023-04-24 17:35:04 +02:00
dependabot[bot]
c19d6b4e29 Bump pandas from 1.5.3 to 2.0.1
Bumps [pandas](https://github.com/pandas-dev/pandas) from 1.5.3 to 2.0.1.
- [Release notes](https://github.com/pandas-dev/pandas/releases)
- [Commits](https://github.com/pandas-dev/pandas/compare/v1.5.3...v2.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 14:01:01 +00:00
Matthias
459e5e67bd Merge pull request #8394 from freqtrade/dependabot/pip/develop/python-telegram-bot-20.2
Bump python-telegram-bot from 13.15 to 20.2
2023-04-24 15:58:39 +02:00
Matthias
b49ff3d5bc Improve type safety 2023-04-24 14:27:56 +02:00
Matthias
2615b0297e Move httpx to regular dependencies, losely-pin 2023-04-24 14:27:56 +02:00
Matthias
c06759223e Improve telegram async tests 2023-04-24 14:27:56 +02:00
Matthias
516b49ff50 Fix bad types 2023-04-24 14:27:56 +02:00
Matthias
d25e82d095 Mock exchange loop 2023-04-24 14:27:56 +02:00
Matthias
5608aaca26 Simplify mocking 2023-04-24 14:27:56 +02:00
Matthias
7171fd1132 Test telegram startup 2023-04-24 14:27:56 +02:00
Matthias
c9e6137ad0 Fix test_telegram _init test 2023-04-24 14:27:56 +02:00
Matthias
cf0b37057c update telegram "cleanup" test 2023-04-24 14:27:56 +02:00
Matthias
69f61ef767 Further telegram async tests 2023-04-24 14:27:56 +02:00
Matthias
4177afdf8b More async test updates 2023-04-24 14:27:56 +02:00
Matthias
678c9ae67f Fix some more async telegram tests 2023-04-24 14:27:56 +02:00
Matthias
c475c81841 Update several tests to async behavior 2023-04-24 14:27:56 +02:00
Matthias
fb56889b43 Update a few tests ... 2023-04-24 14:27:56 +02:00
Matthias
914d7350fa Update mocks in apimanager tests 2023-04-24 14:27:36 +02:00
Matthias
b1367ac46f Update decorator typehint 2023-04-24 14:27:36 +02:00
Matthias
3d0e1d142f Convert endpoints to async 2023-04-24 14:27:36 +02:00
Matthias
54732b72fd Manage startup/teardown of telegram manually 2023-04-24 14:26:50 +02:00
Matthias
e7e6f719e4 _update_msg to async 2023-04-24 14:26:50 +02:00
Matthias
5134bf8ec3 Authorized-only and /version to async 2023-04-24 14:26:50 +02:00
Matthias
cb45689c1d Small fixes to new telegram implementation 2023-04-24 14:26:50 +02:00
Matthias
14b501a4f7 Initial changes for telegram migration 2023-04-24 14:26:50 +02:00
Matthias
68ac934929 Update command list to handle frozenSets 2023-04-24 14:26:50 +02:00
Matthias
57eed50acb Fix some test failures caused by v20 update 2023-04-24 14:26:50 +02:00
Matthias
c37b7b77e4 move telegram fixture to telegram file 2023-04-24 14:26:50 +02:00
Matthias
da261003df Fix telegram imports to match v20.0 2023-04-24 14:26:49 +02:00
dependabot[bot]
99a4a64052 Bump python-telegram-bot from 13.15 to 20.2
Bumps [python-telegram-bot](https://github.com/python-telegram-bot/python-telegram-bot) from 13.15 to 20.2.
- [Release notes](https://github.com/python-telegram-bot/python-telegram-bot/releases)
- [Changelog](https://github.com/python-telegram-bot/python-telegram-bot/blob/master/CHANGES.rst)
- [Commits](https://github.com/python-telegram-bot/python-telegram-bot/compare/v13.15...v20.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 14:26:49 +02:00
Matthias
4690810d5d Merge pull request #8537 from freqtrade/feat/balance_improve
Improve balance output
2023-04-24 14:26:05 +02:00
Matthias
98db27e8f4 Bump develop version to 2023.5-dev 2023-04-24 14:05:35 +02:00
Matthias
d40a631565 Version bump 2023.4 2023-04-24 13:53:27 +02:00
Matthias
5a8f34feac Merge branch 'stable' into new_release 2023-04-24 13:53:15 +02:00
Matthias
8086d90535 Update some tests for balance updates 2023-04-24 12:34:59 +02:00
Matthias
829724c0ec Fallback to "initialMargin" if collateral is not set 2023-04-24 12:13:24 +02:00
Matthias
68a8c79c08 Improve output for futures 2023-04-24 12:03:00 +02:00
Matthias
e99af87b6d store periodic breakdown in backtest results
This will enable the webserver to use this data.
2023-04-24 10:59:30 +02:00
Matthias
3948890c3b Add --breakdown to backtest-show 2023-04-24 10:35:46 +02:00
Matthias
d1e9e70396 Improve Resample-period test 2023-04-24 09:41:36 +02:00
Matthias
f761dc4e1b Merge pull request #8552 from freqtrade/dependabot/pip/develop/mkdocs-material-9.1.7
Bump mkdocs-material from 9.1.6 to 9.1.7
2023-04-24 09:22:32 +02:00
Matthias
666b3bf718 Merge pull request #8547 from freqtrade/dependabot/pip/develop/sqlalchemy-2.0.10
Bump sqlalchemy from 2.0.9 to 2.0.10
2023-04-24 08:49:05 +02:00
dependabot[bot]
f7c6828e6a Bump mkdocs-material from 9.1.6 to 9.1.7
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.1.6 to 9.1.7.
- [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.1.6...9.1.7)

---
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-04-24 06:02:27 +00:00
Matthias
0329c0c3f9 pre-commit - bump sqlalchemy 2023-04-24 07:59:21 +02:00
Matthias
2dddf7fbc7 Merge pull request #8550 from freqtrade/dependabot/pip/develop/filelock-3.12.0
Bump filelock from 3.11.0 to 3.12.0
2023-04-24 07:58:42 +02:00
Matthias
0ff2c66642 Merge pull request #8549 from freqtrade/dependabot/pip/develop/psutil-5.9.5
Bump psutil from 5.9.4 to 5.9.5
2023-04-24 07:58:24 +02:00
dependabot[bot]
c513d1077f Bump sqlalchemy from 2.0.9 to 2.0.10
Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 2.0.9 to 2.0.10.
- [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-04-24 05:32:38 +00:00
Matthias
fc39504cc2 Merge pull request #8544 from freqtrade/dependabot/pip/develop/ccxt-3.0.75
Bump ccxt from 3.0.69 to 3.0.75
2023-04-24 07:31:38 +02:00
Matthias
1976a79645 Merge pull request #8548 from freqtrade/dependabot/pip/develop/numpy-1.24.3
Bump numpy from 1.24.2 to 1.24.3
2023-04-24 07:26:40 +02:00
Matthias
5cc472e2ed Merge pull request #8545 from freqtrade/dependabot/pip/develop/ruff-0.0.262
Bump ruff from 0.0.261 to 0.0.262
2023-04-24 07:13:34 +02:00
Matthias
17c16fd4cb Merge pull request #8543 from freqtrade/dependabot/pip/develop/websockets-11.0.2
Bump websockets from 11.0.1 to 11.0.2
2023-04-24 07:11:33 +02:00
dependabot[bot]
598478e48d Bump filelock from 3.11.0 to 3.12.0
Bumps [filelock](https://github.com/tox-dev/py-filelock) from 3.11.0 to 3.12.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.11.0...3.12.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-04-24 04:00:11 +00:00
dependabot[bot]
15fdaecd7f Bump psutil from 5.9.4 to 5.9.5
Bumps [psutil](https://github.com/giampaolo/psutil) from 5.9.4 to 5.9.5.
- [Release notes](https://github.com/giampaolo/psutil/releases)
- [Changelog](https://github.com/giampaolo/psutil/blob/master/HISTORY.rst)
- [Commits](https://github.com/giampaolo/psutil/compare/release-5.9.4...release-5.9.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 03:59:43 +00:00
dependabot[bot]
43d0c7ff98 Bump numpy from 1.24.2 to 1.24.3
Bumps [numpy](https://github.com/numpy/numpy) from 1.24.2 to 1.24.3.
- [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.2...v1.24.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 03:59:22 +00:00
dependabot[bot]
a64b641fdf Bump ruff from 0.0.261 to 0.0.262
Bumps [ruff](https://github.com/charliermarsh/ruff) from 0.0.261 to 0.0.262.
- [Release notes](https://github.com/charliermarsh/ruff/releases)
- [Changelog](https://github.com/charliermarsh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/charliermarsh/ruff/compare/v0.0.261...v0.0.262)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 03:57:40 +00:00
dependabot[bot]
d320ea052f Bump ccxt from 3.0.69 to 3.0.75
Bumps [ccxt](https://github.com/ccxt/ccxt) from 3.0.69 to 3.0.75.
- [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/3.0.69...3.0.75)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 03:57:22 +00:00
dependabot[bot]
185ea9c98c Bump websockets from 11.0.1 to 11.0.2
Bumps [websockets](https://github.com/aaugustin/websockets) from 11.0.1 to 11.0.2.
- [Release notes](https://github.com/aaugustin/websockets/releases)
- [Commits](https://github.com/aaugustin/websockets/compare/11.0.1...11.0.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 03:56:58 +00:00
Matthias
2dd3b34136 Fix malrendering in freqAI docs 2023-04-23 19:36:27 +02:00
Matthias
ad4996259e Further increase typehints in freqAI interface 2023-04-23 19:36:17 +02:00
Matthias
c5dc21e80c Update freqAI documentation with missing typehints 2023-04-23 19:30:30 +02:00
Matthias
c20b074880 Add FAQ entry about permission error 2023-04-23 19:20:24 +02:00
Matthias
94a6bc608c Update stake-currency behavior 2023-04-22 17:42:09 +02:00
Matthias
741834301f Update tests 2023-04-22 17:21:03 +02:00
Matthias
f937818b80 Add "owned" fields to balance 2023-04-22 17:13:53 +02:00
Matthias
c4f8ff95dd Update tests 2023-04-22 16:13:27 +02:00
Matthias
dbf1f0897e Add /balance full, reduce regular balance output
closes #4497
2023-04-22 15:51:28 +02:00
Matthias
7a47500b22 Add "is_bot_managed" flag to API 2023-04-22 14:57:13 +02:00
Matthias
cb09ef7180 Extract converting wallet to est_stake 2023-04-22 11:48:59 +02:00
Matthias
ce75a032d0 Balance ratio calculation should ignore non-relevant assets
closes #8532
2023-04-22 11:48:59 +02:00
Matthias
5dccfab89c Add test for start_cap_ratio 2023-04-22 11:48:59 +02:00
Matthias
e836fe58b1 Merge pull request #8525 from tijptjik/develop
Docs : Correct user namespace from `cust_` to `custom_`
2023-04-22 11:48:54 +02:00
robcaulk
0a05099713 fix mypy 2023-04-21 22:52:19 +02:00
Matthias
3d4be92cc6 Add option pairlist parameter type 2023-04-21 19:30:32 +02:00
Matthias
9bc17a9232 Downgrade wheel to isntall gym 2023-04-21 06:19:57 +00:00
Matthias
4a4be27ebc use orderid from order, the trade one has been reset
part of #8526
2023-04-21 07:14:03 +02:00
Matthias
ca1a616b89 use Fstrings for log message 2023-04-21 07:08:14 +02:00
Matthias
c5bf029701 Better type response 2023-04-20 19:38:55 +02:00
Matthias
9e4f9798e6 Add pairlist "is-generator" to api 2023-04-20 19:33:36 +02:00
Matthias
3ef2a57bca Add "is_pairlist_generator" field to pairlists 2023-04-20 19:33:33 +02:00
Mart van de Ven
818da02f6c Edit Advanced Strategies intro for clarify and brevity 2023-04-20 14:01:01 +08:00
Mart van de Ven
b545fc5590 Correct user namespace from cust_ to custom_ 2023-04-20 13:36:31 +08:00
Matthias
e20b94d836 Add more filter param descriptions 2023-04-20 07:22:12 +02:00
Matthias
4636de30cd Improve pairlistparam types 2023-04-20 07:03:27 +02:00
Matthias
2ea157d9d3 Add some more pairlist parameter definitions 2023-04-20 06:58:05 +02:00
Matthias
987da010c9 Start pairlist parameter listing 2023-04-19 21:08:44 +02:00
Matthias
5ad352fdf1 add /pairlists to rest client 2023-04-19 21:08:28 +02:00
Matthias
1056ff0d18 Update variable to better reflect it's content 2023-04-19 20:20:29 +02:00
Matthias
b973b6255c Merge pull request #8524 from tijptjik/develop
Docs: Edited configuration.md for consistency
2023-04-19 19:40:31 +02:00
Matthias
f30fc29da0 Merge branch 'develop' into pr/richardjozsa/8336 2023-04-19 19:37:51 +02:00
Matthias
4a295d1910 Merge pull request #8521 from TheJoeSchr/develop
docs: use helper function `stoploss_from_absolute` in strategy callba…
2023-04-19 19:19:58 +02:00
Matthias
2df80fc49a Add /pairlists endpoint to api 2023-04-19 18:35:52 +02:00
Matthias
f1e03a6873 Update variable to better reflect it's content 2023-04-19 18:20:25 +02:00
Mart van de Ven
670a584d7e Fix markdown inconsistencies 2023-04-19 22:00:31 +08:00
Matthias
2f9e6c990c Update docs/strategy-callbacks.md 2023-04-19 15:26:33 +02:00
Mart van de Ven
66f5f76a6c Fix anchor for missing heading 2023-04-19 20:53:25 +08:00
Mart van de Ven
46f4fd79af Fix anchor for missing heading 2023-04-19 20:43:41 +08:00
Mart van de Ven
5ed072c489 Remove extraneous code block 2023-04-19 20:18:56 +08:00
TheJoeSchr
94e190b954 docs: strategy-callbacks: revert leverage=trade.leverage removal 2023-04-19 13:22:52 +02:00
Matthias
9851d67f07 Merge pull request #8499 from bkamuz/develop
Telegram. Fixed the blacklist removal message
2023-04-19 08:59:38 +02:00
Bohdan Kamuz
f99bdc4393 Merge branch 'freqtrade:develop' into develop 2023-04-18 23:49:06 +03:00
Matthias
caf524c685 Don't fail on leverage tier loading error
closes #8512
2023-04-18 18:01:12 +02:00
Joe Schr
f9124ef5b9 docs: strategy-callbacks: removes outdated leverage argument 2023-04-18 17:36:36 +02:00
hippocritical
e990b9fb13 Merge branch 'freqtrade:develop' into develop 2023-04-18 16:55:10 +02:00
Bohdan Kamuz
c297d99975 Telegram. Fixed the blacklist removal message 2023-04-18 10:09:48 +00:00
Joe Schr
6f401a9e15 docs: use helper function stoploss_from_absolute in strategy callbacks "absolute" example 2023-04-18 11:26:55 +02:00
Matthias
ea566c6eb7 Merge pull request #8517 from freqtrade/dependabot/pip/develop/ccxt-3.0.69
Bump ccxt from 3.0.59 to 3.0.69
2023-04-17 20:34:02 +02:00
Matthias
dfe8b3e832 Improve ruff rule selection 2023-04-17 20:33:19 +02:00
Matthias
3fb5cd3df6 Improve formatting 2023-04-17 20:27:18 +02:00
Matthias
7ff35fea3c Default weekly report to monday
closes #8502
2023-04-17 20:20:38 +02:00
dependabot[bot]
f049268354 Bump ccxt from 3.0.59 to 3.0.69
Bumps [ccxt](https://github.com/ccxt/ccxt) from 3.0.59 to 3.0.69.
- [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/3.0.59...3.0.69)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-17 18:03:14 +00:00
Matthias
362974b831 Update test to properly capture errors from leverage initialization 2023-04-17 20:00:57 +02:00
Matthias
14bca509da Cleanup some code 2023-04-17 19:55:58 +02:00
Matthias
b2ea464250 Handle individual exceptions when initializing leverage tiers
closes #8515
closes #8512
closes #8514
2023-04-17 19:52:19 +02:00
Matthias
d73e7f292a simplify Leverage tier code 2023-04-17 19:52:19 +02:00
Bohdan Kamuz
70e48ca43a Merge branch 'freqtrade:develop' into develop 2023-04-17 12:46:00 +03:00
Bohdan Kamuz
d34b15d6a9 Telegram. Fixed the blacklist removal message 2023-04-17 09:40:41 +00:00
Matthias
8dbe6b1c16 Merge pull request #8508 from freqtrade/dependabot/pip/develop/cryptography-40.0.2
Bump cryptography from 40.0.1 to 40.0.2
2023-04-17 10:23:12 +02:00
Matthias
daabc8ffbe Merge pull request #8426 from initrv/add-sb3-learn-progress-bar
Add sb3 learn progress bar
2023-04-17 10:22:49 +02:00
Matthias
45193127e3 Merge pull request #8511 from freqtrade/dependabot/pip/develop/fastapi-0.95.1
Bump fastapi from 0.95.0 to 0.95.1
2023-04-17 10:22:01 +02:00
Matthias
ccc59619d1 Merge pull request #8509 from freqtrade/dependabot/pip/develop/rich-13.3.4
Bump rich from 13.3.3 to 13.3.4
2023-04-17 10:20:58 +02:00
Bohdan Kamuz
c291d69533 Merge branch 'freqtrade:develop' into develop 2023-04-17 08:35:40 +03:00
Matthias
8aec71e27e Add bitvavo sublass to properly set ohlcv limit 2023-04-17 07:25:13 +02:00
Matthias
6c6d2a0f43 Improve live test resiliance 2023-04-17 07:25:13 +02:00
Matthias
8a8cd67988 Improve ccxt_ohlcv test debuggability 2023-04-17 07:25:13 +02:00
Matthias
b67bb0fe28 Merge pull request #8507 from freqtrade/dependabot/pip/develop/pytest-7.3.1
Bump pytest from 7.3.0 to 7.3.1
2023-04-17 07:03:53 +02:00
dependabot[bot]
d1b600e7b0 Bump fastapi from 0.95.0 to 0.95.1
Bumps [fastapi](https://github.com/tiangolo/fastapi) from 0.95.0 to 0.95.1.
- [Release notes](https://github.com/tiangolo/fastapi/releases)
- [Commits](https://github.com/tiangolo/fastapi/compare/0.95.0...0.95.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-04-17 04:29:10 +00:00
Matthias
e58f8e36c4 Merge pull request #8506 from freqtrade/dependabot/pip/develop/httpx-0.24.0
Bump httpx from 0.23.3 to 0.24.0
2023-04-17 06:28:25 +02:00
Matthias
342d43e6bb Merge pull request #8505 from freqtrade/dependabot/pip/develop/tensorboard-2.12.2
Bump tensorboard from 2.12.1 to 2.12.2
2023-04-17 06:27:38 +02:00
dependabot[bot]
7c95848271 Bump rich from 13.3.3 to 13.3.4
Bumps [rich](https://github.com/Textualize/rich) from 13.3.3 to 13.3.4.
- [Release notes](https://github.com/Textualize/rich/releases)
- [Changelog](https://github.com/Textualize/rich/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Textualize/rich/compare/v13.3.3...v13.3.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-17 03:57:33 +00:00
dependabot[bot]
864f53bc4b Bump cryptography from 40.0.1 to 40.0.2
Bumps [cryptography](https://github.com/pyca/cryptography) from 40.0.1 to 40.0.2.
- [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/40.0.1...40.0.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-17 03:57:23 +00:00
dependabot[bot]
f1fcd0760d Bump pytest from 7.3.0 to 7.3.1
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.3.0 to 7.3.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.3.0...7.3.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-04-17 03:57:07 +00:00
dependabot[bot]
f1730ab51b Bump httpx from 0.23.3 to 0.24.0
Bumps [httpx](https://github.com/encode/httpx) from 0.23.3 to 0.24.0.
- [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.3...0.24.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-17 03:56:52 +00:00
dependabot[bot]
dba21c815a Bump tensorboard from 2.12.1 to 2.12.2
Bumps [tensorboard](https://github.com/tensorflow/tensorboard) from 2.12.1 to 2.12.2.
- [Release notes](https://github.com/tensorflow/tensorboard/releases)
- [Changelog](https://github.com/tensorflow/tensorboard/blob/master/RELEASE.md)
- [Commits](https://github.com/tensorflow/tensorboard/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-17 03:56:47 +00:00
hippocritical
2b416d3b62 - Added a first version of docs (needs checking)
- optimized pairs for entry_varholder and exit_varholder to only check a single pair instead of all pairs.
- bias-check of freqai strategies now possible
- added condition to not crash when compared_df is empty (meaning no differences have been found)
2023-04-16 23:47:10 +02:00
Richard Jozsa
c055f82e9a Pip release follow up 2023-04-16 19:28:36 +02:00
Matthias
9caa74c796 Merge branch 'develop' into pr/initrv/8426 2023-04-16 18:16:16 +02:00
Richard Jozsa
8620f1178d Merge branch 'freqtrade:develop' into develop 2023-04-16 14:29:57 +02:00
Bohdan Kamuz
1370ee498c Merge branch 'freqtrade:develop' into develop 2023-04-16 14:39:44 +03:00
Matthias
501a290f81 Pin pip also for windows installs 2023-04-16 09:56:26 +02:00
Matthias
4ed670f828 pin pip installation to <23.1 - which breaks gym installation 2023-04-16 08:56:47 +02:00
Matthias
f6e93114e6 Update binance leverage tiers file 2023-04-16 08:35:17 +02:00
Robert Caulk
6bc8759321 Update constants.py
Make progress bar true by default
2023-04-15 20:01:12 +02:00
Bohdan Kamuz
22efd0bee6 Merge branch 'freqtrade:develop' into develop 2023-04-15 20:41:13 +03:00
Bohdan Kamuz
1d40162e9d Telegram. Fixed the blacklist removal message. 2023-04-15 15:57:31 +00:00
Matthias
20d17cbc52 Disable telegram from default_conf 2023-04-15 17:39:23 +02:00
hippocritical
d5c98a3c39 Merge branch 'freqtrade:develop' into develop 2023-04-15 14:31:27 +02:00
hippocritical
46b97d2be4 Merge remote-tracking branch 'origin/develop' into develop 2023-04-15 14:31:12 +02:00
hippocritical
767442198e saving and updating the csv file now works
open ended timeranges now work
if a file fails then it will not report as non-bias, but report in the table as error and the csv file will not have it listed.
2023-04-15 14:29:52 +02:00
Matthias
a78672c10b Improve log message formatting 2023-04-15 09:47:01 +02:00
Matthias
6a0a33739b order cost should be with leverage, not leverage-cleared
closes #8495
2023-04-15 09:09:28 +02:00
Matthias
b9f142c31e Add failing tests with leverage
related to #8495
2023-04-15 09:07:43 +02:00
Matthias
6e814af36d Add test asserting cost 2023-04-15 09:05:21 +02:00
Matthias
f814146093 Update ta-lib link
closes #8497
2023-04-14 18:06:06 +02:00
Robert Caulk
daa9f6cc19 Merge pull request #8494 from freqtrade/bug-fix-pytorch
Bug fix: ensure data is on same device as model
2023-04-14 00:31:43 +02:00
Matthias
a23ae6a979 Merge pull request #8468 from freqtrade/dependabot/pip/develop/ta-lib-0.4.26
Bump ta-lib from 0.4.25 to 0.4.26
2023-04-13 20:29:56 +02:00
Matthias
90ce2ae7e4 Merge branch 'develop' into pr/initrv/8426 2023-04-13 20:01:35 +02:00
Matthias
3c64c6b034 Merge pull request #8461 from freqtrade/feat/hyperopt_progressbar
hyperopt progressbar -> rich
2023-04-13 20:00:27 +02:00
Matthias
e25f6986d6 Improve windows doc wordings, remove reference to outdated binary provider. 2023-04-13 19:58:54 +02:00
Matthias
95cdb8aa04 Update ta-lib windows wheels 2023-04-13 19:58:34 +02:00
Matthias
4557701daa Merge pull request #8491 from Bloodhunter4rc/remotepairlist
Remotepairlist - fix continous fetching every x bot_loop seconds
2023-04-13 19:52:05 +02:00
Matthias
3b377149e4 Add clarifying comment, simplify code 2023-04-13 18:19:52 +02:00
Matthias
c0045bad34 Merge branch 'develop' into feat/hyperopt_progressbar 2023-04-13 18:01:29 +02:00
robcaulk
dcf9bbdaea ensure data is on same device as the model 2023-04-13 12:19:34 +02:00
hippocritical
a9ef4c3ab0 partial progress commit:
added terminal tabulate-output
added yet non-working csv output using pandas
2023-04-12 21:03:59 +02:00
Bloodhunter4rc
84d2d5e2a6 Change ["Dummy"] to [None]. 2023-04-12 19:32:28 +02:00
Matthias
0afd5a7385 Improve stoploss documentation
closes #8492
2023-04-12 18:13:16 +02:00
Bloodhunter4rc
44bf59668b prevents continous fetching every x bot_loop seconds , adheres to refresh_period, in case the pairlist returned from the remote end is empty. 2023-04-12 13:16:53 +02:00
Matthias
2131205db6 Bump tag length to 255 2023-04-12 07:19:36 +02:00
Matthias
b2b19915e6 Limit enter_tag and exit_reason to their actual field lenght
closes #8486
2023-04-12 07:19:36 +02:00
Matthias
bba6f8e133 Use length constant for tests 2023-04-12 07:19:36 +02:00
Matthias
a6d2233b95 Use constant for custom field lengths 2023-04-11 21:05:14 +02:00
Matthias
9857675a5e Update torch import 2023-04-11 19:38:24 +02:00
Robert Caulk
4ab047dfa7 Merge pull request #8297 from Yinon-Polak/feat/add-pytorch-model-support
Feat/add pytorch model support
2023-04-11 15:40:12 +02:00
Matthias
476ed938f5 Extract custom_tag limit from interface file 2023-04-11 07:26:38 +02:00
Matthias
40ffac9de0 Prevent random test failures by freezing time for certain tests 2023-04-10 19:45:24 +02:00
Matthias
b892d373cd Improve timerange parsing when accepting values from API 2023-04-10 19:45:24 +02:00
Matthias
c3647e49ad Merge pull request #8484 from freqtrade/dependabot/pip/develop/nbconvert-7.3.1
Bump nbconvert from 7.2.10 to 7.3.1
2023-04-10 19:38:12 +02:00
Matthias
37ed37dc76 Merge pull request #8485 from freqtrade/dependabot/pip/develop/mkdocs-material-9.1.6
Bump mkdocs-material from 9.1.5 to 9.1.6
2023-04-10 19:37:54 +02:00
Matthias
5cb688c112 Merge pull request #8482 from freqtrade/dependabot/pip/develop/websockets-11.0.1
Bump websockets from 11.0 to 11.0.1
2023-04-10 19:37:37 +02:00
Matthias
3e394d0612 Merge pull request #8480 from freqtrade/dependabot/pip/develop/sqlalchemy-2.0.9
Bump sqlalchemy from 2.0.8 to 2.0.9
2023-04-10 19:37:17 +02:00
dependabot[bot]
c4c2298686 Bump mkdocs-material from 9.1.5 to 9.1.6
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.1.5 to 9.1.6.
- [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.1.5...9.1.6)

---
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-04-10 16:17:10 +00:00
dependabot[bot]
8564dc10b2 Bump nbconvert from 7.2.10 to 7.3.1
Bumps [nbconvert](https://github.com/jupyter/nbconvert) from 7.2.10 to 7.3.1.
- [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.10...v7.3.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 16:16:42 +00:00
Matthias
3fb892fcb8 Merge pull request #8483 from freqtrade/dependabot/pip/develop/ruff-0.0.261
Bump ruff from 0.0.260 to 0.0.261
2023-04-10 18:16:24 +02:00
Matthias
9968348324 Merge pull request #8481 from freqtrade/dependabot/pip/develop/ccxt-3.0.59
Bump ccxt from 3.0.58 to 3.0.59
2023-04-10 18:15:44 +02:00
dependabot[bot]
fa293c54f8 Bump websockets from 11.0 to 11.0.1
Bumps [websockets](https://github.com/aaugustin/websockets) from 11.0 to 11.0.1.
- [Release notes](https://github.com/aaugustin/websockets/releases)
- [Commits](https://github.com/aaugustin/websockets/compare/11.0...11.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 15:46:40 +00:00
Matthias
95449ca886 Merge pull request #8478 from freqtrade/dependabot/pip/develop/schedule-1.2.0
Bump schedule from 1.1.0 to 1.2.0
2023-04-10 17:45:44 +02:00
Matthias
70fa4a53cd pre-commit - bump sqlalchemy 2023-04-10 17:45:23 +02:00
dependabot[bot]
467c63ff01 Bump ruff from 0.0.260 to 0.0.261
Bumps [ruff](https://github.com/charliermarsh/ruff) from 0.0.260 to 0.0.261.
- [Release notes](https://github.com/charliermarsh/ruff/releases)
- [Changelog](https://github.com/charliermarsh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/charliermarsh/ruff/compare/v0.0.260...v0.0.261)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 15:25:04 +00:00
Matthias
b8a9c200fe Merge pull request #8479 from freqtrade/dependabot/pip/develop/pre-commit-3.2.2
Bump pre-commit from 3.2.1 to 3.2.2
2023-04-10 17:24:02 +02:00
Matthias
7c10af65a1 Merge pull request #8477 from freqtrade/dependabot/pip/develop/plotly-5.14.1
Bump plotly from 5.14.0 to 5.14.1
2023-04-10 16:44:35 +02:00
Matthias
e2cd23b1d2 Remove deprecated pandas option 2023-04-10 16:33:56 +02:00
dependabot[bot]
0d408d3d43 Bump ccxt from 3.0.58 to 3.0.59
Bumps [ccxt](https://github.com/ccxt/ccxt) from 3.0.58 to 3.0.59.
- [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/3.0.58...3.0.59)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 14:20:19 +00:00
dependabot[bot]
2309197771 Bump sqlalchemy from 2.0.8 to 2.0.9
Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 2.0.8 to 2.0.9.
- [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-04-10 14:20:14 +00:00
dependabot[bot]
66fe9abce0 Bump pre-commit from 3.2.1 to 3.2.2
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 3.2.1 to 3.2.2.
- [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/v3.2.1...v3.2.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 14:20:03 +00:00
dependabot[bot]
200c18f3e4 Bump schedule from 1.1.0 to 1.2.0
Bumps [schedule](https://github.com/dbader/schedule) from 1.1.0 to 1.2.0.
- [Release notes](https://github.com/dbader/schedule/releases)
- [Changelog](https://github.com/dbader/schedule/blob/master/HISTORY.rst)
- [Commits](https://github.com/dbader/schedule/compare/1.1.0...1.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 14:19:59 +00:00
dependabot[bot]
351b5f6e65 Bump plotly from 5.14.0 to 5.14.1
Bumps [plotly](https://github.com/plotly/plotly.py) from 5.14.0 to 5.14.1.
- [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.14.0...v5.14.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 14:19:56 +00:00
Matthias
605cc20a21 Merge pull request #8459 from freqtrade/feat/kvstore
Add initial bot start time to /profit endpoint
2023-04-10 14:49:01 +02:00
Matthias
f73d2a5371 Ensure bot_start is called when visualizing results 2023-04-10 14:48:02 +02:00
Matthias
485a074674 Merge pull request #8472 from freqtrade/dependabot/pip/develop/types-python-dateutil-2.8.19.12
Bump types-python-dateutil from 2.8.19.11 to 2.8.19.12
2023-04-10 14:42:53 +02:00
Matthias
865cf5232b Merge pull request #8471 from freqtrade/dependabot/pip/develop/mypy-1.2.0
Bump mypy from 1.1.1 to 1.2.0
2023-04-10 14:42:35 +02:00
Matthias
95a24c3133 Merge pull request #8467 from freqtrade/dependabot/pip/develop/orjson-3.8.10
Bump orjson from 3.8.9 to 3.8.10
2023-04-10 14:41:25 +02:00
hippocritical
e5e63d5bee Merge branch 'freqtrade:develop' into develop 2023-04-10 08:26:51 +02:00
Matthias
6833059c70 Merge pull request #8474 from freqtrade/dependabot/github_actions/develop/pypa/gh-action-pypi-publish-1.8.5
Bump pypa/gh-action-pypi-publish from 1.8.4 to 1.8.5
2023-04-10 08:03:55 +02:00
Matthias
3833dc0b78 pre-commit - bump dateutil 2023-04-10 07:54:01 +02:00
Matthias
e0d3c771db Merge pull request #8465 from freqtrade/dependabot/pip/develop/ccxt-3.0.58
Bump ccxt from 3.0.50 to 3.0.58
2023-04-10 07:53:21 +02:00
dependabot[bot]
5a18ab0784 Bump mypy from 1.1.1 to 1.2.0
Bumps [mypy](https://github.com/python/mypy) from 1.1.1 to 1.2.0.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v1.1.1...v1.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 05:51:33 +00:00
Matthias
1d66f82b1d Merge pull request #8469 from freqtrade/dependabot/pip/develop/filelock-3.11.0
Bump filelock from 3.10.6 to 3.11.0
2023-04-10 07:50:48 +02:00
Matthias
2e765fe6d1 Merge pull request #8470 from freqtrade/dependabot/pip/develop/pymdown-extensions-9.11
Bump pymdown-extensions from 9.10 to 9.11
2023-04-10 07:50:25 +02:00
Matthias
21ea02bbcf Merge pull request #8466 from freqtrade/dependabot/pip/develop/pytest-7.3.0
Bump pytest from 7.2.2 to 7.3.0
2023-04-10 07:49:57 +02:00
dependabot[bot]
2ea0157197 Bump pypa/gh-action-pypi-publish from 1.8.4 to 1.8.5
Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.8.4 to 1.8.5.
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.8.4...v1.8.5)

---
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>
2023-04-10 03:57:51 +00:00
dependabot[bot]
03352f3b62 Bump types-python-dateutil from 2.8.19.11 to 2.8.19.12
Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.8.19.11 to 2.8.19.12.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 03:57:04 +00:00
dependabot[bot]
26eb4f7fe6 Bump pymdown-extensions from 9.10 to 9.11
Bumps [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions) from 9.10 to 9.11.
- [Release notes](https://github.com/facelessuser/pymdown-extensions/releases)
- [Commits](https://github.com/facelessuser/pymdown-extensions/compare/9.10...9.11)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 03:56:57 +00:00
dependabot[bot]
7e1f3aa545 Bump filelock from 3.10.6 to 3.11.0
Bumps [filelock](https://github.com/tox-dev/py-filelock) from 3.10.6 to 3.11.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.10.6...3.11.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-04-10 03:56:51 +00:00
dependabot[bot]
3505fbe783 Bump ta-lib from 0.4.25 to 0.4.26
Bumps [ta-lib](https://github.com/ta-lib/ta-lib-python) from 0.4.25 to 0.4.26.
- [Release notes](https://github.com/ta-lib/ta-lib-python/releases)
- [Changelog](https://github.com/TA-Lib/ta-lib-python/blob/master/CHANGELOG)
- [Commits](https://github.com/ta-lib/ta-lib-python/compare/TA_Lib-0.4.25...TA_Lib-0.4.26)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 03:56:48 +00:00
dependabot[bot]
14532e3a56 Bump orjson from 3.8.9 to 3.8.10
Bumps [orjson](https://github.com/ijl/orjson) from 3.8.9 to 3.8.10.
- [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.9...3.8.10)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 03:56:42 +00:00
dependabot[bot]
a449f7c78c Bump pytest from 7.2.2 to 7.3.0
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.2.2 to 7.3.0.
- [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.2...7.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 03:56:38 +00:00
dependabot[bot]
8854ef8cba Bump ccxt from 3.0.50 to 3.0.58
Bumps [ccxt](https://github.com/ccxt/ccxt) from 3.0.50 to 3.0.58.
- [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/3.0.50...3.0.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-04-10 03:56:33 +00:00
Matthias
526943f29e Remove freqUI alpha warning 2023-04-09 19:44:38 +02:00
Matthias
cf770d496b Improve visual display of progressbar 2023-04-09 18:25:50 +02:00
Matthias
bfd9e35e34 Replace hyperopt progressbar with rich progressbar 2023-04-09 18:17:22 +02:00
Matthias
299e788891 Dump progressbar2 dependency 2023-04-09 18:07:38 +02:00
Matthias
4c1de4ad56 Update tests 2023-04-09 18:07:38 +02:00
Matthias
ed57e7d43b Refactor logging to be a package, instead of a module 2023-04-09 16:48:18 +02:00
Matthias
818d18d4e0 Add StdErrStreamHandler to logging 2023-04-09 16:23:00 +02:00
Matthias
b6aac5079b REmove Rich-progress wrapper again 2023-04-09 16:21:30 +02:00
Matthias
40450ebecc Add dependency on Rich 2023-04-09 16:05:23 +02:00
Matthias
d532da9071 Add Rich Progressbar Wrapper 2023-04-09 16:04:31 +02:00
Matthias
df51111c33 Always show strategy summary 2023-04-09 08:53:36 +02:00
Matthias
dd8900a1c6 Improve ordering of backtest output 2023-04-09 08:53:36 +02:00
Matthias
5404905d28 Fix typos in docs 2023-04-08 17:13:51 +02:00
Matthias
bed51fa790 Properly build specific Torch image 2023-04-08 17:00:25 +02:00
Matthias
f5a5c2d6b9 Improve imports 2023-04-08 16:44:33 +02:00
Matthias
a102cfdfc9 Add new /profit fields to API 2023-04-08 16:41:25 +02:00
Matthias
be72670ca2 Add documentation about /profit change 2023-04-08 16:40:14 +02:00
Matthias
cf2cb94f8d Add bot start date to /profit output 2023-04-08 16:38:44 +02:00
Matthias
fa3a81b022 convert Keys to enum 2023-04-08 16:28:50 +02:00
Matthias
7ff30c6df8 Add additional, typesafe getters 2023-04-08 16:24:38 +02:00
Matthias
7751768b2e Store initial_time value 2023-04-08 16:13:16 +02:00
Matthias
9c2cdd4fb9 Merge pull request #8388 from freqtrade/patch-pair-colon-bug
Bug fix: FreqAI backtest target setting
2023-04-08 14:16:41 +02:00
robcaulk
69b9b35a08 Merge remote-tracking branch 'origin/develop' into feat/add-pytorch-model-support 2023-04-08 13:22:25 +02:00
robcaulk
c2c97d9f78 make a fake pair_dict instead of MagicMocking it 2023-04-08 13:20:29 +02:00
robcaulk
48d3c8e62e fix model loading from disk bug, improve doc, clarify installation/docker instructions, add a torch tag to the freqairl docker image. Fix seriously outdated prediction_model docstrings 2023-04-08 12:09:53 +02:00
Matthias
ac817b7808 Improve docstrings for key-value store 2023-04-08 10:09:31 +02:00
Matthias
4d4f4bf23e Add test for key_value_store 2023-04-08 10:07:21 +02:00
Matthias
c083723698 Add initial version of key value store 2023-04-08 10:07:03 +02:00
Matthias
f8d89c46e5 Don't reset open_order_id if the order didn't cancel 2023-04-07 19:49:13 +02:00
Matthias
1952e453bb Improved formatting for fetch order_or_stop calls 2023-04-07 17:35:11 +02:00
Matthias
77985fa591 Update thread name for uvicorn worker 2023-04-07 14:49:53 +02:00
Matthias
a75d891007 Ensure minimum sqlalchemy version is respected 2023-04-07 14:45:06 +02:00
Matthias
dae3f72be7 Bump Dockerfile to latest 3.10 2023-04-07 14:11:31 +02:00
Matthias
f03a99918a Ensure hyper param file can be loaded
closes #8452
2023-04-04 20:04:28 +02:00
Yinon Polak
a655524221 pytorch mlp rename input to fix mypy error 2023-04-04 12:24:29 +03:00
Yinon Polak
26738370c7 pytorch mlp add explicit annotation to fix mypy error 2023-04-04 12:12:02 +03:00
Matthias
fe02f611fb Fix typo in reinforcement learning
closes #8431
2023-04-04 06:46:35 +02:00
Matthias
1b10a3a2bf Merge branch 'develop' of github.com:freqtrade/freqtrade into develop 2023-04-03 20:24:58 +02:00
Matthias
92a060c5b4 Make stop_price_parameter configurable by exchange 2023-04-03 20:18:57 +02:00
hippocritical
0fb155d6ee Merge branch 'freqtrade:develop' into develop 2023-04-03 20:17:36 +02:00
Matthias
096fd1916c Merge pull request #8445 from freqtrade/dependabot/pip/develop/tensorboard-2.12.1
Bump tensorboard from 2.12.0 to 2.12.1
2023-04-03 19:14:29 +02:00
Matthias
fb09a16127 Merge pull request #8438 from freqtrade/dependabot/pip/develop/types-tabulate-0.9.0.2
Bump types-tabulate from 0.9.0.1 to 0.9.0.2
2023-04-03 18:12:30 +02:00
Yinon Polak
6b204c97ed fix pytorch data convertor type hints 2023-04-03 19:02:07 +03:00
Yinon Polak
0c4574b3b7 prevent mypy error, explicitly unpack input list of pytorch mlp model, 2023-04-03 18:10:47 +03:00
Yinon Polak
d9d9993179 add documentation 2023-04-03 17:06:39 +03:00
Yinon Polak
7b494c8333 add documentation to pytorch data convertor 2023-04-03 16:39:49 +03:00
Yinon Polak
bc9454e0f9 add device to data convertor class doc 2023-04-03 16:36:38 +03:00
Yinon Polak
36a0a14a23 clean code 2023-04-03 16:26:42 +03:00
Yinon Polak
c137666230 fix imports 2023-04-03 16:03:15 +03:00
Matthias
7fed0782d5 pre-commit types-tabulate 2023-04-03 14:19:11 +02:00
Yinon Polak
bd3b70293f add pytorch data convertor 2023-04-03 15:19:10 +03:00
dependabot[bot]
30fc24bd8c Bump types-tabulate from 0.9.0.1 to 0.9.0.2
Bumps [types-tabulate](https://github.com/python/typeshed) from 0.9.0.1 to 0.9.0.2.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-03 12:18:15 +00:00
Matthias
7e3de178e1 Merge pull request #8447 from freqtrade/dependabot/pip/develop/types-python-dateutil-2.8.19.11
Bump types-python-dateutil from 2.8.19.10 to 2.8.19.11
2023-04-03 14:17:24 +02:00
Matthias
0c9c9fff0e Merge branch 'develop' into dependabot/pip/develop/types-python-dateutil-2.8.19.11 2023-04-03 13:41:10 +02:00
Matthias
b96f6670e3 pre-commit dateutil 2023-04-03 13:28:17 +02:00
Matthias
6e02743256 Merge pull request #8446 from freqtrade/dependabot/pip/develop/types-requests-2.28.11.17
Bump types-requests from 2.28.11.16 to 2.28.11.17
2023-04-03 13:27:31 +02:00
Matthias
2b4fa92d09 Merge pull request #8444 from freqtrade/dependabot/pip/develop/ruff-0.0.260
Bump ruff from 0.0.259 to 0.0.260
2023-04-03 11:40:07 +02:00
Matthias
be250230b6 Merge pull request #8443 from freqtrade/dependabot/pip/develop/plotly-5.14.0
Bump plotly from 5.13.1 to 5.14.0
2023-04-03 11:39:42 +02:00
Matthias
5d33ffc015 Merge pull request #8442 from freqtrade/dependabot/pip/develop/orjson-3.8.9
Bump orjson from 3.8.8 to 3.8.9
2023-04-03 11:04:17 +02:00
Matthias
b48498f27f Types pre-commit 2023-04-03 10:16:56 +02:00
Matthias
e582d8bacb Merge pull request #8434 from freqtrade/dependabot/pip/develop/sqlalchemy-2.0.8
Bump sqlalchemy from 2.0.7 to 2.0.8
2023-04-03 10:16:00 +02:00
dependabot[bot]
ff40ee655b Bump types-python-dateutil from 2.8.19.10 to 2.8.19.11
Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.8.19.10 to 2.8.19.11.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-03 07:49:24 +00:00
dependabot[bot]
57deaad806 Bump types-requests from 2.28.11.16 to 2.28.11.17
Bumps [types-requests](https://github.com/python/typeshed) from 2.28.11.16 to 2.28.11.17.
- [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-04-03 07:49:21 +00:00
dependabot[bot]
7779b82277 Bump tensorboard from 2.12.0 to 2.12.1
Bumps [tensorboard](https://github.com/tensorflow/tensorboard) from 2.12.0 to 2.12.1.
- [Release notes](https://github.com/tensorflow/tensorboard/releases)
- [Changelog](https://github.com/tensorflow/tensorboard/blob/2.12.1/RELEASE.md)
- [Commits](https://github.com/tensorflow/tensorboard/compare/2.12.0...2.12.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-03 07:49:18 +00:00
dependabot[bot]
2bd2058afa Bump ruff from 0.0.259 to 0.0.260
Bumps [ruff](https://github.com/charliermarsh/ruff) from 0.0.259 to 0.0.260.
- [Release notes](https://github.com/charliermarsh/ruff/releases)
- [Changelog](https://github.com/charliermarsh/ruff/blob/main/BREAKING_CHANGES.md)
- [Commits](https://github.com/charliermarsh/ruff/compare/v0.0.259...v0.0.260)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-03 07:49:12 +00:00
dependabot[bot]
bf7936b0af Bump plotly from 5.13.1 to 5.14.0
Bumps [plotly](https://github.com/plotly/plotly.py) from 5.13.1 to 5.14.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.13.1...v5.14.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-04-03 07:48:50 +00:00
dependabot[bot]
8236bbfd48 Bump orjson from 3.8.8 to 3.8.9
Bumps [orjson](https://github.com/ijl/orjson) from 3.8.8 to 3.8.9.
- [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.8...3.8.9)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-03 07:48:43 +00:00
Matthias
4dc13ac16a Merge pull request #8437 from freqtrade/dependabot/pip/develop/ccxt-3.0.50
Bump ccxt from 3.0.37 to 3.0.50
2023-04-03 09:47:27 +02:00
Matthias
eb5423469a Merge pull request #8435 from freqtrade/dependabot/pip/develop/xgboost-1.7.5
Bump xgboost from 1.7.4 to 1.7.5
2023-04-03 09:47:09 +02:00
Matthias
43496d7929 bump sqlalchemy pre-commit 2023-04-03 09:46:32 +02:00
Matthias
92c70b6b90 Merge pull request #8441 from freqtrade/dependabot/github_actions/develop/pypa/gh-action-pypi-publish-1.8.4
Bump pypa/gh-action-pypi-publish from 1.8.3 to 1.8.4
2023-04-03 09:45:51 +02:00
Matthias
77897c7d6b Merge pull request #8439 from freqtrade/dependabot/pip/develop/mkdocs-material-9.1.5
Bump mkdocs-material from 9.1.4 to 9.1.5
2023-04-03 09:45:26 +02:00
Matthias
531861573a Merge pull request #8436 from freqtrade/dependabot/pip/develop/types-cachetools-5.3.0.5
Bump types-cachetools from 5.3.0.4 to 5.3.0.5
2023-04-03 09:45:10 +02:00
Matthias
c9b904eb0e Fix typos in documentation 2023-04-03 06:49:30 +02:00
Matthias
372f1cb37f Reduce verbosity for stop orders 2023-04-03 06:37:31 +02:00
Matthias
a3acdd5240 apply stop-reserve to minimum limits only when necessary
it's unnecessary for amount - but necessary for Cost / price limits.
2023-04-03 06:37:31 +02:00
Matthias
e6a125719e Slightly refactor _get_stake_amount_limit 2023-04-03 06:37:31 +02:00
Matthias
78a1551798 Reorder get_stake_limit 2023-04-03 06:37:31 +02:00
Matthias
6f79d14c9c pre-commit - bump cachetools 2023-04-03 06:37:15 +02:00
Matthias
28d8722fa7 Merge pull request #8433 from freqtrade/dependabot/pip/develop/websockets-11.0
Bump websockets from 10.4 to 11.0
2023-04-03 06:36:30 +02:00
dependabot[bot]
2715b2ccf0 Bump pypa/gh-action-pypi-publish from 1.8.3 to 1.8.4
Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.8.3 to 1.8.4.
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.8.3...v1.8.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>
2023-04-03 03:58:12 +00:00
dependabot[bot]
2ea575cb31 Bump mkdocs-material from 9.1.4 to 9.1.5
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.1.4 to 9.1.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.1.4...9.1.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-04-03 03:57:30 +00:00
dependabot[bot]
1b31c54162 Bump ccxt from 3.0.37 to 3.0.50
Bumps [ccxt](https://github.com/ccxt/ccxt) from 3.0.37 to 3.0.50.
- [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/3.0.37...3.0.50)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-03 03:57:19 +00:00
dependabot[bot]
e289c10b6c Bump types-cachetools from 5.3.0.4 to 5.3.0.5
Bumps [types-cachetools](https://github.com/python/typeshed) from 5.3.0.4 to 5.3.0.5.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-03 03:57:10 +00:00
dependabot[bot]
26ed1ca07c Bump xgboost from 1.7.4 to 1.7.5
Bumps [xgboost](https://github.com/dmlc/xgboost) from 1.7.4 to 1.7.5.
- [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.4...v1.7.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-03 03:57:05 +00:00
dependabot[bot]
b1e20bcd1e Bump sqlalchemy from 2.0.7 to 2.0.8
Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 2.0.7 to 2.0.8.
- [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-04-03 03:57:00 +00:00
dependabot[bot]
12a73bc151 Bump websockets from 10.4 to 11.0
Bumps [websockets](https://github.com/aaugustin/websockets) from 10.4 to 11.0.
- [Release notes](https://github.com/aaugustin/websockets/releases)
- [Commits](https://github.com/aaugustin/websockets/compare/10.4...11.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-03 03:56:46 +00:00
Matthias
19e112f399 Merge pull request #8427 from initrv/typo-fix-constants
Typo fix constants
2023-04-02 07:42:15 +02:00
initrv
cfc0410388 use rl_config get instead of freqai_info 2023-04-02 04:08:07 +03:00
initrv
cccf4f305b fix randomize_starting_position typo 2023-04-02 03:42:05 +03:00
initrv
4c608e7167 remove misplaced param 2023-04-02 03:12:24 +03:00
initrv
cab82e8e60 Add sb3 learn progress bar 2023-04-02 02:59:02 +03:00
Matthias
dc7e834911 Fix some type issues 2023-04-01 20:17:56 +02:00
Matthias
a630799984 Merge pull request #8423 from freqtrade/add-profit-trade-history
make trade_type value more explicit, add profit to trade_history dict
2023-04-01 15:19:54 +02:00
Matthias
916e1bbc7c Merge pull request #8412 from freqtrade/fix/partial_stops
support partially filled stops
2023-04-01 15:18:42 +02:00
Robert Caulk
631cb44f5c ensure python code block renders 2023-04-01 15:16:48 +02:00
Robert Caulk
367186cc34 Update freqai-feature-engineering.md
The `metadata` section of `freqai-feature-engineering.md` had a misplaced whitespace in front of the title. 

This PR removes the whitespace.
2023-04-01 15:16:43 +02:00
robcaulk
92f34f262e make trade_type value more explicit, add profit to trade_history dict 2023-04-01 10:05:58 +02:00
Matthias
5e13b48648 Merge pull request #8386 from freqtrade/feature/price_to_precision_round
price to precision rounding
2023-03-31 07:20:10 +02:00
Matthias
6dfb1a1d14 Improve docker regular build caching 2023-03-31 06:49:12 +02:00
Matthias
f8330800d1 Improve docker arm builds 2023-03-31 06:49:02 +02:00
Matthias
3ec7c72da1 Bump develop version to 2023.4.dev 2023-03-30 07:06:23 +02:00
robcaulk
355fde3bca revert setting dk to live in test_plot_feature_importances 2023-03-29 22:01:54 +02:00
hippocritical
bad2cdabf2 Merge branch 'freqtrade:develop' into develop 2023-03-29 20:51:59 +02:00
Matthias
861c577138 Support partially filled stop orders
closes #8374
2023-03-29 07:05:39 +02:00
Matthias
e062a74e70 Add test for partial stop order canceling
part of #8374
2023-03-29 06:57:17 +02:00
Matthias
c330c493d5 test for Handle stop on exchange partial filled
part of #8374
2023-03-29 06:57:17 +02:00
hippocritical
7bd55971dc strategy_updater:
removed args_common_optimize for strategy-updater

backtest_lookahead_bias_checker:
added args and cli-options for minimum and target trade amounts
fixed code according to best-practice coding requests of matthias (CamelCase etc)
2023-03-28 22:20:00 +02:00
Yinon Polak
5a7ca35c6b declare class names in FreqaiExampleHybridStrategy 2023-03-28 16:24:49 +03:00
Yinon Polak
077a947972 clean code 2023-03-28 15:18:10 +03:00
Yinon Polak
8ac3a94358 add note to pytorch docs - setting class names for classifiers 2023-03-28 15:17:40 +03:00
Yinon Polak
dfbebdea9b improve comment on class_names in freqai interface 2023-03-28 14:44:44 +03:00
Yinon Polak
b795a70102 fix config example in pytorch mlp documentation 2023-03-28 14:44:43 +03:00
Yinon Polak
026b6a39a9 bugfix skip test split when empty 2023-03-28 14:40:23 +03:00
Richard Jozsa
7cbc0ce80a Merge branch 'freqtrade:develop' into develop 2023-03-28 01:23:24 +02:00
robcaulk
3cabcabcbd ensure labels are properly defined in backtesting 2023-03-27 15:23:01 +02:00
robcaulk
55781e7f10 fix tests 2023-03-26 19:22:52 +02:00
robcaulk
f1e831a7b8 fix bug in backtest target setting 2023-03-26 13:43:59 +02:00
Matthias
159090c0e7 Add explicit tests for TRUNCATE mode 2023-03-26 11:14:34 +02:00
Matthias
0cb28f3d82 Use kwarg for rounding_mode, update tests with additional parameter 2023-03-26 11:00:41 +02:00
Matthias
d0d0cbe1d1 Implement price_to_precision logic for stoploss 2023-03-26 10:37:18 +02:00
Matthias
02078456fc Merge branch 'develop' into pr/asuiu/8296 2023-03-26 10:28:02 +02:00
Matthias
01dfb1cba8 Revert having price_rounding_mode as configuration 2023-03-26 10:24:47 +02:00
hippocritical
efefcb240b Merge branch 'freqtrade:develop' into develop 2023-03-24 22:37:21 +01:00
Yinon Polak
8903ba5d89 fix enf of file 2023-03-24 20:35:55 +03:00
Yinon Polak
eabd321281 small docs change 2023-03-23 15:59:57 +02:00
Yinon Polak
45c6ae446f small docs change 2023-03-23 15:04:29 +02:00
Yinon Polak
952e641213 small docs change 2023-03-23 12:43:37 +02:00
Yinon Polak
c44b5b1b3a add pytorch parameters to parameter table docs 2023-03-23 12:41:20 +02:00
Yinon Polak
fc8625c5c5 add pytorch classes uml diagram 2023-03-23 12:13:27 +02:00
Yinon Polak
36a005754a add pytorch documentation 2023-03-22 18:15:57 +02:00
Yinon Polak
479aafc331 rename Torch to PyTorch 2023-03-22 17:50:00 +02:00
hippocritical
f57787882d Merge remote-tracking branch 'origin/develop' into develop 2023-03-22 12:44:29 +01:00
hippocritical
d12a7ff18b freqtrades' merge broke my side, fixed it by porting it over to my develop branch, no changes with this commit logic-wise. 2023-03-22 12:32:39 +01:00
Yinon Polak
f81e3d8667 sort imports 2023-03-21 16:42:13 +02:00
Yinon Polak
b9c7d338b3 fix test_start_backtesting 2023-03-21 16:38:05 +02:00
Yinon Polak
4f93106755 Merge remote-tracking branch 'origin/feat/add-pytorch-model-support' into feat/add-pytorch-model-support 2023-03-21 16:26:42 +02:00
Yinon Polak
02bccd0097 add pytorch mlp models to test_start_backtesting 2023-03-21 16:20:35 +02:00
robcaulk
1ba01746a0 organize pytorch files 2023-03-21 15:09:54 +01:00
Yinon Polak
83a7d888bc type hint init in pytorch mlp classes 2023-03-21 15:19:34 +02:00
Yinon Polak
eba82360fa skip pytorch tests on python 3.11 and intel based mac os 2023-03-21 15:18:05 +02:00
Yinon Polak
3fa23860c0 skip pytorch tests on python 3.11 and intel based mac os 2023-03-21 14:34:27 +02:00
Yinon Polak
a80afc8f1b add optional target tensor squeezing to pytorch trainer 2023-03-21 13:20:54 +02:00
Yinon Polak
97339e14cf round up divisions in calc_n_epochs 2023-03-21 12:29:05 +02:00
Yinon Polak
443263803c unsqueeze target tensor when 1 dimensional 2023-03-21 11:42:05 +02:00
Yinon Polak
9906e7d646 clean code 2023-03-21 11:23:45 +02:00
Yinon Polak
e8f040bfbd add class_name attribute to freqai interface 2023-03-20 20:38:43 +02:00
Yinon Polak
a4b617e482 type hints fixes 2023-03-20 20:22:28 +02:00
Yinon Polak
c06cd38951 clean code 2023-03-20 19:55:39 +02:00
Yinon Polak
0a55753faf move default attributes of pytorch classifier to initializer,
to prevent mypy from complaining
2023-03-20 19:40:36 +02:00
Yinon Polak
6b4d9f97c1 clean code 2023-03-20 19:28:30 +02:00
Yinon Polak
bf4aa91aab Merge remote-tracking branch 'origin/feat/add-pytorch-model-support' into feat/add-pytorch-model-support
# Conflicts:
#	freqtrade/freqai/base_models/PyTorchModelTrainer.py
#	freqtrade/freqai/prediction_models/PyTorchClassifier.py
#	freqtrade/freqai/prediction_models/PyTorchMLPClassifier.py
#	freqtrade/freqai/prediction_models/PyTorchMLPModel.py
#	tests/freqai/test_freqai_interface.py
2023-03-20 18:44:24 +02:00
Yinon Polak
500c401b75 improve pytorch classifier documentation 2023-03-20 18:41:04 +02:00
Yinon Polak
81a2cbb4eb fix tests 2023-03-20 18:41:04 +02:00
Yinon Polak
0510cf4491 add config params to tests 2023-03-20 18:41:04 +02:00
Yinon Polak
68728409aa add pytorch regressor test 2023-03-20 18:41:04 +02:00
Yinon Polak
c00ffcee59 fix pytorch classifier test 2023-03-20 18:41:04 +02:00
Yinon Polak
9aec1ddb17 sort imports 2023-03-20 18:41:04 +02:00
Yinon Polak
d98890f32e sort imports 2023-03-20 18:41:04 +02:00
Yinon Polak
f659f8e309 remove unused imports 2023-03-20 18:41:04 +02:00
Yinon Polak
54db239175 add pytorch regressor example 2023-03-20 18:41:04 +02:00
Yinon Polak
601c37f862 refactor classifiers class names 2023-03-20 18:41:04 +02:00
Yinon Polak
501e746c52 improve mlp documentation 2023-03-20 18:41:04 +02:00
Yinon Polak
d04146d1b1 improve mlp documentation 2023-03-20 18:41:04 +02:00
Yinon Polak
ea08931ab3 add mlp documentation 2023-03-20 18:41:04 +02:00
Yinon Polak
ddd1b5c0ff modify feedforward net, move layer norm to start of thr block 2023-03-20 18:41:04 +02:00
Yinon Polak
e08d8190ae fix test 2023-03-20 18:41:04 +02:00
Yinon Polak
fbf7049ac5 sort imports 2023-03-20 18:41:04 +02:00
Yinon Polak
2a1a8c0e64 fix test 2023-03-20 18:41:04 +02:00
Yinon Polak
833aaf8e10 create children class to PyTorchClassifier to implement the fit method where we initialize the trainer and model objects 2023-03-20 18:41:04 +02:00
Yinon Polak
566346dd87 classifier test - set model file extension 2023-03-20 18:41:03 +02:00
Yinon Polak
d0a33d2ee7 fix tests 2023-03-20 18:41:03 +02:00
robcaulk
fab505be1b cheat flake8 for now until we can refactor save into the model class 2023-03-20 18:41:03 +02:00
Richard Jozsa
66c326b789 Add proper handling of multiple environments 2023-03-20 15:54:58 +01:00
Yinon Polak
2f386913ac refactor classifiers class names 2023-03-20 11:54:17 +02:00
Yinon Polak
1c11a5f048 improve mlp documentation 2023-03-19 18:10:57 +02:00
Yinon Polak
903a1dc3e5 improve mlp documentation 2023-03-19 18:04:01 +02:00
Yinon Polak
6f9a8a089c add mlp documentation 2023-03-19 17:45:30 +02:00
Yinon Polak
8bee499328 modify feedforward net, move layer norm to start of thr block 2023-03-19 17:03:36 +02:00
Matthias
f455e3327c Simplify method further 2023-03-19 15:01:37 +01:00
Matthias
cd9c2c4c23 Merge branch 'develop' into pr/froggleston/7861 2023-03-19 15:00:20 +01:00
Matthias
af6fc886f6 Small refactor for new methods 2023-03-19 14:56:41 +01:00
Yinon Polak
719faab4b8 fix test 2023-03-19 15:21:34 +02:00
Yinon Polak
9f477aa3c9 sort imports 2023-03-19 15:09:50 +02:00
Yinon Polak
61ac36c576 fix test 2023-03-19 14:49:12 +02:00
Yinon Polak
366c148c10 create children class to PyTorchClassifier to implement the fit method where we initialize the trainer and model objects 2023-03-19 14:38:49 +02:00
Yinon Polak
a49f62eecb classifier test - set model file extension 2023-03-18 20:51:30 +02:00
Yinon Polak
fab9ff1294 fix tests 2023-03-18 15:27:38 +02:00
Yinon Polak
1c91b4427b Merge remote-tracking branch 'origin/feat/add-pytorch-model-support' into feat/add-pytorch-model-support 2023-03-18 14:14:38 +02:00
Yinon Polak
244662b1a4 set class names attribute in the general classifier testing strategy 2023-03-18 14:12:31 +02:00
Richard Jozsa
d03fe1f8ee add latest experimental version of gymnasium 2023-03-16 00:53:37 +01:00
robcaulk
4550447409 cheat flake8 for now until we can refactor save into the model class 2023-03-14 21:13:30 +01:00
Yinon Polak
366740885a reduce mlp number of parameters for testing 2023-03-13 20:18:26 +02:00
Yinon Polak
918889a2bd reduce mlp number of parameters for testing 2023-03-13 20:09:12 +02:00
pbs
fc6d7f012e Support for python 3.11 2023-03-13 17:34:34 +00:00
Yinon Polak
9c8c30b0e8 add test 2023-03-13 17:17:00 +02:00
Yinon Polak
d7ea750823 revert to using model_training_parameters 2023-03-13 00:35:51 +02:00
Yinon Polak
b6096efadd logging change 2023-03-13 00:35:14 +02:00
Yinon Polak
b927c9dc01 remove train loss calculation from estimate_loss 2023-03-13 00:17:34 +02:00
Yinon Polak
523a58d3d6 simplify statement for pytorch file_type extension 2023-03-13 00:16:44 +02:00
Yinon Polak
0012fe36ca sort imports 2023-03-12 16:16:04 +02:00
Yinon Polak
cb17b36981 simplify file_type check comparisons 2023-03-12 14:50:08 +02:00
Yinon Polak
f9fdf1c31b generalize mlp model 2023-03-12 14:31:08 +02:00
Yinon Polak
1cf0e7be24 use one iteration on all test and train data for evaluation 2023-03-12 12:48:15 +02:00
Yinon Polak
8a9f2aedbb improve documentation 2023-03-09 14:55:52 +02:00
Yinon Polak
e88a0d5248 convert single quotes to double quotes 2023-03-09 13:29:11 +02:00
Yinon Polak
2ef11faba7 reformat documentation 2023-03-09 13:25:20 +02:00
Yinon Polak
c9eee2944b reformat documentation 2023-03-09 13:01:04 +02:00
Yinon Polak
6f962362f2 expand pytorch trainer documentation 2023-03-09 12:45:46 +02:00
Yinon Polak
ba5de0cd00 add documentation 2023-03-09 11:21:10 +02:00
Yinon Polak
3081b9402b add documentation 2023-03-09 11:14:54 +02:00
ASU
1132fa6093 feat: Added price_rounding modes in config 2023-03-09 02:11:31 +02:00
Yinon Polak
1597c3aa89 set class names in IStrategy.set_freqai_targets method, also save class name with model meta data 2023-03-08 18:36:44 +02:00
Yinon Polak
7d26df01b8 fix tensor type hint 2023-03-08 16:17:19 +02:00
Yinon Polak
c8296ccb2d sort imports 2023-03-08 16:13:35 +02:00
Yinon Polak
8d60327d60 add missing import 2023-03-08 16:12:47 +02:00
Yinon Polak
04564dc134 add missing import 2023-03-08 16:11:51 +02:00
Yinon Polak
6161b858c4 sort imports 2023-03-08 16:10:25 +02:00
Yinon Polak
1921a07b89 sort imports 2023-03-08 16:08:04 +02:00
Yinon Polak
b65ade51be revert config_freqai_example changes 2023-03-08 16:05:02 +02:00
Yinon Polak
dfbb2e2b35 sort imports 2023-03-08 16:03:36 +02:00
Yinon Polak
1805db2b07 change documentation and small bugfix 2023-03-08 15:38:22 +02:00
Yinon Polak
76fbec0c17 ad multiclass target names encoder to ints 2023-03-08 14:29:38 +02:00
Yinon Polak
4241bff32a type hints fixes 2023-03-06 20:15:36 +02:00
Yinon Polak
5dd60eda36 type hints fixes 2023-03-06 19:37:08 +02:00
Yinon Polak
8acdd0b47c type hints fixes 2023-03-06 19:14:54 +02:00
Yinon Polak
125085fbaf add freqai.model_exists pytorch file type support 2023-03-06 18:10:49 +02:00
Yinon Polak
7eedcb9c14 reformat code 2023-03-06 17:56:07 +02:00
Yinon Polak
e6e747bcd8 reformat code 2023-03-06 17:50:02 +02:00
Yinon Polak
348a08f1c4 add todo - currently assuming class labels are strings ['0.0', '1.0' .. n_classes]. need to resolve it per ClassifierModel 2023-03-06 16:41:47 +02:00
Yinon Polak
b1ac2bf515 use data loader, add evaluation on epoch 2023-03-06 16:16:45 +02:00
Yinon Polak
751b205618 initial commit 2023-03-05 16:59:24 +02:00
Timothy Pogue
97a6fb285f revert to dataframe.to_json 2023-01-10 17:52:24 -07:00
froggleston
3adb3d9b1e Merge branch 'reject_report' of github.com:froggleston/freqtrade into reject_report 2022-12-08 18:49:17 +00:00
froggleston
6f08b610d6 Merge branch 'develop' of github.com:froggleston/freqtrade into reject_report 2022-12-08 18:48:33 +00:00
froggleston
f5359985e8 Make CLI option and docs clearer that we're handling signals not trades 2022-12-08 18:47:09 +00:00
Robert Davey
d3443beaf9 Merge branch 'freqtrade:develop' into reject_report 2022-12-08 18:33:10 +00:00
froggleston
854f056eaf Fix missing Path constructors 2022-12-05 16:16:36 +00:00
froggleston
5a4e99b413 Add support for collating and analysing rejected trades in backtest 2022-12-05 15:34:31 +00:00
255 changed files with 12640 additions and 5421 deletions

View File

@@ -1,11 +1,12 @@
FROM freqtradeorg/freqtrade:develop
FROM freqtradeorg/freqtrade:develop_freqairl
USER root
# Install dependencies
COPY requirements-dev.txt /freqtrade/
RUN apt-get update \
&& apt-get -y install git mercurial sudo vim build-essential \
&& apt-get -y install --no-install-recommends apt-utils dialog \
&& apt-get -y install --no-install-recommends git sudo vim build-essential \
&& apt-get clean \
&& mkdir -p /home/ftuser/.vscode-server /home/ftuser/.vscode-server-insiders /home/ftuser/commandhistory \
&& echo "export PROMPT_COMMAND='history -a'" >> /home/ftuser/.bashrc \

View File

@@ -19,23 +19,24 @@
"postCreateCommand": "freqtrade create-userdir --userdir user_data/",
"workspaceFolder": "/workspaces/freqtrade",
"settings": {
"terminal.integrated.shell.linux": "/bin/bash",
"editor.insertSpaces": true,
"files.trimTrailingWhitespace": true,
"[markdown]": {
"files.trimTrailingWhitespace": false,
"customizations": {
"settings": {
"terminal.integrated.shell.linux": "/bin/bash",
"editor.insertSpaces": true,
"files.trimTrailingWhitespace": true,
"[markdown]": {
"files.trimTrailingWhitespace": false,
},
"python.pythonPath": "/usr/local/bin/python",
},
"python.pythonPath": "/usr/local/bin/python",
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"davidanson.vscode-markdownlint",
"ms-azuretools.vscode-docker",
"vscode-icons-team.vscode-icons",
],
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"davidanson.vscode-markdownlint",
"ms-azuretools.vscode-docker",
"vscode-icons-team.vscode-icons",
],
}
}

View File

@@ -14,7 +14,7 @@ on:
- cron: '0 5 * * 4'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
group: "${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}"
cancel-in-progress: true
permissions:
repository-projects: read
@@ -77,6 +77,17 @@ jobs:
# Allow failure for coveralls
coveralls || true
- name: Check for repository changes
run: |
if [ -n "$(git status --porcelain)" ]; then
echo "Repository is dirty, changes detected:"
git status
git diff
exit 1
else
echo "Repository is clean, no changes detected."
fi
- name: Backtesting (multi)
run: |
cp config_examples/config_bittrex.example.json config.json
@@ -125,6 +136,7 @@ jobs:
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
check-latest: true
- name: Cache_dependencies
uses: actions/cache@v3
@@ -148,7 +160,8 @@ jobs:
- name: Installation - macOS
if: runner.os == 'macOS'
run: |
brew update
# brew update
# TODO: Should be the brew upgrade
# homebrew fails to update python due to unlinking failures
# https://github.com/actions/runner-images/issues/6817
rm /usr/local/bin/2to3 || true
@@ -174,6 +187,17 @@ jobs:
run: |
pytest --random-order
- name: Check for repository changes
run: |
if [ -n "$(git status --porcelain)" ]; then
echo "Repository is dirty, changes detected:"
git status
git diff
exit 1
else
echo "Repository is clean, no changes detected."
fi
- name: Backtesting
run: |
cp config_examples/config_bittrex.example.json config.json
@@ -237,6 +261,18 @@ jobs:
run: |
pytest --random-order
- name: Check for repository changes
run: |
if (git status --porcelain) {
Write-Host "Repository is dirty, changes detected:"
git status
git diff
exit 1
}
else {
Write-Host "Repository is clean, no changes detected."
}
- name: Backtesting
run: |
cp config_examples/config_bittrex.example.json config.json
@@ -302,7 +338,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.10"
python-version: "3.11"
- name: Documentation build
run: |
@@ -425,7 +461,7 @@ jobs:
python setup.py sdist bdist_wheel
- name: Publish to PyPI (Test)
uses: pypa/gh-action-pypi-publish@v1.8.3
uses: pypa/gh-action-pypi-publish@v1.8.7
if: (github.event_name == 'release')
with:
user: __token__
@@ -433,7 +469,7 @@ jobs:
repository_url: https://test.pypi.org/legacy/
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@v1.8.3
uses: pypa/gh-action-pypi-publish@v1.8.7
if: (github.event_name == 'release')
with:
user: __token__

View File

@@ -8,17 +8,17 @@ repos:
# stages: [push]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: "v1.0.1"
rev: "v1.3.0"
hooks:
- id: mypy
exclude: build_helpers
additional_dependencies:
- types-cachetools==5.3.0.4
- types-cachetools==5.3.0.5
- types-filelock==3.2.7
- types-requests==2.28.11.16
- types-tabulate==0.9.0.1
- types-python-dateutil==2.8.19.10
- SQLAlchemy==2.0.7
- types-requests==2.31.0.1
- types-tabulate==0.9.0.2
- types-python-dateutil==2.8.19.13
- SQLAlchemy==2.0.17
# stages: [push]
- repo: https://github.com/pycqa/isort
@@ -30,7 +30,7 @@ repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
# Ruff version.
rev: 'v0.0.255'
rev: 'v0.0.270'
hooks:
- id: ruff

View File

@@ -1,4 +1,4 @@
FROM python:3.10.10-slim-bullseye as base
FROM python:3.11.4-slim-bullseye as base
# Setup env
ENV LANG C.UTF-8
@@ -25,7 +25,7 @@ FROM base as python-deps
RUN apt-get update \
&& apt-get -y install build-essential libssl-dev git libffi-dev libgfortran5 pkg-config cmake gcc \
&& apt-get clean \
&& pip install --upgrade pip
&& pip install --upgrade pip wheel
# Install TA-lib
COPY build_helpers/* /tmp/

View File

@@ -210,6 +210,6 @@ To run this bot we recommend you a cloud instance with a minimum of:
- [Python >= 3.8](http://docs.python-guide.org/en/latest/starting/installation/)
- [pip](https://pip.pypa.io/en/stable/installing/)
- [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
- [TA-Lib](https://mrjbq7.github.io/ta-lib/install.html)
- [TA-Lib](https://ta-lib.github.io/ta-lib-python/)
- [virtualenv](https://virtualenv.pypa.io/en/stable/installation.html) (Recommended)
- [Docker](https://www.docker.com/products/docker) (Recommended)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -6,16 +6,16 @@ python -m pip install --upgrade pip wheel
$pyv = python -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"
if ($pyv -eq '3.8') {
pip install build_helpers\TA_Lib-0.4.25-cp38-cp38-win_amd64.whl
pip install build_helpers\TA_Lib-0.4.26-cp38-cp38-win_amd64.whl
}
if ($pyv -eq '3.9') {
pip install build_helpers\TA_Lib-0.4.25-cp39-cp39-win_amd64.whl
pip install build_helpers\TA_Lib-0.4.26-cp39-cp39-win_amd64.whl
}
if ($pyv -eq '3.10') {
pip install build_helpers\TA_Lib-0.4.25-cp310-cp310-win_amd64.whl
pip install build_helpers\TA_Lib-0.4.26-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 build_helpers\TA_Lib-0.4.26-cp311-cp311-win_amd64.whl
}
pip install -r requirements-dev.txt
pip install -e .

View File

@@ -12,6 +12,7 @@ TAG=$(echo "${BRANCH_NAME}" | sed -e "s/\//_/g")
TAG_PLOT=${TAG}_plot
TAG_FREQAI=${TAG}_freqai
TAG_FREQAI_RL=${TAG_FREQAI}rl
TAG_FREQAI_TORCH=${TAG_FREQAI}torch
TAG_PI="${TAG}_pi"
TAG_ARM=${TAG}_arm
@@ -42,9 +43,9 @@ if [ $? -ne 0 ]; then
return 1
fi
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 build --build-arg sourceimage=freqtrade --build-arg sourcetag=${TAG_ARM} -t freqtrade:${TAG_PLOT_ARM} -f docker/Dockerfile.plot .
docker build --build-arg sourceimage=freqtrade --build-arg sourcetag=${TAG_ARM} -t freqtrade:${TAG_FREQAI_ARM} -f docker/Dockerfile.freqai .
docker build --build-arg sourceimage=freqtrade --build-arg sourcetag=${TAG_FREQAI_ARM} -t freqtrade:${TAG_FREQAI_RL_ARM} -f docker/Dockerfile.freqai_rl .
# Tag image for upload and next build step
docker tag freqtrade:$TAG_ARM ${CACHE_IMAGE}:$TAG_ARM
@@ -84,6 +85,10 @@ 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}
# Create special Torch tag - which is identical to the RL tag.
docker manifest create ${IMAGE_NAME}:${TAG_FREQAI_TORCH} ${CACHE_IMAGE}:${TAG_FREQAI_RL} ${CACHE_IMAGE}:${TAG_FREQAI_RL_ARM}
docker manifest push -p ${IMAGE_NAME}:${TAG_FREQAI_TORCH}
# copy images to ghcr.io
alias crane="docker run --rm -i -v $(pwd)/.crane:/home/nonroot/.docker/ gcr.io/go-containerregistry/crane"
@@ -93,6 +98,7 @@ chmod a+rwx .crane
echo "${GHCR_TOKEN}" | crane auth login ghcr.io -u "${GHCR_USERNAME}" --password-stdin
crane copy ${IMAGE_NAME}:${TAG_FREQAI_RL} ${GHCR_IMAGE_NAME}:${TAG_FREQAI_RL}
crane copy ${IMAGE_NAME}:${TAG_FREQAI_RL} ${GHCR_IMAGE_NAME}:${TAG_FREQAI_TORCH}
crane copy ${IMAGE_NAME}:${TAG_FREQAI} ${GHCR_IMAGE_NAME}:${TAG_FREQAI}
crane copy ${IMAGE_NAME}:${TAG_PLOT} ${GHCR_IMAGE_NAME}:${TAG_PLOT}
crane copy ${IMAGE_NAME}:${TAG} ${GHCR_IMAGE_NAME}:${TAG}

View File

@@ -58,9 +58,9 @@ fi
# Tag image for upload and next build step
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 build --build-arg sourceimage=freqtrade --build-arg sourcetag=${TAG} -t freqtrade:${TAG_PLOT} -f docker/Dockerfile.plot .
docker build --build-arg sourceimage=freqtrade --build-arg sourcetag=${TAG} -t freqtrade:${TAG_FREQAI} -f docker/Dockerfile.freqai .
docker build --build-arg sourceimage=freqtrade --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

View File

@@ -6,6 +6,15 @@ services:
# image: freqtradeorg/freqtrade:develop
# Use plotting image
# image: freqtradeorg/freqtrade:develop_plot
# # Enable GPU Image and GPU Resources (only relevant for freqAI)
# # Make sure to uncomment the whole deploy section
# deploy:
# resources:
# reservations:
# devices:
# - driver: nvidia
# count: 1
# capabilities: [gpu]
# Build step - only needed when additional dependencies are needed
# build:
# context: .
@@ -16,7 +25,7 @@ services:
- "./user_data:/freqtrade/user_data"
# Expose api on port 8080 (localhost only)
# Please read the https://www.freqtrade.io/en/stable/rest-api/ documentation
# before enabling this.
# for more information.
ports:
- "127.0.0.1:8080:8080"
# Default command used when running `docker compose up`

View File

@@ -0,0 +1,36 @@
---
version: '3'
services:
freqtrade:
image: freqtradeorg/freqtrade:stable_freqaitorch
# # Enable GPU Image and GPU Resources
# # Make sure to uncomment the whole deploy section
# deploy:
# resources:
# reservations:
# devices:
# - driver: nvidia
# count: 1
# capabilities: [gpu]
# Build step - only needed when additional dependencies are needed
# build:
# context: .
# dockerfile: "./docker/Dockerfile.custom"
restart: unless-stopped
container_name: freqtrade
volumes:
- "./user_data:/freqtrade/user_data"
# Expose api on port 8080 (localhost only)
# Please read the https://www.freqtrade.io/en/stable/rest-api/ documentation
# for more information.
ports:
- "127.0.0.1:8080:8080"
# Default command used when running `docker compose up`
command: >
trade
--logfile /freqtrade/user_data/logs/freqtrade.log
--db-url sqlite:////freqtrade/user_data/tradesv3.sqlite
--config /freqtrade/user_data/config.json
--freqai-model XGBoostClassifier
--strategy SampleStrategy

View File

@@ -29,7 +29,7 @@ If all goes well, you should now see a `backtest-result-{timestamp}_signals.pkl`
`user_data/backtest_results` folder.
To analyze the entry/exit tags, we now need to use the `freqtrade backtesting-analysis` command
with `--analysis-groups` option provided with space-separated arguments (default `0 1 2`):
with `--analysis-groups` option provided with space-separated arguments:
``` bash
freqtrade backtesting-analysis -c <config.json> --analysis-groups 0 1 2 3 4 5
@@ -39,6 +39,7 @@ This command will read from the last backtesting results. The `--analysis-groups
used to specify the various tabular outputs showing the profit fo each group or trade,
ranging from the simplest (0) to the most detailed per pair, per buy and per sell tag (4):
* 0: overall winrate and profit summary by enter_tag
* 1: profit summaries grouped by enter_tag
* 2: profit summaries grouped by enter_tag and exit_tag
* 3: profit summaries grouped by pair and enter_tag
@@ -115,3 +116,38 @@ For example, if your backtest timerange was `20220101-20221231` but you only wan
```bash
freqtrade backtesting-analysis -c <config.json> --timerange 20220101-20220201
```
### Printing out rejected signals
Use the `--rejected-signals` option to print out rejected signals.
```bash
freqtrade backtesting-analysis -c <config.json> --rejected-signals
```
### Writing tables to CSV
Some of the tabular outputs can become large, so printing them out to the terminal is not preferable.
Use the `--analysis-to-csv` option to disable printing out of tables to standard out and write them to CSV files.
```bash
freqtrade backtesting-analysis -c <config.json> --analysis-to-csv
```
By default this will write one file per output table you specified in the `backtesting-analysis` command, e.g.
```bash
freqtrade backtesting-analysis -c <config.json> --analysis-to-csv --rejected-signals --analysis-groups 0 1
```
This will write to `user_data/backtest_results`:
* rejected_signals.csv
* group_0.csv
* group_1.csv
To override where the files will be written, also specify the `--analysis-csv-path` option.
```bash
freqtrade backtesting-analysis -c <config.json> --analysis-to-csv --analysis-csv-path another/data/path/
```

View File

@@ -136,7 +136,7 @@ class MyAwesomeStrategy(IStrategy):
### Dynamic parameters
Parameters can also be defined dynamically, but must be available to the instance once the * [`bot_start()` callback](strategy-callbacks.md#bot-start) has been called.
Parameters can also be defined dynamically, but must be available to the instance once the [`bot_start()` callback](strategy-callbacks.md#bot-start) has been called.
``` python

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -274,19 +274,20 @@ A backtesting result will look like that:
| XRP/BTC | 35 | 0.66 | 22.96 | 0.00114897 | 11.48 | 3:49:00 | 12 0 23 34.3 |
| ZEC/BTC | 22 | -0.46 | -10.18 | -0.00050971 | -5.09 | 2:22:00 | 7 0 15 31.8 |
| TOTAL | 429 | 0.36 | 152.41 | 0.00762792 | 76.20 | 4:12:00 | 186 0 243 43.4 |
========================================================= EXIT REASON STATS ==========================================================
| Exit Reason | Exits | Wins | Draws | Losses |
|:-------------------|--------:|------:|-------:|--------:|
| trailing_stop_loss | 205 | 150 | 0 | 55 |
| stop_loss | 166 | 0 | 0 | 166 |
| exit_signal | 56 | 36 | 0 | 20 |
| force_exit | 2 | 0 | 0 | 2 |
====================================================== LEFT OPEN TRADES REPORT ======================================================
| Pair | Entries | Avg Profit % | Cum Profit % | Tot Profit BTC | Tot Profit % | Avg Duration | Win Draw Loss Win% |
|:---------|---------:|---------------:|---------------:|-----------------:|---------------:|:---------------|--------------------:|
| ADA/BTC | 1 | 0.89 | 0.89 | 0.00004434 | 0.44 | 6:00:00 | 1 0 0 100 |
| LTC/BTC | 1 | 0.68 | 0.68 | 0.00003421 | 0.34 | 2:00:00 | 1 0 0 100 |
| TOTAL | 2 | 0.78 | 1.57 | 0.00007855 | 0.78 | 4:00:00 | 2 0 0 100 |
==================== EXIT REASON STATS ====================
| Exit Reason | Exits | Wins | Draws | Losses |
|:-------------------|--------:|------:|-------:|--------:|
| trailing_stop_loss | 205 | 150 | 0 | 55 |
| stop_loss | 166 | 0 | 0 | 166 |
| exit_signal | 56 | 36 | 0 | 20 |
| force_exit | 2 | 0 | 0 | 2 |
================== SUMMARY METRICS ==================
| Metric | Value |
|-----------------------------+---------------------|

View File

@@ -138,7 +138,7 @@ Mandatory parameters are marked as **Required**, which means that they are requi
| `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`.
| `available_capital` | Available starting capital for the bot. Useful when running multiple bots on the same exchange account.[More information below](#configuring-amount-per-trade). <br> **Datatype:** Positive float.
| `available_capital` | Available starting capital for the bot. Useful when running multiple bots on the same exchange account. [More information below](#configuring-amount-per-trade). <br> **Datatype:** Positive float.
| `amend_last_stake_amount` | Use reduced last stake amount if necessary. [More information below](#configuring-amount-per-trade). <br>*Defaults to `false`.* <br> **Datatype:** Boolean
| `last_stake_amount_min_ratio` | Defines minimum stake amount that has to be left and executed. Applies only to the last stake amount when it's amended to a reduced value (i.e. if `amend_last_stake_amount` is set to `true`). [More information below](#configuring-amount-per-trade). <br>*Defaults to `0.5`.* <br> **Datatype:** Float (as ratio)
| `amount_reserve_percent` | Reserve some amount in min pair stake amount. The bot will reserve `amount_reserve_percent` + stoploss value when calculating min pair stake amount in order to avoid possible trade refusals. <br>*Defaults to `0.05` (5%).* <br> **Datatype:** Positive Float as ratio.
@@ -155,25 +155,25 @@ Mandatory parameters are marked as **Required**, which means that they are requi
| `trailing_stop_positive_offset` | Offset on when to apply `trailing_stop_positive`. Percentage value which should be positive. More details in the [stoploss documentation](stoploss.md#trailing-stop-loss-only-once-the-trade-has-reached-a-certain-offset). [Strategy Override](#parameters-in-the-strategy). <br>*Defaults to `0.0` (no offset).* <br> **Datatype:** Float
| `trailing_only_offset_is_reached` | Only apply trailing stoploss when the offset is reached. [stoploss documentation](stoploss.md). [Strategy Override](#parameters-in-the-strategy). <br>*Defaults to `false`.* <br> **Datatype:** Boolean
| `fee` | Fee used during backtesting / dry-runs. Should normally not be configured, which has freqtrade fall back to the exchange default fee. Set as ratio (e.g. 0.001 = 0.1%). Fee is applied twice for each trade, once when buying, once when selling. <br> **Datatype:** Float (as ratio)
| `futures_funding_rate` | User-specified funding rate to be used when historical funding rates are not available from the exchange. This does not overwrite real historical rates. It is recommended that this be set to 0 unless you are testing a specific coin and you understand how the funding rate will affect freqtrade's profit calculations. [More information here](leverage.md#unavailable-funding-rates) <br>*Defaults to None.*<br> **Datatype:** Float
| `futures_funding_rate` | User-specified funding rate to be used when historical funding rates are not available from the exchange. This does not overwrite real historical rates. It is recommended that this be set to 0 unless you are testing a specific coin and you understand how the funding rate will affect freqtrade's profit calculations. [More information here](leverage.md#unavailable-funding-rates) <br>*Defaults to `None`.*<br> **Datatype:** Float
| `trading_mode` | Specifies if you want to trade regularly, trade with leverage, or trade contracts whose prices are derived from matching cryptocurrency prices. [leverage documentation](leverage.md). <br>*Defaults to `"spot"`.* <br> **Datatype:** String
| `margin_mode` | When trading with leverage, this determines if the collateral owned by the trader will be shared or isolated to each trading pair [leverage documentation](leverage.md). <br> **Datatype:** String
| `liquidation_buffer` | A ratio specifying how large of a safety net to place between the liquidation price and the stoploss to prevent a position from reaching the liquidation price [leverage documentation](leverage.md). <br>*Defaults to `0.05`.* <br> **Datatype:** Float
| | **Unfilled timeout**
| `unfilledtimeout.entry` | **Required.** How long (in minutes or seconds) the bot will wait for an unfilled entry order to complete, after which the order will be cancelled and repeated at current (new) price, as long as there is a signal. [Strategy Override](#parameters-in-the-strategy).<br> **Datatype:** Integer
| `unfilledtimeout.exit` | **Required.** How long (in minutes or seconds) the bot will wait for an unfilled exit order to complete, after which the order will be cancelled and repeated at current (new) price, as long as there is a signal. [Strategy Override](#parameters-in-the-strategy).<br> **Datatype:** Integer
| `unfilledtimeout.unit` | Unit to use in unfilledtimeout setting. Note: If you set unfilledtimeout.unit to "seconds", "internals.process_throttle_secs" must be inferior or equal to timeout [Strategy Override](#parameters-in-the-strategy). <br> *Defaults to `minutes`.* <br> **Datatype:** String
| `unfilledtimeout.unit` | Unit to use in unfilledtimeout setting. Note: If you set unfilledtimeout.unit to "seconds", "internals.process_throttle_secs" must be inferior or equal to timeout [Strategy Override](#parameters-in-the-strategy). <br> *Defaults to `"minutes"`.* <br> **Datatype:** String
| `unfilledtimeout.exit_timeout_count` | How many times can exit orders time out. Once this number of timeouts is reached, an emergency exit is triggered. 0 to disable and allow unlimited order cancels. [Strategy Override](#parameters-in-the-strategy).<br>*Defaults to `0`.* <br> **Datatype:** Integer
| | **Pricing**
| `entry_pricing.price_side` | Select the side of the spread the bot should look at to get the entry rate. [More information below](#buy-price-side).<br> *Defaults to `same`.* <br> **Datatype:** String (either `ask`, `bid`, `same` or `other`).
| `entry_pricing.price_side` | Select the side of the spread the bot should look at to get the entry rate. [More information below](#entry-price).<br> *Defaults to `"same"`.* <br> **Datatype:** String (either `ask`, `bid`, `same` or `other`).
| `entry_pricing.price_last_balance` | **Required.** Interpolate the bidding price. More information [below](#entry-price-without-orderbook-enabled).
| `entry_pricing.use_order_book` | Enable entering using the rates in [Order Book Entry](#entry-price-with-orderbook-enabled). <br> *Defaults to `True`.*<br> **Datatype:** Boolean
| `entry_pricing.use_order_book` | Enable entering using the rates in [Order Book Entry](#entry-price-with-orderbook-enabled). <br> *Defaults to `true`.*<br> **Datatype:** Boolean
| `entry_pricing.order_book_top` | Bot will use the top N rate in Order Book "price_side" to enter a trade. I.e. a value of 2 will allow the bot to pick the 2nd entry in [Order Book Entry](#entry-price-with-orderbook-enabled). <br>*Defaults to `1`.* <br> **Datatype:** Positive Integer
| `entry_pricing. check_depth_of_market.enabled` | Do not enter if the difference of buy orders and sell orders is met in Order Book. [Check market depth](#check-depth-of-market). <br>*Defaults to `false`.* <br> **Datatype:** Boolean
| `entry_pricing. check_depth_of_market.bids_to_ask_delta` | The difference ratio of buy orders and sell orders found in Order Book. A value below 1 means sell order size is greater, while value greater than 1 means buy order size is higher. [Check market depth](#check-depth-of-market) <br> *Defaults to `0`.* <br> **Datatype:** Float (as ratio)
| `exit_pricing.price_side` | Select the side of the spread the bot should look at to get the exit rate. [More information below](#exit-price-side).<br> *Defaults to `same`.* <br> **Datatype:** String (either `ask`, `bid`, `same` or `other`).
| `exit_pricing.price_side` | Select the side of the spread the bot should look at to get the exit rate. [More information below](#exit-price-side).<br> *Defaults to `"same"`.* <br> **Datatype:** String (either `ask`, `bid`, `same` or `other`).
| `exit_pricing.price_last_balance` | Interpolate the exiting price. More information [below](#exit-price-without-orderbook-enabled).
| `exit_pricing.use_order_book` | Enable exiting of open trades using [Order Book Exit](#exit-price-with-orderbook-enabled). <br> *Defaults to `True`.*<br> **Datatype:** Boolean
| `exit_pricing.use_order_book` | Enable exiting of open trades using [Order Book Exit](#exit-price-with-orderbook-enabled). <br> *Defaults to `true`.*<br> **Datatype:** Boolean
| `exit_pricing.order_book_top` | Bot will use the top N rate in Order Book "price_side" to exit. I.e. a value of 2 will allow the bot to pick the 2nd ask rate in [Order Book Exit](#exit-price-with-orderbook-enabled)<br>*Defaults to `1`.* <br> **Datatype:** Positive Integer
| `custom_price_max_distance_ratio` | Configure maximum distance ratio between current and custom entry or exit price. <br>*Defaults to `0.02` 2%).*<br> **Datatype:** Positive float
| | **TODO**
@@ -199,10 +199,10 @@ Mandatory parameters are marked as **Required**, which means that they are requi
| `exchange.ccxt_sync_config` | Additional CCXT parameters passed to the regular (sync) ccxt instance. Parameters may differ from exchange to exchange and are documented in the [ccxt documentation](https://ccxt.readthedocs.io/en/latest/manual.html#instantiation) <br> **Datatype:** Dict
| `exchange.ccxt_async_config` | Additional CCXT parameters passed to the async ccxt instance. Parameters may differ from exchange to exchange and are documented in the [ccxt documentation](https://ccxt.readthedocs.io/en/latest/manual.html#instantiation) <br> **Datatype:** Dict
| `exchange.markets_refresh_interval` | The interval in minutes in which markets are reloaded. <br>*Defaults to `60` minutes.* <br> **Datatype:** Positive Integer
| `exchange.skip_pair_validation` | Skip pairlist validation on startup.<br>*Defaults to `false`<br> **Datatype:** Boolean
| `exchange.skip_open_order_update` | Skips open order updates on startup should the exchange cause problems. Only relevant in live conditions.<br>*Defaults to `false`<br> **Datatype:** Boolean
| `exchange.skip_pair_validation` | Skip pairlist validation on startup.<br>*Defaults to `false`*<br> **Datatype:** Boolean
| `exchange.skip_open_order_update` | Skips open order updates on startup should the exchange cause problems. Only relevant in live conditions.<br>*Defaults to `false`*<br> **Datatype:** Boolean
| `exchange.unknown_fee_rate` | Fallback value to use when calculating trading fees. This can be useful for exchanges which have fees in non-tradable currencies. The value provided here will be multiplied with the "fee cost".<br>*Defaults to `None`<br> **Datatype:** float
| `exchange.log_responses` | Log relevant exchange responses. For debug mode only - use with care.<br>*Defaults to `false`<br> **Datatype:** Boolean
| `exchange.log_responses` | Log relevant exchange responses. For debug mode only - use with care.<br>*Defaults to `false`*<br> **Datatype:** Boolean
| `experimental.block_bad_exchanges` | Block exchanges known to not work with freqtrade. Leave on default unless you want to test if that exchange works now. <br>*Defaults to `true`.* <br> **Datatype:** Boolean
| | **Plugins**
| `edge.*` | Please refer to [edge configuration document](edge.md) for detailed explanation of all possible configuration options.
@@ -213,7 +213,7 @@ Mandatory parameters are marked as **Required**, which means that they are requi
| `telegram.token` | Your Telegram bot token. Only required if `telegram.enabled` is `true`. <br>**Keep it in secret, do not disclose publicly.** <br> **Datatype:** String
| `telegram.chat_id` | Your personal Telegram account id. Only required if `telegram.enabled` is `true`. <br>**Keep it in secret, do not disclose publicly.** <br> **Datatype:** String
| `telegram.balance_dust_level` | Dust-level (in stake currency) - currencies with a balance below this will not be shown by `/balance`. <br> **Datatype:** float
| `telegram.reload` | Allow "reload" buttons on telegram messages. <br>*Defaults to `True`.<br> **Datatype:** boolean
| `telegram.reload` | Allow "reload" buttons on telegram messages. <br>*Defaults to `true`.<br> **Datatype:** boolean
| `telegram.notification_settings.*` | Detailed notification settings. Refer to the [telegram documentation](telegram-usage.md) for details.<br> **Datatype:** dictionary
| `telegram.allow_custom_messages` | Enable the sending of Telegram messages from strategies via the dataprovider.send_msg() function. <br> **Datatype:** Boolean
| | **Webhook**

View File

@@ -6,7 +6,7 @@ To download data (candles / OHLCV) needed for backtesting and hyperoptimization
If no additional parameter is specified, freqtrade will download data for `"1m"` and `"5m"` timeframes for the last 30 days.
Exchange and pairs will come from `config.json` (if specified using `-c/--config`).
Otherwise `--exchange` becomes mandatory.
Without provided configuration, `--exchange` becomes mandatory.
You can use a relative timerange (`--days 20`) or an absolute starting point (`--timerange 20200101-`). For incremental downloads, the relative approach should be used.
@@ -83,40 +83,47 @@ Common arguments:
```
!!! Tip "Downloading all data for one quote currency"
Often, you'll want to download data for all pairs of a specific quote-currency. In such cases, you can use the following shorthand:
`freqtrade download-data --exchange binance --pairs .*/USDT <...>`. The provided "pairs" string will be expanded to contain all active pairs on the exchange.
To also download data for inactive (delisted) pairs, add `--include-inactive-pairs` to the command.
!!! Note "Startup period"
`download-data` is a strategy-independent command. The idea is to download a big chunk of data once, and then iteratively increase the amount of data stored.
For that reason, `download-data` does not care about the "startup-period" defined in a strategy. It's up to the user to download additional days if the backtest should start at a specific point in time (while respecting startup period).
### Pairs file
### Start download
In alternative to the whitelist from `config.json`, a `pairs.json` file can be used.
If you are using Binance for example:
- create a directory `user_data/data/binance` and copy or create the `pairs.json` file in that directory.
- update the `pairs.json` file to contain the currency pairs you are interested in.
A very simple command (assuming an available `config.json` file) can look as follows.
```bash
mkdir -p user_data/data/binance
touch user_data/data/binance/pairs.json
freqtrade download-data --exchange binance
```
The format of the `pairs.json` file is a simple json list.
Mixing different stake-currencies is allowed for this file, since it's only used for downloading.
This will download historical candle (OHLCV) data for all the currency pairs defined in the configuration.
``` json
[
"ETH/BTC",
"ETH/USDT",
"BTC/USDT",
"XRP/ETH"
]
Alternatively, specify the pairs directly
```bash
freqtrade download-data --exchange binance --pairs ETH/USDT XRP/USDT BTC/USDT
```
!!! Tip "Downloading all data for one quote currency"
Often, you'll want to download data for all pairs of a specific quote-currency. In such cases, you can use the following shorthand:
`freqtrade download-data --exchange binance --pairs .*/USDT <...>`. The provided "pairs" string will be expanded to contain all active pairs on the exchange.
To also download data for inactive (delisted) pairs, add `--include-inactive-pairs` to the command.
or as regex (in this case, to download all active USDT pairs)
```bash
freqtrade download-data --exchange binance --pairs .*/USDT
```
### Other Notes
* To use a different directory than the exchange specific default, use `--datadir user_data/data/some_directory`.
* To change the exchange used to download the historical data from, please use a different configuration file (you'll probably need to adjust rate limits etc.)
* To use `pairs.json` from some other directory, use `--pairs-file some_other_dir/pairs.json`.
* To download historical candle (OHLCV) data for only 10 days, use `--days 10` (defaults to 30 days).
* To download historical candle (OHLCV) data from a fixed starting point, use `--timerange 20200101-` - which will download all data from January 1st, 2020.
* Use `--timeframes` to specify what timeframe download the historical candle (OHLCV) data for. Default is `--timeframes 1m 5m` which will download 1-minute and 5-minute data.
* To use exchange, timeframe and list of pairs as defined in your configuration file, use the `-c/--config` option. With this, the script uses the whitelist defined in the config as the list of currency pairs to download data for and does not require the pairs.json file. You can combine `-c/--config` with most other options.
??? Note "Permission denied errors"
If your configuration directory `user_data` was made by docker, you may get the following error:
@@ -131,39 +138,7 @@ Mixing different stake-currencies is allowed for this file, since it's only used
sudo chown -R $UID:$GID user_data
```
### Start download
Then run:
```bash
freqtrade download-data --exchange binance
```
This will download historical candle (OHLCV) data for all the currency pairs you defined in `pairs.json`.
Alternatively, specify the pairs directly
```bash
freqtrade download-data --exchange binance --pairs ETH/USDT XRP/USDT BTC/USDT
```
or as regex (to download all active USDT pairs)
```bash
freqtrade download-data --exchange binance --pairs .*/USDT
```
### Other Notes
- To use a different directory than the exchange specific default, use `--datadir user_data/data/some_directory`.
- To change the exchange used to download the historical data from, please use a different configuration file (you'll probably need to adjust rate limits etc.)
- To use `pairs.json` from some other directory, use `--pairs-file some_other_dir/pairs.json`.
- To download historical candle (OHLCV) data for only 10 days, use `--days 10` (defaults to 30 days).
- To download historical candle (OHLCV) data from a fixed starting point, use `--timerange 20200101-` - which will download all data from January 1st, 2020.
- Use `--timeframes` to specify what timeframe download the historical candle (OHLCV) data for. Default is `--timeframes 1m 5m` which will download 1-minute and 5-minute data.
- To use exchange, timeframe and list of pairs as defined in your configuration file, use the `-c/--config` option. With this, the script uses the whitelist defined in the config as the list of currency pairs to download data for and does not require the pairs.json file. You can combine `-c/--config` with most other options.
#### Download additional data before the current timerange
### Download additional data before the current timerange
Assuming you downloaded all data from 2022 (`--timerange 20220101-`) - but you'd now like to also backtest with earlier data.
You can do so by using the `--prepend` flag, combined with `--timerange` - specifying an end-date.
@@ -238,7 +213,36 @@ Size has been taken from the BTC/USDT 1m spot combination for the timerange spec
To have a best performance/size mix, we recommend the use of either feather or parquet.
#### Sub-command convert data
### Pairs file
In alternative to the whitelist from `config.json`, a `pairs.json` file can be used.
If you are using Binance for example:
* create a directory `user_data/data/binance` and copy or create the `pairs.json` file in that directory.
* update the `pairs.json` file to contain the currency pairs you are interested in.
```bash
mkdir -p user_data/data/binance
touch user_data/data/binance/pairs.json
```
The format of the `pairs.json` file is a simple json list.
Mixing different stake-currencies is allowed for this file, since it's only used for downloading.
``` json
[
"ETH/BTC",
"ETH/USDT",
"BTC/USDT",
"XRP/ETH"
]
```
!!! Note
The `pairs.json` file is only used when no configuration is loaded (implicitly by naming, or via `--config` flag).
You can force the usage of this file via `--pairs-file pairs.json` - however we recommend to use the pairlist from within the configuration, either via `exchange.pair_whitelist` or `pairs` setting in the configuration.
## Sub-command convert data
```
usage: freqtrade convert-data [-h] [-v] [--logfile FILE] [-V] [-c PATH]
@@ -290,7 +294,7 @@ Common arguments:
```
##### Example converting data
### Example converting data
The following command will convert all candle (OHLCV) data available in `~/.freqtrade/data/binance` from json to jsongz, saving diskspace in the process.
It'll also remove original json data files (`--erase` parameter).
@@ -299,7 +303,7 @@ It'll also remove original json data files (`--erase` parameter).
freqtrade convert-data --format-from json --format-to jsongz --datadir ~/.freqtrade/data/binance -t 5m 15m --erase
```
#### Sub-command convert trade data
## Sub-command convert trade data
```
usage: freqtrade convert-trade-data [-h] [-v] [--logfile FILE] [-V] [-c PATH]
@@ -342,7 +346,7 @@ Common arguments:
```
##### Example converting trades
### Example converting trades
The following command will convert all available trade-data in `~/.freqtrade/data/kraken` from jsongz to json.
It'll also remove original jsongz data files (`--erase` parameter).
@@ -351,7 +355,7 @@ It'll also remove original jsongz data files (`--erase` parameter).
freqtrade convert-trade-data --format-from jsongz --format-to json --datadir ~/.freqtrade/data/kraken --erase
```
### Sub-command trades to ohlcv
## Sub-command trades to ohlcv
When you need to use `--dl-trades` (kraken only) to download data, conversion of trades data to ohlcv data is the last step.
This command will allow you to repeat this last step for additional timeframes without re-downloading the data.
@@ -400,13 +404,13 @@ Common arguments:
```
#### Example trade-to-ohlcv conversion
### Example trade-to-ohlcv conversion
``` bash
freqtrade trades-to-ohlcv --exchange kraken -t 5m 1h 1d --pairs BTC/EUR ETH/EUR
```
### Sub-command list-data
## Sub-command list-data
You can get a list of downloaded data using the `list-data` sub-command.
@@ -451,7 +455,7 @@ Common arguments:
```
#### Example list-data
### Example list-data
```bash
> freqtrade list-data --userdir ~/.freqtrade/user_data/
@@ -465,7 +469,7 @@ ETH/BTC 5m, 15m, 30m, 1h, 2h, 4h, 6h, 12h, 1d
ETH/USDT 5m, 15m, 30m, 1h, 2h, 4h
```
### Trades (tick) data
## Trades (tick) data
By default, `download-data` sub-command downloads Candles (OHLCV) data. Some exchanges also provide historic trade-data via their API.
This data can be useful if you need many different timeframes, since it is only downloaded once, and then resampled locally to the desired timeframes.

View File

@@ -327,18 +327,18 @@ To check how the new exchange behaves, you can use the following snippet:
``` python
import ccxt
from datetime import datetime
from datetime import datetime, timezone
from freqtrade.data.converter import ohlcv_to_dataframe
ct = ccxt.binance()
ct = ccxt.binance() # Use the exchange you're testing
timeframe = "1d"
pair = "XLM/BTC" # Make sure to use a pair that exists on that exchange!
pair = "BTC/USDT" # Make sure to use a pair that exists on that exchange!
raw = ct.fetch_ohlcv(pair, timeframe=timeframe)
# convert to dataframe
df1 = ohlcv_to_dataframe(raw, timeframe, pair=pair, drop_incomplete=False)
print(df1.tail(1))
print(datetime.utcnow())
print(datetime.now(timezone.utc))
```
``` output

View File

@@ -142,6 +142,13 @@ To fix this, redefine order types in the strategy to use "limit" instead of "mar
The same fix should be applied in the configuration file, if order types are defined in your custom config rather than in the strategy.
### I'm trying to start the bot live, but get an API permission error
Errors like `Invalid API-key, IP, or permissions for action` mean exactly what they actually say.
Your API key is either invalid (copy/paste error? check for leading/trailing spaces in the config), expired, or the IP you're running the bot from is not enabled in the Exchange's API console.
Usually, the permission "Spot Trading" (or the equivalent in the exchange you use) will be necessary.
Futures will usually have to be enabled specifically.
### How do I search the bot logs for something?
By default, the bot writes its log into stderr stream. This is implemented this way so that you can easily separate the bot's diagnostics messages from Backtesting, Edge and Hyperopt results, output from other various Freqtrade utility sub-commands, as well as from the output of your custom `print()`'s you may have inserted into your strategy. So if you need to search the log messages with the grep utility, you need to redirect stderr to stdout and disregard stdout.

View File

@@ -43,16 +43,16 @@ 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 `set_freqai_labels()`
# the model will return all labels created by user in `set_freqai_targets()`
# (& 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
# `feature_engineering_*` for each training period.
# `set_freqai_targets()` for each training period.
dataframe = self.freqai.start(dataframe, metadata, self)
return dataframe
def feature_engineering_expand_all(self, dataframe, period, **kwargs):
def feature_engineering_expand_all(self, dataframe: DataFrame, period, **kwargs) -> DataFrame:
"""
*Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined
@@ -77,7 +77,7 @@ The FreqAI strategy requires including the following lines of code in the standa
return dataframe
def feature_engineering_expand_basic(self, dataframe, **kwargs):
def feature_engineering_expand_basic(self, dataframe: DataFrame, **kwargs) -> DataFrame:
"""
*Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined
@@ -101,7 +101,7 @@ The FreqAI strategy requires including the following lines of code in the standa
dataframe["%-raw_price"] = dataframe["close"]
return dataframe
def feature_engineering_standard(self, dataframe, **kwargs):
def feature_engineering_standard(self, dataframe: DataFrame, **kwargs) -> DataFrame:
"""
*Only functional with FreqAI enabled strategies*
This optional function will be called once with the dataframe of the base timeframe.
@@ -122,7 +122,7 @@ The FreqAI strategy requires including the following lines of code in the standa
dataframe["%-hour_of_day"] = (dataframe["date"].dt.hour + 1) / 25
return dataframe
def set_freqai_targets(self, dataframe, **kwargs):
def set_freqai_targets(self, dataframe: DataFrame, **kwargs) -> DataFrame:
"""
*Only functional with FreqAI enabled strategies*
Required function to set the targets for the model.
@@ -139,6 +139,7 @@ The FreqAI strategy requires including the following lines of code in the standa
/ dataframe["close"]
- 1
)
return dataframe
```
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`.
@@ -159,7 +160,7 @@ Below are the values you can expect to include/use inside a typical strategy dat
|------------|-------------|
| `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['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 `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.
@@ -236,3 +237,181 @@ If you want to predict multiple targets you must specify all labels in the same
df['&s-up_or_down'] = np.where( df["close"].shift(-100) > df["close"], 'up', 'down')
df['&s-up_or_down'] = np.where( df["close"].shift(-100) == df["close"], 'same', df['&s-up_or_down'])
```
## PyTorch Module
### Quick start
The easiest way to quickly run a pytorch model is with the following command (for regression task):
```bash
freqtrade trade --config config_examples/config_freqai.example.json --strategy FreqaiExampleStrategy --freqaimodel PyTorchMLPRegressor --strategy-path freqtrade/templates
```
!!! Note "Installation/docker"
The PyTorch module requires 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 or PyTorch (~700mb additional space required) [y/N]?".
Users who prefer docker should ensure they use the docker image appended with `_freqaitorch`.
We do provide an explicit docker-compose file for this in `docker/docker-compose-freqai.yml` - which can be used via `docker compose -f docker/docker-compose-freqai.yml run ...` - or can be copied to replace the original docker file.
This docker-compose file also contains a (disabled) section to enable GPU resources within docker containers. This obviously assumes the system has GPU resources available.
### Structure
#### Model
You can construct your own Neural Network architecture in PyTorch by simply defining your `nn.Module` class inside your custom [`IFreqaiModel` file](#using-different-prediction-models) and then using that class in your `def train()` function. Here is an example of logistic regression model implementation using PyTorch (should be used with nn.BCELoss criterion) for classification tasks.
```python
class LogisticRegression(nn.Module):
def __init__(self, input_size: int):
super().__init__()
# Define your layers
self.linear = nn.Linear(input_size, 1)
self.activation = nn.Sigmoid()
def forward(self, x: torch.Tensor) -> torch.Tensor:
# Define the forward pass
out = self.linear(x)
out = self.activation(out)
return out
class MyCoolPyTorchClassifier(BasePyTorchClassifier):
"""
This is a custom IFreqaiModel showing how a user might setup their own
custom Neural Network architecture for their training.
"""
@property
def data_convertor(self) -> PyTorchDataConvertor:
return DefaultPyTorchDataConvertor(target_tensor_type=torch.float)
def __init__(self, **kwargs) -> None:
super().__init__(**kwargs)
config = self.freqai_info.get("model_training_parameters", {})
self.learning_rate: float = config.get("learning_rate", 3e-4)
self.model_kwargs: Dict[str, Any] = config.get("model_kwargs", {})
self.trainer_kwargs: Dict[str, Any] = config.get("trainer_kwargs", {})
def fit(self, data_dictionary: Dict, dk: FreqaiDataKitchen, **kwargs) -> Any:
"""
User sets up the training and test data to fit their desired model here
:param data_dictionary: the dictionary holding all data for train, test,
labels, weights
:param dk: The datakitchen object for the current coin/model
"""
class_names = self.get_class_names()
self.convert_label_column_to_int(data_dictionary, dk, class_names)
n_features = data_dictionary["train_features"].shape[-1]
model = LogisticRegression(
input_dim=n_features
)
model.to(self.device)
optimizer = torch.optim.AdamW(model.parameters(), lr=self.learning_rate)
criterion = torch.nn.CrossEntropyLoss()
init_model = self.get_init_model(dk.pair)
trainer = PyTorchModelTrainer(
model=model,
optimizer=optimizer,
criterion=criterion,
model_meta_data={"class_names": class_names},
device=self.device,
init_model=init_model,
data_convertor=self.data_convertor,
**self.trainer_kwargs,
)
trainer.fit(data_dictionary, self.splits)
return trainer
```
#### Trainer
The `PyTorchModelTrainer` performs the idiomatic PyTorch train loop:
Define our model, loss function, and optimizer, and then move them to the appropriate device (GPU or CPU). Inside the loop, we iterate through the batches in the dataloader, move the data to the device, compute the prediction and loss, backpropagate, and update the model parameters using the optimizer.
In addition, the trainer is responsible for the following:
- saving and loading the model
- converting the data from `pandas.DataFrame` to `torch.Tensor`.
#### Integration with Freqai module
Like all freqai models, PyTorch models inherit `IFreqaiModel`. `IFreqaiModel` declares three abstract methods: `train`, `fit`, and `predict`. we implement these methods in three levels of hierarchy.
From top to bottom:
1. `BasePyTorchModel` - Implements the `train` method. all `BasePyTorch*` inherit it. responsible for general data preparation (e.g., data normalization) and calling the `fit` method. Sets `device` attribute used by children classes. Sets `model_type` attribute used by the parent class.
2. `BasePyTorch*` - Implements the `predict` method. Here, the `*` represents a group of algorithms, such as classifiers or regressors. responsible for data preprocessing, predicting, and postprocessing if needed.
3. `PyTorch*Classifier` / `PyTorch*Regressor` - implements the `fit` method. responsible for the main train flaw, where we initialize the trainer and model objects.
![image](assets/freqai_pytorch-diagram.png)
#### Full example
Building a PyTorch regressor using MLP (multilayer perceptron) model, MSELoss criterion, and AdamW optimizer.
```python
class PyTorchMLPRegressor(BasePyTorchRegressor):
def __init__(self, **kwargs) -> None:
super().__init__(**kwargs)
config = self.freqai_info.get("model_training_parameters", {})
self.learning_rate: float = config.get("learning_rate", 3e-4)
self.model_kwargs: Dict[str, Any] = config.get("model_kwargs", {})
self.trainer_kwargs: Dict[str, Any] = config.get("trainer_kwargs", {})
def fit(self, data_dictionary: Dict, dk: FreqaiDataKitchen, **kwargs) -> Any:
n_features = data_dictionary["train_features"].shape[-1]
model = PyTorchMLPModel(
input_dim=n_features,
output_dim=1,
**self.model_kwargs
)
model.to(self.device)
optimizer = torch.optim.AdamW(model.parameters(), lr=self.learning_rate)
criterion = torch.nn.MSELoss()
init_model = self.get_init_model(dk.pair)
trainer = PyTorchModelTrainer(
model=model,
optimizer=optimizer,
criterion=criterion,
device=self.device,
init_model=init_model,
target_tensor_type=torch.float,
**self.trainer_kwargs,
)
trainer.fit(data_dictionary)
return trainer
```
Here we create a `PyTorchMLPRegressor` class that implements the `fit` method. The `fit` method specifies the training building blocks: model, optimizer, criterion, and trainer. We inherit both `BasePyTorchRegressor` and `BasePyTorchModel`, where the former implements the `predict` method that is suitable for our regression task, and the latter implements the train method.
??? Note "Setting Class Names for Classifiers"
When using classifiers, the user must declare the class names (or targets) by overriding the `IFreqaiModel.class_names` attribute. This is achieved by setting `self.freqai.class_names` in the FreqAI strategy inside the `set_freqai_targets` method.
For example, if you are using a binary classifier to predict price movements as up or down, you can set the class names as follows:
```python
def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs) -> DataFrame:
self.freqai.class_names = ["down", "up"]
dataframe['&s-up_or_down'] = np.where(dataframe["close"].shift(-100) >
dataframe["close"], 'up', 'down')
return dataframe
```
To see a full example, you can refer to the [classifier test strategy class](https://github.com/freqtrade/freqtrade/blob/develop/tests/strategy/strats/freqai_test_classifier.py).
#### Improving performance with `torch.compile()`
Torch provides a `torch.compile()` method that can be used to improve performance for specific GPU hardware. More details can be found [here](https://pytorch.org/tutorials/intermediate/torch_compile_tutorial.html). In brief, you simply wrap your `model` in `torch.compile()`:
```python
model = PyTorchMLPModel(
input_dim=n_features,
output_dim=1,
**self.model_kwargs
)
model.to(self.device)
model = torch.compile(model)
```
Then proceed to use the model as normal. Keep in mind that doing this will remove eager execution, which means errors and tracebacks will not be informative.

View File

@@ -6,8 +6,8 @@ Low level feature engineering is performed in the user strategy within a set of
| 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_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.
@@ -16,7 +16,7 @@ Meanwhile, high level feature engineering is handled within `"feature_parameters
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 feature_engineering_expand_all(self, dataframe, period, metadata, **kwargs):
def feature_engineering_expand_all(self, dataframe: DataFrame, period, metadata, **kwargs) -> DataFrame:
"""
*Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined
@@ -67,7 +67,7 @@ It is advisable to start from the template `feature_engineering_*` functions in
return dataframe
def feature_engineering_expand_basic(self, dataframe, metadata, **kwargs):
def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata, **kwargs) -> DataFrame:
"""
*Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined
@@ -96,7 +96,7 @@ It is advisable to start from the template `feature_engineering_*` functions in
dataframe["%-raw_price"] = dataframe["close"]
return dataframe
def feature_engineering_standard(self, dataframe, metadata, **kwargs):
def feature_engineering_standard(self, dataframe: DataFrame, metadata, **kwargs) -> DataFrame:
"""
*Only functional with FreqAI enabled strategies*
This optional function will be called once with the dataframe of the base timeframe.
@@ -122,7 +122,7 @@ It is advisable to start from the template `feature_engineering_*` functions in
dataframe["%-hour_of_day"] = (dataframe["date"].dt.hour + 1) / 25
return dataframe
def set_freqai_targets(self, dataframe, metadata, **kwargs):
def set_freqai_targets(self, dataframe: DataFrame, metadata, **kwargs) -> DataFrame:
"""
*Only functional with FreqAI enabled strategies*
Required function to set the targets for the model.
@@ -180,16 +180,18 @@ You can ask for each of the defined features to be included also for informative
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$.
!!! note "Learn more about creative feature engineering"
Check out our [medium article](https://emergentmethods.medium.com/freqai-from-price-to-prediction-6fadac18b665) geared toward helping users learn how to creatively engineer features.
### Gain finer control over `feature_engineering_*` functions with `metadata`
### 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.
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)
```python
def feature_engineering_expand_all(self, dataframe: DataFrame, period, metadata, **kwargs) -> DataFrame:
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"`.
@@ -210,41 +212,7 @@ Another example, where the user wants to use live metrics from the trade databas
You need to set the standard dictionary in the config so that FreqAI can return proper dataframe shapes. These values will likely be overridden by the prediction model, but in the case where the model has yet to set them, or needs a default initial value, the pre-set values are what will be returned.
## Feature normalization
FreqAI is strict when it comes to data normalization. The train features, $X^{train}$, are always normalized to [-1, 1] using a shifted min-max normalization:
$$X^{train}_{norm} = 2 * \frac{X^{train} - X^{train}.min()}{X^{train}.max() - X^{train}.min()} - 1$$
All other data (test data and unseen prediction data in dry/live/backtest) is always automatically normalized to the training feature space according to industry standards. FreqAI stores all the metadata required to ensure that test and prediction features will be properly normalized and that predictions are properly denormalized. For this reason, it is not recommended to eschew industry standards and modify FreqAI internals - however - advanced users can do so by inheriting `train()` in their custom `IFreqaiModel` and using their own normalization functions.
## Data dimensionality reduction with Principal Component Analysis
You can reduce the dimensionality of your features by activating the `principal_component_analysis` in the config:
```json
"freqai": {
"feature_parameters" : {
"principal_component_analysis": true
}
}
```
This will perform PCA on the features and reduce their dimensionality so that the explained variance of the data set is >= 0.999. Reducing data dimensionality makes training the model faster and hence allows for more up-to-date models.
## Inlier metric
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.
![inlier-metric](assets/freqai_inlier-metric.jpg)
FreqAI adds the `inlier_metric` to the training features and hence gives the model access to a novel type of temporal information.
This function does **not** remove outliers from the data set.
## Weighting features for temporal importance
### Weighting features for temporal importance
FreqAI allows you to set a `weight_factor` to weight recent data more strongly than past data via an exponential function:
@@ -254,13 +222,103 @@ where $W_i$ is the weight of data point $i$ in a total set of $n$ data points. B
![weight-factor](assets/freqai_weight-factor.jpg)
## Building the data pipeline
By default, FreqAI builds a dynamic pipeline based on user congfiguration settings. The default settings are robust and designed to work with a variety of methods. These two steps are a `MinMaxScaler(-1,1)` and a `VarianceThreshold` which removes any column that has 0 variance. Users can activate other steps with more configuration parameters. For example if users add `use_SVM_to_remove_outliers: true` to the `freqai` config, then FreqAI will automatically add the [`SVMOutlierExtractor`](#identifying-outliers-using-a-support-vector-machine-svm) to the pipeline. Likewise, users can add `principal_component_analysis: true` to the `freqai` config to activate PCA. The [DissimilarityIndex](#identifying-outliers-with-the-dissimilarity-index-di) is activated with `DI_threshold: 1`. Finally, noise can also be added to the data with `noise_standard_deviation: 0.1`. Finally, users can add [DBSCAN](#identifying-outliers-with-dbscan) outlier removal with `use_DBSCAN_to_remove_outliers: true`.
!!! note "More information available"
Please review the [parameter table](freqai-parameter-table.md) for more information on these parameters.
### Customizing the pipeline
Users are encouraged to customize the data pipeline to their needs by building their own data pipeline. This can be done by simply setting `dk.feature_pipeline` to their desired `Pipeline` object inside their `IFreqaiModel` `train()` function, or if they prefer not to touch the `train()` function, they can override `define_data_pipeline`/`define_label_pipeline` functions in their `IFreqaiModel`:
!!! note "More information available"
FreqAI uses the the [`DataSieve`](https://github.com/emergentmethods/datasieve) pipeline, which follows the SKlearn pipeline API, but adds, among other features, coherence between the X, y, and sample_weight vector point removals, feature removal, feature name following.
```python
from datasieve.transforms import SKLearnWrapper, DissimilarityIndex
from datasieve.pipeline import Pipeline
from sklearn.preprocessing import QuantileTransformer, StandardScaler
from freqai.base_models import BaseRegressionModel
class MyFreqaiModel(BaseRegressionModel):
"""
Some cool custom model
"""
def fit(self, data_dictionary: Dict, dk: FreqaiDataKitchen, **kwargs) -> Any:
"""
My custom fit function
"""
model = cool_model.fit()
return model
def define_data_pipeline(self) -> Pipeline:
"""
User defines their custom feature pipeline here (if they wish)
"""
feature_pipeline = Pipeline([
('qt', SKLearnWrapper(QuantileTransformer(output_distribution='normal'))),
('di', ds.DissimilarityIndex(di_threshold=1)
])
return feature_pipeline
def define_label_pipeline(self) -> Pipeline:
"""
User defines their custom label pipeline here (if they wish)
"""
label_pipeline = Pipeline([
('qt', SKLearnWrapper(StandardScaler())),
])
return label_pipeline
```
Here, you are defining the exact pipeline that will be used for your feature set during training and prediction. You can use *most* SKLearn transformation steps by wrapping them in the `SKLearnWrapper` class as shown above. In addition, you can use any of the transformations available in the [`DataSieve` library](https://github.com/emergentmethods/datasieve).
You can easily add your own transformation by creating a class that inherits from the datasieve `BaseTransform` and implementing your `fit()`, `transform()` and `inverse_transform()` methods:
```python
from datasieve.transforms.base_transform import BaseTransform
# import whatever else you need
class MyCoolTransform(BaseTransform):
def __init__(self, **kwargs):
self.param1 = kwargs.get('param1', 1)
def fit(self, X, y=None, sample_weight=None, feature_list=None, **kwargs):
# do something with X, y, sample_weight, or/and feature_list
return X, y, sample_weight, feature_list
def transform(self, X, y=None, sample_weight=None,
feature_list=None, outlier_check=False, **kwargs):
# do something with X, y, sample_weight, or/and feature_list
return X, y, sample_weight, feature_list
def inverse_transform(self, X, y=None, sample_weight=None, feature_list=None, **kwargs):
# do/dont do something with X, y, sample_weight, or/and feature_list
return X, y, sample_weight, feature_list
```
!!! note "Hint"
You can define this custom class in the same file as your `IFreqaiModel`.
### Migrating a custom `IFreqaiModel` to the new Pipeline
If you have created your own custom `IFreqaiModel` with a custom `train()`/`predict()` function, *and* you still rely on `data_cleaning_train/predict()`, then you will need to migrate to the new pipeline. If your model does *not* rely on `data_cleaning_train/predict()`, then you do not need to worry about this migration.
More details about the migration can be found [here](strategy_migration.md#freqai---new-data-pipeline).
## Outlier detection
Equity and crypto markets suffer from a high level of non-patterned noise in the form of outlier data points. FreqAI implements a variety of methods to identify such outliers and hence mitigate risk.
### Identifying outliers with the Dissimilarity Index (DI)
The Dissimilarity Index (DI) aims to quantify the uncertainty associated with each prediction made by the model.
The Dissimilarity Index (DI) aims to quantify the uncertainty associated with each prediction made by the model.
You can tell FreqAI to remove outlier data points from the training/test data sets using the DI by including the following statement in the config:
@@ -272,7 +330,7 @@ You can tell FreqAI to remove outlier data points from the training/test data se
}
```
The DI allows predictions which are outliers (not existent in the model feature space) to be thrown out due to low levels of certainty. To do so, FreqAI measures the distance between each training data point (feature vector), $X_{a}$, and all other training data points:
Which will add `DissimilarityIndex` step to your `feature_pipeline` and set the threshold to 1. The DI allows predictions which are outliers (not existent in the model feature space) to be thrown out due to low levels of certainty. To do so, FreqAI measures the distance between each training data point (feature vector), $X_{a}$, and all other training data points:
$$ d_{ab} = \sqrt{\sum_{j=1}^p(X_{a,j}-X_{b,j})^2} $$
@@ -306,9 +364,9 @@ You can tell FreqAI to remove outlier data points from the training/test data se
}
```
The SVM will be trained on the training data and any data point that the SVM deems to be beyond the feature space will be removed.
Which will add `SVMOutlierExtractor` step to your `feature_pipeline`. The SVM will be trained on the training data and any data point that the SVM deems to be beyond the feature space will be removed.
FreqAI uses `sklearn.linear_model.SGDOneClassSVM` (details are available on scikit-learn's webpage [here](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.SGDOneClassSVM.html) (external website)) and you can elect to provide additional parameters for the SVM, such as `shuffle`, and `nu`.
You can elect to provide additional parameters for the SVM, such as `shuffle`, and `nu` via the `feature_parameters.svm_params` dictionary in the config.
The parameter `shuffle` is by default set to `False` to ensure consistent results. If it is set to `True`, running the SVM multiple times on the same data set might result in different outcomes due to `max_iter` being to low for the algorithm to reach the demanded `tol`. Increasing `max_iter` solves this issue but causes the procedure to take longer time.
@@ -326,7 +384,7 @@ You can configure FreqAI to use DBSCAN to cluster and remove outliers from the t
}
```
DBSCAN is an unsupervised machine learning algorithm that clusters data without needing to know how many clusters there should be.
Which will add the `DataSieveDBSCAN` step to your `feature_pipeline`. This is an unsupervised machine learning algorithm that clusters data without needing to know how many clusters there should be.
Given a number of data points $N$, and a distance $\varepsilon$, DBSCAN clusters the data set by setting all data points that have $N-1$ other data points within a distance of $\varepsilon$ as *core points*. A data point that is within a distance of $\varepsilon$ from a *core point* but that does not have $N-1$ other data points within a distance of $\varepsilon$ from itself is considered an *edge point*. A cluster is then the collection of *core points* and *edge points*. Data points that have no other data points at a distance $<\varepsilon$ are considered outliers. The figure below shows a cluster with $N = 3$.

View File

@@ -18,9 +18,10 @@ Mandatory parameters are marked as **Required** and have to be set in one of the
| `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.
| `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`.
| `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)). Beware that this is currently a naive approach to incremental learning, and it has a high probability of overfitting/getting stuck in local minima while the market moves away from your model. We have the connections here primarily for experimental purposes and so that it is ready for more mature approaches to continual learning in chaotic systems like the crypto market. <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`
| `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.
| `activate_tensorboard` | <br> Indicate whether or not to activate tensorboard for the tensorboard enabled modules (currently Reinforcment Learning, XGBoost, Catboost, and PyTorch). Tensorboard needs Torch installed, which means you will need the torch/RL docker image or you need to answer "yes" to the install question about whether or not you wish to install Torch. <br> **Datatype:** Boolean. <br> Default: `True`.
### Feature parameters
@@ -85,6 +86,28 @@ Mandatory parameters are marked as **Required** and have to be set in one of the
| `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`.
| `drop_ohlc_from_features` | Do not include the normalized ohlc data in the feature set passed to the agent during training (ohlc will still be used for driving the environment in all cases) <br> **Datatype:** Boolean. <br> **Default:** `False`
| `progress_bar` | Display a progress bar with the current progress, elapsed time and estimated remaining time. <br> **Datatype:** Boolean. <br> Default: `False`.
### PyTorch parameters
#### general
| Parameter | Description |
|------------|-------------|
| | **Model training parameters within the `freqai.model_training_parameters` sub dictionary**
| `learning_rate` | Learning rate to be passed to the optimizer. <br> **Datatype:** float. <br> Default: `3e-4`.
| `model_kwargs` | Parameters to be passed to the model class. <br> **Datatype:** dict. <br> Default: `{}`.
| `trainer_kwargs` | Parameters to be passed to the trainer class. <br> **Datatype:** dict. <br> Default: `{}`.
#### trainer_kwargs
| Parameter | Description |
|------------|-------------|
| | **Model training parameters within the `freqai.model_training_parameters.model_kwargs` sub dictionary**
| `max_iters` | The number of training iterations to run. iteration here refers to the number of times we call self.optimizer.step(). used to calculate n_epochs. <br> **Datatype:** int. <br> Default: `100`.
| `batch_size` | The size of the batches to use during training.. <br> **Datatype:** int. <br> Default: `64`.
| `max_n_eval_batches` | The maximum number batches to use for evaluation.. <br> **Datatype:** int, optional. <br> Default: `None`.
### Additional parameters
@@ -92,5 +115,5 @@ Mandatory parameters are marked as **Required** and have to be set in one of the
|------------|-------------|
| | **Extraneous parameters**
| `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.conv_width` | The width of a 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

@@ -37,7 +37,7 @@ freqtrade trade --freqaimodel ReinforcementLearner --strategy MyRLStrategy --con
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):
def set_freqai_targets(self, dataframe, **kwargs) -> DataFrame:
"""
*Only functional with FreqAI enabled strategies*
Required function to set the targets for the model.
@@ -53,17 +53,19 @@ where `ReinforcementLearner` will use the templated `ReinforcementLearner` from
# For RL, there are no direct targets to set. This is filler (neutral)
# until the agent sends an action.
dataframe["&-action"] = 0
return dataframe
```
Most of the function remains the same as for typical Regressors, however, the function below 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):
def feature_engineering_standard(self, dataframe: DataFrame, **kwargs) -> DataFrame:
# 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"]
return dataframe
```
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.
@@ -133,92 +135,104 @@ Parameter details can be found [here](freqai-parameter-table.md), but in general
## 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:
!!! danger "Not for production"
Warning!
The reward function provided with the Freqtrade source code is a showcase of functionality designed to show/test as many possible environment control features as possible. It is also designed to run quickly on small computers. This is a benchmark, it is *not* for live production. Please beware that you will need to create your own custom_reward() function or use a template built by other users outside of the Freqtrade source code.
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 this is *not* designed for production. Users *must* create their own custom reinforcement learning model class or use a pre-built one from outside the Freqtrade source code 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:
!!! note "Hint"
The best reward functions are ones that are continuously differentiable, and well scaled. In other words, adding a single large negative penalty to a rare event is not a good idea, and the neural net will not be able to learn that function. Instead, it is better to add a small negative penalty to a common event. This will help the agent learn faster. Not only this, but you can help improve the continuity of your rewards/penalties by having them scale with severity according to some linear/exponential functions. In other words, you'd slowly scale the penalty as the duration of the trade increases. This is better than a single large penalty occuring at a single point in time.
```python
from freqtrade.freqai.prediction_models.ReinforcementLearner import ReinforcementLearner
from freqtrade.freqai.RL.Base5ActionRLEnv import Actions, Base5ActionRLEnv, Positions
from freqtrade.freqai.prediction_models.ReinforcementLearner import ReinforcementLearner
from freqtrade.freqai.RL.Base5ActionRLEnv import Actions, Base5ActionRLEnv, Positions
class MyCoolRLModel(ReinforcementLearner):
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 created RL prediction model.
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.
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.
Warning!
This is function is a showcase of functionality designed to show as many possible
environment control features as possible. It is also designed to run quickly
on small computers. This is a benchmark, it is *not* for live production.
"""
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()
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
factor = 100
pair = self.pair.replace(':', '')
pair = self.pair.replace(':', '')
# 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_{pair}_"
f"{self.config['timeframe']}"].iloc[self._current_tick]
# 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_{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
# 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.
# 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
## 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:
@@ -231,32 +245,30 @@ where `unique-id` is the `identifier` set in the `freqai` configuration file. Th
![tensorboard](assets/tensorboard.jpg)
### Custom logging
## 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("invalid")
return -2
```python
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("invalid")
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)`. In this case the metric values are not incremented.
### Choosing a base environment
## 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:

View File

@@ -131,6 +131,9 @@ You can choose to adopt a continual learning scheme by setting `"continual_learn
???+ danger "Continual learning enforces a constant parameter space"
Since `continual_learning` means that the model parameter space *cannot* change between trainings, `principal_component_analysis` is automatically disabled when `continual_learning` is enabled. Hint: PCA changes the parameter space and the number of features, learn more about PCA [here](freqai-feature-engineering.md#data-dimensionality-reduction-with-principal-component-analysis).
???+ danger "Experimental functionality"
Beware that this is currently a naive approach to incremental learning, and it has a high probability of overfitting/getting stuck in local minima while the market moves away from your model. We have the mechanics available in FreqAI primarily for experimental purposes and so that it is ready for more mature approaches to continual learning in chaotic systems like the crypto market.
## Hyperopt
You can hyperopt using the same command as for [typical Freqtrade hyperopt](hyperopt.md):
@@ -158,7 +161,14 @@ This specific hyperopt would help you understand the appropriate `DI_values` for
## Using Tensorboard
CatBoost models benefit from tracking training metrics via Tensorboard. You can take advantage of the FreqAI integration to track training and evaluation performance across all coins and across all retrainings. Tensorboard is activated via the following command:
!!! note "Availability"
FreqAI includes tensorboard for a variety of models, including XGBoost, all PyTorch models, Reinforcement Learning, and Catboost. If you would like to see Tensorboard integrated into another model type, please open an issue on the [Freqtrade GitHub](https://github.com/freqtrade/freqtrade/issues)
!!! danger "Requirements"
Tensorboard logging requires the FreqAI torch installation/docker image.
The easiest way to use tensorboard is to ensure `freqai.activate_tensorboard` is set to `True` (default setting) in your configuration file, run FreqAI, then open a separate shell and run:
```bash
cd freqtrade
@@ -168,3 +178,7 @@ 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)
!!! note "Deactivate for improved performance"
Tensorboard logging can slow down training and should be deactivated for production use.

View File

@@ -32,7 +32,10 @@ The easiest way to quickly test FreqAI is to run it in dry mode with the followi
freqtrade trade --config config_examples/config_freqai.example.json --strategy FreqaiExampleStrategy --freqaimodel LightGBMRegressor --strategy-path freqtrade/templates
```
You will see the boot-up process of automatic data downloading, followed by simultaneous training and trading.
You will see the boot-up process of automatic data downloading, followed by simultaneous training and trading.
!!! danger "Not for production"
The example strategy provided with the Freqtrade source code is designed for showcasing/testing a wide variety of FreqAI features. It is also designed to run on small computers so that it can be used as a benchmark between developers and users. It is *not* designed to be run in production.
An example strategy, prediction model, and config to use as a starting points can be found in
`freqtrade/templates/FreqaiExampleStrategy.py`, `freqtrade/freqai/prediction_models/LightGBMRegressor.py`, and
@@ -69,15 +72,14 @@ pip install -r requirements-freqai.txt
```
!!! Note
Catboost will not be installed on arm devices (raspberry, Mac M1, ARM based VPS, ...), since it does not provide wheels for this platform.
!!! Note "python 3.11"
Some dependencies (Catboost, Torch) currently don't support python 3.11. Freqtrade therefore only supports python 3.10 for these models/dependencies.
Tests involving these dependencies are skipped on 3.11.
Catboost will not be installed on low-powered arm devices (raspberry), since it does not provide wheels for this platform.
### 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. If you would like to use PyTorch or Reinforcement learning, you should use the torch or RL tags, `image: freqtradeorg/freqtrade:develop_freqaitorch`, `image: freqtradeorg/freqtrade:develop_freqairl`.
!!! note "docker-compose-freqai.yml"
We do provide an explicit docker-compose file for this in `docker/docker-compose-freqai.yml` - which can be used via `docker compose -f docker/docker-compose-freqai.yml run ...` - or can be copied to replace the original docker file. This docker-compose file also contains a (disabled) section to enable GPU resources within docker containers. This obviously assumes the system has GPU resources available.
### FreqAI position in open-source machine learning landscape
@@ -105,6 +107,13 @@ This is for performance reasons - FreqAI relies on making quick predictions/retr
it needs to download all the training data at the beginning of a dry/live instance. FreqAI stores and appends
new candles automatically for future retrains. This means that if new pairs arrive later in the dry run due to a volume pairlist, it will not have the data ready. However, FreqAI does work with the `ShufflePairlist` or a `VolumePairlist` which keeps the total pairlist constant (but reorders the pairs according to volume).
## Additional learning materials
Here we compile some external materials that provide deeper looks into various components of FreqAI:
- [Real-time head-to-head: Adaptive modeling of financial market data using XGBoost and CatBoost](https://emergentmethods.medium.com/real-time-head-to-head-adaptive-modeling-of-financial-market-data-using-xgboost-and-catboost-995a115a7495)
- [FreqAI - from price to prediction](https://emergentmethods.medium.com/freqai-from-price-to-prediction-6fadac18b665)
## Credits
FreqAI is developed by a group of individuals who all contribute specific skillsets to the project.

View File

@@ -30,12 +30,6 @@ 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
@@ -52,7 +46,7 @@ These requirements apply to both [Script Installation](#script-installation) and
* [pip](https://pip.pypa.io/en/stable/installing/)
* [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
* [virtualenv](https://virtualenv.pypa.io/en/stable/installation.html) (Recommended)
* [TA-Lib](https://mrjbq7.github.io/ta-lib/install.html) (install instructions [below](#install-ta-lib))
* [TA-Lib](https://ta-lib.github.io/ta-lib-python/) (install instructions [below](#install-ta-lib))
### Install code
@@ -210,7 +204,7 @@ sudo ./build_helpers/install_ta-lib.sh
##### TA-Lib manual installation
Official webpage: https://mrjbq7.github.io/ta-lib/install.html
[Official installation guide](https://ta-lib.github.io/ta-lib-python/install.html)
```bash
wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz
@@ -242,6 +236,7 @@ source .env/bin/activate
```bash
python3 -m pip install --upgrade pip
python3 -m pip install -r requirements.txt
python3 -m pip install -e .
```

100
docs/lookahead-analysis.md Normal file
View File

@@ -0,0 +1,100 @@
# Lookahead analysis
This page explains how to validate your strategy in terms of look ahead bias.
Checking look ahead bias is the bane of any strategy since it is sometimes very easy to introduce backtest bias -
but very hard to detect.
Backtesting initializes all timestamps at once and calculates all indicators in the beginning.
This means that if your indicators or entry/exit signals could look into future candles and falsify your backtest.
Lookahead-analysis requires historic data to be available.
To learn how to get data for the pairs and exchange you're interested in,
head over to the [Data Downloading](data-download.md) section of the documentation.
This command is built upon backtesting since it internally chains backtests and pokes at the strategy to provoke it to show look ahead bias.
This is done by not looking at the strategy itself - but at the results it returned.
The results are things like changed indicator-values and moved entries/exits compared to the full backtest.
You can use commands of [Backtesting](backtesting.md).
It also supports the lookahead-analysis of freqai strategies.
- `--cache` is forced to "none".
- `--max-open-trades` is forced to be at least equal to the number of pairs.
- `--dry-run-wallet` is forced to be basically infinite.
## Lookahead-analysis command reference
```
usage: freqtrade lookahead-analysis [-h] [-v] [--logfile FILE] [-V] [-c PATH]
[-d PATH] [--userdir PATH] [-s NAME]
[--strategy-path PATH]
[--recursive-strategy-search]
[--freqaimodel NAME]
[--freqaimodel-path PATH] [-i TIMEFRAME]
[--timerange TIMERANGE]
[--data-format-ohlcv {json,jsongz,hdf5,feather,parquet}]
[--max-open-trades INT]
[--stake-amount STAKE_AMOUNT]
[--fee FLOAT] [-p PAIRS [PAIRS ...]]
[--enable-protections]
[--dry-run-wallet DRY_RUN_WALLET]
[--timeframe-detail TIMEFRAME_DETAIL]
[--strategy-list STRATEGY_LIST [STRATEGY_LIST ...]]
[--export {none,trades,signals}]
[--export-filename PATH]
[--breakdown {day,week,month} [{day,week,month} ...]]
[--cache {none,day,week,month}]
[--freqai-backtest-live-models]
[--minimum-trade-amount INT]
[--targeted-trade-amount INT]
[--lookahead-analysis-exportfilename LOOKAHEAD_ANALYSIS_EXPORTFILENAME]
options:
--minimum-trade-amount INT
Minimum trade amount for lookahead-analysis
--targeted-trade-amount INT
Targeted trade amount for lookahead analysis
--lookahead-analysis-exportfilename LOOKAHEAD_ANALYSIS_EXPORTFILENAME
Use this csv-filename to store lookahead-analysis-
results
```
!!! Note ""
The above Output was reduced to options `lookahead-analysis` adds on top of regular backtesting commands.
### Summary
Checks a given strategy for look ahead bias via lookahead-analysis
Look ahead bias means that the backtest uses data from future candles thereby not making it viable beyond backtesting
and producing false hopes for the one backtesting.
### Introduction
Many strategies - without the programmer knowing - have fallen prey to look ahead bias.
Any backtest will populate the full dataframe including all time stamps at the beginning.
If the programmer is not careful or oblivious how things work internally
(which sometimes can be really hard to find out) then it will just look into the future making the strategy amazing
but not realistic.
This command is made to try to verify the validity in the form of the aforementioned look ahead bias.
### How does the command work?
It will start with a backtest of all pairs to generate a baseline for indicators and entries/exits.
After the backtest ran, it will look if the `minimum-trade-amount` is met
and if not cancel the lookahead-analysis for this strategy.
After setting the baseline it will then do additional runs for every entry and exit separately.
When a verification-backtest is done, it will compare the indicators as the signal (either entry or exit) and report the bias.
After all signals have been verified or falsified a result-table will be generated for the user to see.
### Caveats
- `lookahead-analysis` can only verify / falsify the trades it calculated and verified.
If the strategy has many different signals / signal types, it's up to you to select appropriate parameters to ensure that all signals have triggered at least once. Not triggered signals will not have been verified.
This could lead to a false-negative (the strategy will then be reported as non-biased).
- `lookahead-analysis` has access to everything that backtesting has too.
Please don't provoke any configs like enabling position stacking.
If you decide to do so, then make doubly sure that you won't ever run out of `max_open_trades` amount and neither leftover money in your wallet.

View File

@@ -49,7 +49,7 @@ Enable subscribing to an instance by adding the `external_message_consumer` sect
| `wait_timeout` | Timeout until we ping again if no message is received. <br>*Defaults to `300`.*<br> **Datatype:** Integer - in seconds.
| `ping_timeout` | Ping timeout <br>*Defaults to `10`.*<br> **Datatype:** Integer - in seconds.
| `sleep_time` | Sleep time before retrying to connect.<br>*Defaults to `10`.*<br> **Datatype:** Integer - in seconds.
| `remove_entry_exit_signals` | Remove signal columns from the dataframe (set them to 0) on dataframe receipt.<br>*Defaults to `False`.*<br> **Datatype:** Boolean.
| `remove_entry_exit_signals` | Remove signal columns from the dataframe (set them to 0) on dataframe receipt.<br>*Defaults to `false`.*<br> **Datatype:** Boolean.
| `message_size_limit` | Size limit per message<br>*Defaults to `8`.*<br> **Datatype:** Integer - Megabytes.
Instead of (or as well as) calculating indicators in `populate_indicators()` the follower instance listens on the connection to a producer instance's messages (or multiple producer instances in advanced configurations) and requests the producer's most recently analyzed dataframes for each pair in the active whitelist.

View File

@@ -1,6 +1,6 @@
markdown==3.3.7
mkdocs==1.4.2
mkdocs-material==9.1.4
mkdocs==1.4.3
mkdocs-material==9.1.17
mdx_truly_sane_lists==1.3
pymdown-extensions==9.10
pymdown-extensions==10.0.1
jinja2==3.1.2

View File

@@ -9,9 +9,6 @@ This same command can also be used to update freqUI, should there be a new relea
Once the bot is started in trade / dry-run mode (with `freqtrade trade`) - the UI will be available under the configured port below (usually `http://127.0.0.1:8080`).
!!! info "Alpha release"
FreqUI is still considered an alpha release - if you encounter bugs or inconsistencies please open a [FreqUI issue](https://github.com/freqtrade/frequi/issues/new/choose).
!!! Note "developers"
Developers should not use this method, but instead use the method described in the [freqUI repository](https://github.com/freqtrade/frequi) to get the source-code of freqUI.
@@ -137,7 +134,9 @@ python3 scripts/rest_client.py --config rest_config.json <command> [optional par
| `reload_config` | Reloads the configuration file.
| `trades` | List last trades. Limited to 500 trades per call.
| `trade/<tradeid>` | Get specific trade.
| `delete_trade <trade_id>` | Remove trade from the database. Tries to close open orders. Requires manual handling of this trade on the exchange.
| `trade/<tradeid>` | DELETE - Remove trade from the database. Tries to close open orders. Requires manual handling of this trade on the exchange.
| `trade/<tradeid>/open-order` | DELETE - Cancel open order for this trade.
| `trade/<tradeid>/reload` | GET - Reload a trade from the Exchange. Only works in live, and can potentially help recover a trade that was manually sold on the exchange.
| `show_config` | Shows part of the current configuration with relevant settings to operation.
| `logs` | Shows last log messages.
| `status` | Lists all open trades.

View File

@@ -23,10 +23,22 @@ These modes can be configured with these values:
'stoploss_on_exchange_limit_ratio': 0.99
```
!!! Note
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.
Stoploss on exchange is only supported for the following exchanges, and not all exchanges support both stop-limit and stop-market.
The Order-type will be ignored if only one mode is available.
| Exchange | stop-loss type |
|----------|-------------|
| Binance | limit |
| Binance Futures | market, limit |
| Huobi | limit |
| kraken | market, limit |
| Gate | limit |
| Okx | limit |
| Kucoin | stop-limit, stop-market|
!!! Note "Tight stoploss"
<ins>Do not set too low/tight stoploss value when using stop loss on exchange!</ins>
If set to low/tight you will have greater risk of missing fill on the order and stoploss will not work.
### stoploss_on_exchange and stoploss_on_exchange_limit_ratio
@@ -197,11 +209,6 @@ You can also keep a static stoploss until the offset is reached, and then trail
If `trailing_only_offset_is_reached = True` then the trailing stoploss is only activated once the offset is reached. Until then, the stoploss remains at the configured `stoploss`.
This option can be used with or without `trailing_stop_positive`, but uses `trailing_stop_positive_offset` as offset.
``` python
trailing_stop_positive_offset = 0.011
trailing_only_offset_is_reached = True
```
Configuration (offset is buy-price + 3%):
``` python

View File

@@ -1,21 +1,21 @@
# Advanced Strategies
This page explains some advanced concepts available for strategies.
If you're just getting started, please be familiar with the methods described in the [Strategy Customization](strategy-customization.md) documentation and with the [Freqtrade basics](bot-basics.md) first.
If you're just getting started, please familiarize yourself with the [Freqtrade basics](bot-basics.md) and methods described in [Strategy Customization](strategy-customization.md) first.
[Freqtrade basics](bot-basics.md) describes in which sequence each method described below is called, which can be helpful to understand which method to use for your custom needs.
The call sequence of the methods described here is covered under [bot execution logic](bot-basics.md#bot-execution-logic). Those docs are also helpful in deciding which method is most suitable for your customisation needs.
!!! Note
All callback methods described below should only be implemented in a strategy if they are actually used.
Callback methods should *only* be implemented if a strategy uses them.
!!! Tip
You can get a strategy template containing all below methods by running `freqtrade new-strategy --strategy MyAwesomeStrategy --template advanced`
Start off with a strategy template containing all available callback methods by running `freqtrade new-strategy --strategy MyAwesomeStrategy --template advanced`
## Storing information
Storing information can be accomplished by creating a new dictionary within the strategy class.
The name of the variable can be chosen at will, but should be prefixed with `cust_` to avoid naming collisions with predefined strategy variables.
The name of the variable can be chosen at will, but should be prefixed with `custom_` to avoid naming collisions with predefined strategy variables.
```python
class AwesomeStrategy(IStrategy):
@@ -227,8 +227,8 @@ for val in self.buy_ema_short.range:
f'ema_short_{val}': ta.EMA(dataframe, timeperiod=val)
}))
# Append columns to existing dataframe
merged_frame = pd.concat(frames, axis=1)
# Combine all dataframes, and reassign the original dataframe column
dataframe = pd.concat(frames, axis=1)
```
Freqtrade does however also counter this by running `dataframe.copy()` on the dataframe right after the `populate_indicators()` method - so performance implications of this should be low to non-existant.

View File

@@ -43,7 +43,7 @@ class AwesomeStrategy(IStrategy):
if self.config['runmode'].value in ('live', 'dry_run'):
# Assign this to the class by using self.*
# can then be used by populate_* methods
self.cust_remote_data = requests.get('https://some_remote_source.example.com')
self.custom_remote_data = requests.get('https://some_remote_source.example.com')
```
@@ -352,7 +352,7 @@ class AwesomeStrategy(IStrategy):
# Convert absolute price to percentage relative to current_rate
if stoploss_price < current_rate:
return (stoploss_price / current_rate) - 1
return stoploss_from_absolute(stoploss_price, current_rate, is_short=trade.is_short)
# return maximum stoploss value, keeping current stoploss price unchanged
return 1

View File

@@ -342,16 +342,12 @@ The above configuration would therefore mean:
The calculation does include fees.
To disable ROI completely, set it to an insanely high number:
To disable ROI completely, set it to an empty dictionary:
```python
minimal_roi = {
"0": 100
}
minimal_roi = {}
```
While technically not completely disabled, this would exit once the trade reaches 10000% Profit.
To use times based on candle duration (timeframe), the following snippet can be handy.
This will allow you to change the timeframe for the strategy, and ROI times will still be set as candles (e.g. after 3 candles ...)

View File

@@ -578,7 +578,7 @@ def populate_any_indicators(
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):
def feature_engineering_expand_all(self, dataframe, period, **kwargs) -> DataFrame::
"""
*Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined
@@ -638,7 +638,7 @@ Features will now expand automatically. As such, the expansion loops, as well as
Basic features. Make sure to remove the `{pair}` part from your features.
``` python linenums="1"
def feature_engineering_expand_basic(self, dataframe, **kwargs):
def feature_engineering_expand_basic(self, dataframe: DataFrame, **kwargs) -> DataFrame::
"""
*Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined
@@ -673,7 +673,7 @@ Basic features. Make sure to remove the `{pair}` part from your features.
### FreqAI - feature engineering standard
``` python linenums="1"
def feature_engineering_standard(self, dataframe, **kwargs):
def feature_engineering_standard(self, dataframe: DataFrame, **kwargs) -> DataFrame:
"""
*Only functional with FreqAI enabled strategies*
This optional function will be called once with the dataframe of the base timeframe.
@@ -704,7 +704,7 @@ Basic features. Make sure to remove the `{pair}` part from your features.
Targets now get their own, dedicated method.
``` python linenums="1"
def set_freqai_targets(self, dataframe, **kwargs):
def set_freqai_targets(self, dataframe: DataFrame, **kwargs) -> DataFrame:
"""
*Only functional with FreqAI enabled strategies*
Required function to set the targets for the model.
@@ -728,3 +728,86 @@ Targets now get their own, dedicated method.
return dataframe
```
### FreqAI - New data Pipeline
If you have created your own custom `IFreqaiModel` with a custom `train()`/`predict()` function, *and* you still rely on `data_cleaning_train/predict()`, then you will need to migrate to the new pipeline. If your model does *not* rely on `data_cleaning_train/predict()`, then you do not need to worry about this migration. That means that this migration guide is relevant for a very small percentage of power-users. If you stumbled upon this guide by mistake, feel free to inquire in depth about your problem in the Freqtrade discord server.
The conversion involves first removing `data_cleaning_train/predict()` and replacing them with a `define_data_pipeline()` and `define_label_pipeline()` function to your `IFreqaiModel` class:
```python linenums="1" hl_lines="11-14 47-49 55-57"
class MyCoolFreqaiModel(BaseRegressionModel):
"""
Some cool custom IFreqaiModel you made before Freqtrade version 2023.6
"""
def train(
self, unfiltered_df: DataFrame, pair: str, dk: FreqaiDataKitchen, **kwargs
) -> Any:
# ... your custom stuff
# Remove these lines
# data_dictionary = dk.make_train_test_datasets(features_filtered, labels_filtered)
# self.data_cleaning_train(dk)
# data_dictionary = dk.normalize_data(data_dictionary)
# (1)
# Add these lines. Now we control the pipeline fit/transform ourselves
dd = dk.make_train_test_datasets(features_filtered, labels_filtered)
dk.feature_pipeline = self.define_data_pipeline(threads=dk.thread_count)
dk.label_pipeline = self.define_label_pipeline(threads=dk.thread_count)
(dd["train_features"],
dd["train_labels"],
dd["train_weights"]) = dk.feature_pipeline.fit_transform(dd["train_features"],
dd["train_labels"],
dd["train_weights"])
(dd["test_features"],
dd["test_labels"],
dd["test_weights"]) = dk.feature_pipeline.transform(dd["test_features"],
dd["test_labels"],
dd["test_weights"])
dd["train_labels"], _, _ = dk.label_pipeline.fit_transform(dd["train_labels"])
dd["test_labels"], _, _ = dk.label_pipeline.transform(dd["test_labels"])
# ... your custom code
return model
def predict(
self, unfiltered_df: DataFrame, dk: FreqaiDataKitchen, **kwargs
) -> Tuple[DataFrame, npt.NDArray[np.int_]]:
# ... your custom stuff
# Remove these lines:
# self.data_cleaning_predict(dk)
# (2)
# Add these lines:
dk.data_dictionary["prediction_features"], outliers, _ = dk.feature_pipeline.transform(
dk.data_dictionary["prediction_features"], outlier_check=True)
# Remove this line
# pred_df = dk.denormalize_labels_from_metadata(pred_df)
# (3)
# Replace with these lines
pred_df, _, _ = dk.label_pipeline.inverse_transform(pred_df)
if self.freqai_info.get("DI_threshold", 0) > 0:
dk.DI_values = dk.feature_pipeline["di"].di_values
else:
dk.DI_values = np.zeros(outliers.shape[0])
dk.do_predict = outliers
# ... your custom code
return (pred_df, dk.do_predict)
```
1. Data normalization and cleaning is now homogenized with the new pipeline definition. This is created in the new `define_data_pipeline()` and `define_label_pipeline()` functions. The `data_cleaning_train()` and `data_cleaning_predict()` functions are no longer used. You can override `define_data_pipeline()` to create your own custom pipeline if you wish.
2. Data normalization and cleaning is now homogenized with the new pipeline definition. This is created in the new `define_data_pipeline()` and `define_label_pipeline()` functions. The `data_cleaning_train()` and `data_cleaning_predict()` functions are no longer used. You can override `define_data_pipeline()` to create your own custom pipeline if you wish.
3. Data denormalization is done with the new pipeline. Replace this with the lines below.

View File

@@ -187,11 +187,13 @@ official commands. You can ask at any moment for help with `/help`.
| `/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.
| `/reload_trade <trade_id>` | Reload a trade from the Exchange. Only works in live, and can potentially help recover a trade that was manually sold 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
| `/balance` | Show bot managed balance per currency
| `/balance full` | Show account balance per currency
| `/daily <n>` | Shows profit or loss per day, over the last n days (n defaults to 7)
| `/weekly <n>` | Shows profit or loss per week, over the last n weeks (n defaults to 8)
| `/monthly <n>` | Shows profit or loss per month, over the last n months (n defaults to 6)
@@ -202,7 +204,6 @@ official commands. You can ask at any moment for help with `/help`.
| `/blacklist [pair]` | Show the current blacklist, or adds a pair to the blacklist.
| `/edge` | Show validated pairs by Edge if it is enabled.
## Telegram commands in action
Below, example of Telegram message you will receive for each command.
@@ -279,6 +280,7 @@ Return a summary of your profit/loss and performance.
> ∙ `33.095 EUR`
>
> **Total Trade Count:** `138`
> **Bot started:** `2022-07-11 18:40:44`
> **First Trade opened:** `3 days ago`
> **Latest Trade opened:** `2 minutes ago`
> **Avg. Duration:** `2:33:45`
@@ -292,6 +294,7 @@ The relative profit of `15.2 Σ%` is be based on the starting capital - so in th
Starting capital is either taken from the `available_capital` setting, or calculated by using current wallet size - profits.
Profit Factor is calculated as gross profits / gross losses - and should serve as an overall metric for the strategy.
Max drawdown corresponds to the backtesting metric `Absolute Drawdown (Account)` - calculated as `(Absolute Drawdown) / (DrawdownHigh + startingBalance)`.
Bot started date will refer to the date the bot was first started. For older bots, this will default to the first trade's open date.
### /forceexit <trade_id>

View File

@@ -723,6 +723,9 @@ usage: freqtrade backtesting-analysis [-h] [-v] [--logfile FILE] [-V]
[--exit-reason-list EXIT_REASON_LIST [EXIT_REASON_LIST ...]]
[--indicator-list INDICATOR_LIST [INDICATOR_LIST ...]]
[--timerange YYYYMMDD-[YYYYMMDD]]
[--rejected]
[--analysis-to-csv]
[--analysis-csv-path PATH]
optional arguments:
-h, --help show this help message and exit
@@ -736,19 +739,27 @@ optional arguments:
pair and enter_tag, 4: by pair, enter_ and exit_tag
(this can get quite large)
--enter-reason-list ENTER_REASON_LIST [ENTER_REASON_LIST ...]
Comma separated list of entry signals to analyse.
Default: all. e.g. 'entry_tag_a,entry_tag_b'
Space separated list of entry signals to analyse.
Default: all. e.g. 'entry_tag_a entry_tag_b'
--exit-reason-list EXIT_REASON_LIST [EXIT_REASON_LIST ...]
Comma separated list of exit signals to analyse.
Space separated list of exit signals to analyse.
Default: all. e.g.
'exit_tag_a,roi,stop_loss,trailing_stop_loss'
'exit_tag_a roi stop_loss trailing_stop_loss'
--indicator-list INDICATOR_LIST [INDICATOR_LIST ...]
Comma separated list of indicators to analyse. e.g.
'close,rsi,bb_lowerband,profit_abs'
Space 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
--rejected
Print out rejected trades table
--analysis-to-csv
Write out tables to individual CSVs, by default to
'user_data/backtest_results' unless '--analysis-csv-path' is given.
--analysis-csv-path [PATH]
Optional path where individual CSVs will be written. If not used,
CSVs will be written to 'user_data/backtest_results'.
Common arguments:
-v, --verbose Verbose mode (-vv for more, -vvv to get all messages).

View File

@@ -24,9 +24,9 @@ git clone https://github.com/freqtrade/freqtrade.git
Install ta-lib according to the [ta-lib documentation](https://github.com/mrjbq7/ta-lib#windows).
As compiling from source on windows has heavy dependencies (requires a partial visual studio installation), there is also a repository of unofficial pre-compiled windows Wheels [here](https://www.lfd.uci.edu/~gohlke/pythonlibs/#ta-lib), which need to be downloaded and installed using `pip install TA_Lib-0.4.25-cp38-cp38-win_amd64.whl` (make sure to use the version matching your python version).
As compiling from source on windows has heavy dependencies (requires a partial visual studio installation), Freqtrade provides these dependencies (in the binary wheel format) for the latest 3 Python versions (3.8, 3.9, 3.10 and 3.11) and for 64bit Windows.
These Wheels are also used by CI running on windows, and are therefore tested together with freqtrade.
Freqtrade provides these dependencies for the latest 3 Python versions (3.8, 3.9, 3.10 and 3.11) and for 64bit Windows.
Other versions must be downloaded from the above link.
``` powershell
@@ -45,8 +45,6 @@ freqtrade
The above installation script assumes you're using powershell on a 64bit windows.
Commands for the legacy CMD windows console may differ.
> Thanks [Owdr](https://github.com/Owdr) for the commands. Source: [Issue #222](https://github.com/freqtrade/freqtrade/issues/222)
### Error during installation on Windows
``` bash

View File

@@ -1,5 +1,5 @@
""" Freqtrade bot """
__version__ = '2023.3'
__version__ = '2023.6'
if 'dev' in __version__:
from pathlib import Path

View File

@@ -19,7 +19,8 @@ from freqtrade.commands.list_commands import (start_list_exchanges, start_list_f
start_list_markets, start_list_strategies,
start_list_timeframes, start_show_trades)
from freqtrade.commands.optimize_commands import (start_backtesting, start_backtesting_show,
start_edge, start_hyperopt)
start_edge, start_hyperopt,
start_lookahead_analysis)
from freqtrade.commands.pairlist_commands import start_test_pairlist
from freqtrade.commands.plot_commands import start_plot_dataframe, start_plot_profit
from freqtrade.commands.strategy_utils_commands import start_strategy_update

29
freqtrade/commands/arguments.py Normal file → Executable file
View File

@@ -46,7 +46,7 @@ ARGS_LIST_FREQAIMODELS = ["freqaimodel_path", "print_one_column", "print_coloriz
ARGS_LIST_HYPEROPTS = ["hyperopt_path", "print_one_column", "print_colorized"]
ARGS_BACKTEST_SHOW = ["exportfilename", "backtest_show_pair_list"]
ARGS_BACKTEST_SHOW = ["exportfilename", "backtest_show_pair_list", "backtest_breakdown"]
ARGS_LIST_EXCHANGES = ["print_one_column", "list_exchanges_all"]
@@ -106,7 +106,8 @@ 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", "timerange"]
"exit_reason_list", "indicator_list", "timerange",
"analysis_rejected", "analysis_to_csv", "analysis_csv_path"]
NO_CONF_REQURIED = ["convert-data", "convert-trade-data", "download-data", "list-timeframes",
"list-markets", "list-pairs", "list-strategies", "list-freqaimodels",
@@ -116,7 +117,11 @@ NO_CONF_REQURIED = ["convert-data", "convert-trade-data", "download-data", "list
NO_CONF_ALLOWED = ["create-userdir", "list-exchanges", "new-strategy"]
ARGS_STRATEGY_UTILS = ["strategy_list", "strategy_path", "recursive_strategy_search"]
ARGS_STRATEGY_UPDATER = ["strategy_list", "strategy_path", "recursive_strategy_search"]
ARGS_LOOKAHEAD_ANALYSIS = [
a for a in ARGS_BACKTEST if a not in ("position_stacking", "use_max_market_positions", 'cache')
] + ["minimum_trade_amount", "targeted_trade_amount", "lookahead_analysis_exportfilename"]
class Arguments:
@@ -200,8 +205,9 @@ class Arguments:
start_install_ui, start_list_data, start_list_exchanges,
start_list_freqAI_models, start_list_markets,
start_list_strategies, start_list_timeframes,
start_new_config, start_new_strategy, start_plot_dataframe,
start_plot_profit, start_show_trades, start_strategy_update,
start_lookahead_analysis, start_new_config,
start_new_strategy, start_plot_dataframe, start_plot_profit,
start_show_trades, start_strategy_update,
start_test_pairlist, start_trading, start_webserver)
subparsers = self.parser.add_subparsers(dest='command',
@@ -450,4 +456,15 @@ class Arguments:
'files to the current version',
parents=[_common_parser])
strategy_updater_cmd.set_defaults(func=start_strategy_update)
self._build_args(optionlist=ARGS_STRATEGY_UTILS, parser=strategy_updater_cmd)
self._build_args(optionlist=ARGS_STRATEGY_UPDATER, parser=strategy_updater_cmd)
# Add lookahead_analysis subcommand
lookahead_analayis_cmd = subparsers.add_parser(
'lookahead-analysis',
help="Check for potential look ahead bias.",
parents=[_common_parser, _strategy_parser])
lookahead_analayis_cmd.set_defaults(func=start_lookahead_analysis)
self._build_args(optionlist=ARGS_LOOKAHEAD_ANALYSIS,
parser=lookahead_analayis_cmd)

46
freqtrade/commands/cli_options.py Normal file → Executable file
View File

@@ -636,30 +636,45 @@ AVAILABLE_CLI_OPTIONS = {
"4: by pair, enter_ and exit_tag (this can get quite large), "
"5: by exit_tag"),
nargs='+',
default=['0', '1', '2'],
default=[],
choices=['0', '1', '2', '3', '4', '5'],
),
"enter_reason_list": Arg(
"--enter-reason-list",
help=("Comma separated list of entry signals to analyse. Default: all. "
"e.g. 'entry_tag_a,entry_tag_b'"),
help=("Space separated list of entry signals to analyse. Default: all. "
"e.g. 'entry_tag_a entry_tag_b'"),
nargs='+',
default=['all'],
),
"exit_reason_list": Arg(
"--exit-reason-list",
help=("Comma separated list of exit signals to analyse. Default: all. "
"e.g. 'exit_tag_a,roi,stop_loss,trailing_stop_loss'"),
help=("Space separated list of exit signals to analyse. Default: all. "
"e.g. 'exit_tag_a roi stop_loss trailing_stop_loss'"),
nargs='+',
default=['all'],
),
"indicator_list": Arg(
"--indicator-list",
help=("Comma separated list of indicators to analyse. "
"e.g. 'close,rsi,bb_lowerband,profit_abs'"),
help=("Space separated list of indicators to analyse. "
"e.g. 'close rsi bb_lowerband profit_abs'"),
nargs='+',
default=[],
),
"analysis_rejected": Arg(
'--rejected-signals',
help='Analyse rejected signals',
action='store_true',
),
"analysis_to_csv": Arg(
'--analysis-to-csv',
help='Save selected analysis tables to individual CSVs',
action='store_true',
),
"analysis_csv_path": Arg(
'--analysis-csv-path',
help=("Specify a path to save the analysis CSVs "
"if --analysis-to-csv is enabled. Default: user_data/basktesting_results/"),
),
"freqaimodel": Arg(
'--freqaimodel',
help='Specify a custom freqaimodels.',
@@ -675,4 +690,21 @@ AVAILABLE_CLI_OPTIONS = {
help='Run backtest with ready models.',
action='store_true'
),
"minimum_trade_amount": Arg(
'--minimum-trade-amount',
help='Minimum trade amount for lookahead-analysis',
type=check_int_positive,
metavar='INT',
),
"targeted_trade_amount": Arg(
'--targeted-trade-amount',
help='Targeted trade amount for lookahead analysis',
type=check_int_positive,
metavar='INT',
),
"lookahead_analysis_exportfilename": Arg(
'--lookahead-analysis-exportfilename',
help="Use this csv-filename to store lookahead-analysis-results",
type=str
),
}

View File

@@ -1,18 +1,16 @@
import logging
import sys
from collections import defaultdict
from datetime import datetime, timedelta
from typing import Any, Dict, List
from typing import Any, Dict
from freqtrade.configuration import TimeRange, setup_utils_configuration
from freqtrade.constants import DATETIME_PRINT_FORMAT, Config
from freqtrade.data.converter import convert_ohlcv_format, convert_trades_format
from freqtrade.data.history import (convert_trades_to_ohlcv, refresh_backtest_ohlcv_data,
refresh_backtest_trades_data)
from freqtrade.data.history import convert_trades_to_ohlcv, download_data_main
from freqtrade.enums import CandleType, RunMode, TradingMode
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.exchange import timeframe_to_minutes
from freqtrade.plugins.pairlist.pairlist_helpers import expand_pairlist
from freqtrade.resolvers import ExchangeResolver
from freqtrade.util.binance_mig import migrate_binance_futures_data
@@ -20,7 +18,7 @@ from freqtrade.util.binance_mig import migrate_binance_futures_data
logger = logging.getLogger(__name__)
def _data_download_sanity(config: Config) -> None:
def _check_data_config_download_sanity(config: Config) -> None:
if 'days' in config and 'timerange' in config:
raise OperationalException("--days and --timerange are mutually exclusive. "
"You can only specify one or the other.")
@@ -37,78 +35,14 @@ def start_download_data(args: Dict[str, Any]) -> None:
"""
config = setup_utils_configuration(args, RunMode.UTIL_EXCHANGE)
_data_download_sanity(config)
timerange = TimeRange()
if 'days' in config:
time_since = (datetime.now() - timedelta(days=config['days'])).strftime("%Y%m%d")
timerange = TimeRange.parse_timerange(f'{time_since}-')
if 'timerange' in config:
timerange = timerange.parse_timerange(config['timerange'])
# Remove stake-currency to skip checks which are not relevant for datadownload
config['stake_currency'] = ''
pairs_not_available: List[str] = []
# Init exchange
exchange = ExchangeResolver.load_exchange(config['exchange']['name'], config, validate=False)
markets = [p for p, m in exchange.markets.items() if market_is_active(m)
or config.get('include_inactive')]
expanded_pairs = dynamic_expand_pairlist(config, markets)
# Manual validations of relevant settings
if not config['exchange'].get('skip_pair_validation', False):
exchange.validate_pairs(expanded_pairs)
logger.info(f"About to download pairs: {expanded_pairs}, "
f"intervals: {config['timeframes']} to {config['datadir']}")
for timeframe in config['timeframes']:
exchange.validate_timeframes(timeframe)
_check_data_config_download_sanity(config)
try:
if config.get('download_trades'):
if config.get('trading_mode') == 'futures':
raise OperationalException("Trade download not supported for futures.")
pairs_not_available = refresh_backtest_trades_data(
exchange, pairs=expanded_pairs, datadir=config['datadir'],
timerange=timerange, new_pairs_days=config['new_pairs_days'],
erase=bool(config.get('erase')), data_format=config['dataformat_trades'])
# Convert downloaded trade data to different timeframes
convert_trades_to_ohlcv(
pairs=expanded_pairs, timeframes=config['timeframes'],
datadir=config['datadir'], timerange=timerange, erase=bool(config.get('erase')),
data_format_ohlcv=config['dataformat_ohlcv'],
data_format_trades=config['dataformat_trades'],
)
else:
if not exchange.get_option('ohlcv_has_history', True):
raise OperationalException(
f"Historic klines not available for {exchange.name}. "
"Please use `--dl-trades` instead for this exchange "
"(will unfortunately take a long time)."
)
migrate_binance_futures_data(config)
pairs_not_available = refresh_backtest_ohlcv_data(
exchange, pairs=expanded_pairs, timeframes=config['timeframes'],
datadir=config['datadir'], timerange=timerange,
new_pairs_days=config['new_pairs_days'],
erase=bool(config.get('erase')), data_format=config['dataformat_ohlcv'],
trading_mode=config.get('trading_mode', 'spot'),
prepend=config.get('prepend_data', False)
)
download_data_main(config)
except KeyboardInterrupt:
sys.exit("SIGINT received, aborting ...")
finally:
if pairs_not_available:
logger.info(f"Pairs [{','.join(pairs_not_available)}] not available "
f"on exchange {exchange.name}.")
def start_convert_trades(args: Dict[str, Any]) -> None:
@@ -125,7 +59,7 @@ def start_convert_trades(args: Dict[str, Any]) -> None:
"Please check the documentation on how to configure this.")
# Init exchange
exchange = ExchangeResolver.load_exchange(config['exchange']['name'], config, validate=False)
exchange = ExchangeResolver.load_exchange(config, validate=False)
# Manual validations of relevant settings
if not config['exchange'].get('skip_pair_validation', False):
exchange.validate_pairs(config['pairs'])

View File

@@ -1,7 +1,7 @@
import csv
import logging
import sys
from typing import Any, Dict, List
from typing import Any, Dict, List, Union
import rapidjson
from colorama import Fore, Style
@@ -11,9 +11,10 @@ from tabulate import tabulate
from freqtrade.configuration import setup_utils_configuration
from freqtrade.enums import RunMode
from freqtrade.exceptions import OperationalException
from freqtrade.exchange import market_is_active, validate_exchanges
from freqtrade.exchange import list_available_exchanges, market_is_active
from freqtrade.misc import parse_db_uri_for_logging, plural
from freqtrade.resolvers import ExchangeResolver, StrategyResolver
from freqtrade.types import ValidExchangesType
logger = logging.getLogger(__name__)
@@ -25,18 +26,42 @@ def start_list_exchanges(args: Dict[str, Any]) -> None:
:param args: Cli args from Arguments()
:return: None
"""
exchanges = validate_exchanges(args['list_exchanges_all'])
exchanges = list_available_exchanges(args['list_exchanges_all'])
if args['print_one_column']:
print('\n'.join([e[0] for e in exchanges]))
print('\n'.join([e['name'] for e in exchanges]))
else:
headers = {
'name': 'Exchange name',
'supported': 'Supported',
'trade_modes': 'Markets',
'comment': 'Reason',
}
headers.update({'valid': 'Valid'} if args['list_exchanges_all'] else {})
def build_entry(exchange: ValidExchangesType, valid: bool):
valid_entry = {'valid': exchange['valid']} if valid else {}
result: Dict[str, Union[str, bool]] = {
'name': exchange['name'],
**valid_entry,
'supported': 'Official' if exchange['supported'] else '',
'trade_modes': ', '.join(
(f"{a['margin_mode']} " if a['margin_mode'] else '') + a['trading_mode']
for a in exchange['trade_modes']
),
'comment': exchange['comment'],
}
return result
if args['list_exchanges_all']:
print("All exchanges supported by the ccxt library:")
exchanges = [build_entry(e, True) for e in exchanges]
else:
print("Exchanges available for Freqtrade:")
exchanges = [e for e in exchanges if e[1] is not False]
exchanges = [build_entry(e, False) for e in exchanges if e['valid'] is not False]
print(tabulate(exchanges, headers=['Exchange name', 'Valid', 'reason']))
print(tabulate(exchanges, headers=headers, ))
def _print_objs_tabular(objs: List, print_colorized: bool) -> None:
@@ -114,7 +139,7 @@ def start_list_timeframes(args: Dict[str, Any]) -> None:
config['timeframe'] = None
# Init exchange
exchange = ExchangeResolver.load_exchange(config['exchange']['name'], config, validate=False)
exchange = ExchangeResolver.load_exchange(config, validate=False)
if args['print_one_column']:
print('\n'.join(exchange.timeframes))
@@ -133,7 +158,7 @@ def start_list_markets(args: Dict[str, Any], pairs_only: bool = False) -> None:
config = setup_utils_configuration(args, RunMode.UTIL_EXCHANGE)
# Init exchange
exchange = ExchangeResolver.load_exchange(config['exchange']['name'], config, validate=False)
exchange = ExchangeResolver.load_exchange(config, validate=False)
# By default only active pairs/markets are to be shown
active_only = not args.get('list_pairs_all', False)

View File

@@ -132,3 +132,15 @@ def start_edge(args: Dict[str, Any]) -> None:
# Initialize Edge object
edge_cli = EdgeCli(config)
edge_cli.start()
def start_lookahead_analysis(args: Dict[str, Any]) -> None:
"""
Start the backtest bias tester script
:param args: Cli args from Arguments()
:return: None
"""
from freqtrade.optimize.lookahead_analysis_helpers import LookaheadAnalysisSubFunctions
config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE)
LookaheadAnalysisSubFunctions.start(config)

View File

@@ -18,7 +18,7 @@ def start_test_pairlist(args: Dict[str, Any]) -> None:
from freqtrade.plugins.pairlistmanager import PairListManager
config = setup_utils_configuration(args, RunMode.UTIL_EXCHANGE)
exchange = ExchangeResolver.load_exchange(config['exchange']['name'], config, validate=False)
exchange = ExchangeResolver.load_exchange(config, validate=False)
quote_currencies = args.get('quote_currencies')
if not quote_currencies:

View File

@@ -174,7 +174,7 @@ def _validate_whitelist(conf: Dict[str, Any]) -> None:
return
for pl in conf.get('pairlists', [{'method': 'StaticPairList'}]):
if (pl.get('method') == 'StaticPairList'
if (isinstance(pl, dict) and pl.get('method') == 'StaticPairList'
and not conf.get('exchange', {}).get('pair_whitelist')):
raise OperationalException("StaticPairList requires pair_whitelist to be set.")

View File

@@ -203,7 +203,7 @@ class Configuration:
# This will override the strategy configuration
self._args_to_config(config, argname='timeframe',
logstring='Parameter -i/--timeframe detected ... '
'Using timeframe: {} ...')
'Using timeframe: {} ...')
self._args_to_config(config, argname='position_stacking',
logstring='Parameter --enable-position-stacking detected ...')
@@ -300,6 +300,9 @@ class Configuration:
self._args_to_config(config, argname='hyperoptexportfilename',
logstring='Using hyperopt file: {}')
self._args_to_config(config, argname='lookahead_analysis_exportfilename',
logstring='Saving lookahead analysis results into {} ...')
self._args_to_config(config, argname='epochs',
logstring='Parameter --epochs detected ... '
'Will run Hyperopt with for {} epochs ...'
@@ -465,6 +468,28 @@ class Configuration:
self._args_to_config(config, argname='timerange',
logstring='Filter trades by timerange: {}')
self._args_to_config(config, argname='analysis_rejected',
logstring='Analyse rejected signals: {}')
self._args_to_config(config, argname='analysis_to_csv',
logstring='Store analysis tables to CSV: {}')
self._args_to_config(config, argname='analysis_csv_path',
logstring='Path to store analysis CSVs: {}')
self._args_to_config(config, argname='analysis_csv_path',
logstring='Path to store analysis CSVs: {}')
# Lookahead analysis results
self._args_to_config(config, argname='targeted_trade_amount',
logstring='Targeted Trade amount: {}')
self._args_to_config(config, argname='minimum_trade_amount',
logstring='Minimum Trade amount: {}')
self._args_to_config(config, argname='lookahead_analysis_exportfilename',
logstring='Path to store lookahead-analysis-results: {}')
def _process_runmode(self, config: Config) -> None:
self._args_to_config(config, argname='dry_run',
@@ -543,6 +568,7 @@ class Configuration:
# Fall back to /dl_path/pairs.json
pairs_file = config['datadir'] / 'pairs.json'
if pairs_file.exists():
logger.info(f'Reading pairs file "{pairs_file}".')
config['pairs'] = load_file(pairs_file)
if 'pairs' in config and isinstance(config['pairs'], list):
config['pairs'].sort()

View File

@@ -6,7 +6,7 @@ import re
from datetime import datetime, timezone
from typing import Optional
import arrow
from typing_extensions import Self
from freqtrade.constants import DATETIME_PRINT_FORMAT
from freqtrade.exceptions import OperationalException
@@ -109,15 +109,15 @@ class TimeRange:
self.startts = int(min_date.timestamp() + timeframe_secs * startup_candles)
self.starttype = 'date'
@staticmethod
def parse_timerange(text: Optional[str]) -> 'TimeRange':
@classmethod
def parse_timerange(cls, text: Optional[str]) -> Self:
"""
Parse the value of the argument --timerange to determine what is the range desired
:param text: value from --timerange
:return: Start and End range period
"""
if text is None:
return TimeRange(None, None, 0, 0)
if not text:
return cls(None, None, 0, 0)
syntax = [(r'^-(\d{8})$', (None, 'date')),
(r'^(\d{8})-$', ('date', None)),
(r'^(\d{8})-(\d{8})$', ('date', 'date')),
@@ -139,7 +139,8 @@ class TimeRange:
if stype[0]:
starts = rvals[index]
if stype[0] == 'date' and len(starts) == 8:
start = arrow.get(starts, 'YYYYMMDD').int_timestamp
start = int(datetime.strptime(starts, '%Y%m%d').replace(
tzinfo=timezone.utc).timestamp())
elif len(starts) == 13:
start = int(starts) // 1000
else:
@@ -148,7 +149,8 @@ class TimeRange:
if stype[1]:
stops = rvals[index]
if stype[1] == 'date' and len(stops) == 8:
stop = arrow.get(stops, 'YYYYMMDD').int_timestamp
stop = int(datetime.strptime(stops, '%Y%m%d').replace(
tzinfo=timezone.utc).timestamp())
elif len(stops) == 13:
stop = int(stops) // 1000
else:
@@ -156,5 +158,5 @@ class TimeRange:
if start > stop > 0:
raise OperationalException(
f'Start date is after stop date for timerange "{text}"')
return TimeRange(stype[0], stype[1], start, stop)
return cls(stype[0], stype[1], start, stop)
raise OperationalException(f'Incorrect syntax for timerange "{text}"')

View File

@@ -8,6 +8,7 @@ from typing import Any, Dict, List, Literal, Tuple
from freqtrade.enums import CandleType, PriceType, RPCMessageType
DOCS_LINK = "https://www.freqtrade.io/en/stable"
DEFAULT_CONFIG = 'config.json'
DEFAULT_EXCHANGE = 'bittrex'
PROCESS_THROTTLE_SECS = 5 # sec
@@ -64,6 +65,7 @@ USERPATH_FREQAIMODELS = 'freqaimodels'
TELEGRAM_SETTING_OPTIONS = ['on', 'off', 'silent']
WEBHOOK_FORMAT_OPTIONS = ['form', 'json', 'raw']
FULL_DATAFRAME_THRESHOLD = 100
CUSTOM_TAG_MAX_LENGTH = 255
ENV_VAR_PREFIX = 'FREQTRADE__'
@@ -110,6 +112,8 @@ MINIMAL_CONFIG = {
}
}
__MESSAGE_TYPE_DICT: Dict[str, Dict[str, str]] = {x: {'type': 'object'} for x in RPCMessageType}
# Required json-schema for user specified config
CONF_SCHEMA = {
'type': 'object',
@@ -147,7 +151,6 @@ CONF_SCHEMA = {
'patternProperties': {
'^[0-9.]+$': {'type': 'number'}
},
'minProperties': 1
},
'amount_reserve_percent': {'type': 'number', 'minimum': 0.0, 'maximum': 0.5},
'stoploss': {'type': 'number', 'maximum': 0, 'exclusiveMaximum': True, 'minimum': -1},
@@ -163,6 +166,9 @@ CONF_SCHEMA = {
'trading_mode': {'type': 'string', 'enum': TRADING_MODES},
'margin_mode': {'type': 'string', 'enum': MARGIN_MODES},
'reduce_df_footprint': {'type': 'boolean', 'default': False},
'minimum_trade_amount': {'type': 'number', 'default': 10},
'targeted_trade_amount': {'type': 'number', 'default': 20},
'lookahead_analysis_exportfilename': {'type': 'string'},
'liquidation_buffer': {'type': 'number', 'minimum': 0.0, 'maximum': 0.99},
'backtest_breakdown': {
'type': 'array',
@@ -350,7 +356,8 @@ CONF_SCHEMA = {
'format': {'type': 'string', 'enum': WEBHOOK_FORMAT_OPTIONS, 'default': 'form'},
'retries': {'type': 'integer', 'minimum': 0},
'retry_delay': {'type': 'number', 'minimum': 0},
**dict([(x, {'type': 'object'}) for x in RPCMessageType]),
**__MESSAGE_TYPE_DICT,
# **{x: {'type': 'object'} for x in RPCMessageType},
# Below -> Deprecated
'webhookentry': {'type': 'object'},
'webhookentrycancel': {'type': 'object'},
@@ -598,7 +605,8 @@ CONF_SCHEMA = {
"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},
"randomize_starting_position": {"type": "boolean", "default": False},
"progress_bar": {"type": "boolean", "default": True},
"model_reward_parameters": {
"type": "object",
"properties": {
@@ -688,4 +696,6 @@ BidAsk = Literal['bid', 'ask']
OBLiteral = Literal['asks', 'bids']
Config = Dict[str, Any]
# Exchange part of the configuration.
ExchangeConfig = Dict[str, Any]
IntOrInf = float

View File

@@ -246,14 +246,8 @@ 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
)
df['open_date'] = pd.to_datetime(df['open_date'], utc=True)
df['close_date'] = pd.to_datetime(df['close_date'], utc=True)
# Compatibility support for pre short Columns
if 'is_short' not in df.columns:
df['is_short'] = False

View File

@@ -34,7 +34,7 @@ def ohlcv_to_dataframe(ohlcv: list, timeframe: str, pair: str, *,
cols = DEFAULT_DATAFRAME_COLUMNS
df = DataFrame(ohlcv, columns=cols)
df['date'] = to_datetime(df['date'], unit='ms', utc=True, infer_datetime_format=True)
df['date'] = to_datetime(df['date'], unit='ms', utc=True)
# Some exchanges return int values for Volume and even for OHLC.
# Convert them since TA-LIB indicators used in the strategy assume floats

View File

@@ -1,5 +1,6 @@
import logging
from pathlib import Path
from typing import List
import joblib
import pandas as pd
@@ -15,22 +16,31 @@ from freqtrade.exceptions import OperationalException
logger = logging.getLogger(__name__)
def _load_signal_candles(backtest_dir: Path):
def _load_backtest_analysis_data(backtest_dir: Path, name: str):
if backtest_dir.is_dir():
scpf = Path(backtest_dir,
Path(get_latest_backtest_filename(backtest_dir)).stem + "_signals.pkl"
Path(get_latest_backtest_filename(backtest_dir)).stem + "_" + name + ".pkl"
)
else:
scpf = Path(backtest_dir.parent / f"{backtest_dir.stem}_signals.pkl")
scpf = Path(backtest_dir.parent / f"{backtest_dir.stem}_{name}.pkl")
try:
with scpf.open("rb") as scp:
signal_candles = joblib.load(scp)
logger.info(f"Loaded signal candles: {str(scpf)}")
loaded_data = joblib.load(scp)
logger.info(f"Loaded {name} candles: {str(scpf)}")
except Exception as e:
logger.error("Cannot load signal candles from pickled results: ", e)
logger.error(f"Cannot load {name} data from pickled results: ", e)
return None
return signal_candles
return loaded_data
def _load_rejected_signals(backtest_dir: Path):
return _load_backtest_analysis_data(backtest_dir, "rejected")
def _load_signal_candles(backtest_dir: Path):
return _load_backtest_analysis_data(backtest_dir, "signals")
def _process_candles_and_indicators(pairlist, strategy_name, trades, signal_candles):
@@ -43,9 +53,7 @@ def _process_candles_and_indicators(pairlist, strategy_name, trades, signal_cand
for pair in pairlist:
if pair in signal_candles[strategy_name]:
analysed_trades_dict[strategy_name][pair] = _analyze_candles_and_indicators(
pair,
trades,
signal_candles[strategy_name][pair])
pair, trades, signal_candles[strategy_name][pair])
except Exception as e:
print(f"Cannot process entry/exit reasons for {strategy_name}: ", e)
@@ -85,7 +93,7 @@ def _analyze_candles_and_indicators(pair, trades: pd.DataFrame, signal_candles:
return pd.DataFrame()
def _do_group_table_output(bigdf, glist):
def _do_group_table_output(bigdf, glist, csv_path: Path, to_csv=False, ):
for g in glist:
# 0: summary wins/losses grouped by enter tag
if g == "0":
@@ -116,7 +124,8 @@ def _do_group_table_output(bigdf, glist):
sortcols = ['total_num_buys']
_print_table(new, sortcols, show_index=True)
_print_table(new, sortcols, show_index=True, name="Group 0:",
to_csv=to_csv, csv_path=csv_path)
else:
agg_mask = {'profit_abs': ['count', 'sum', 'median', 'mean'],
@@ -154,11 +163,24 @@ def _do_group_table_output(bigdf, glist):
new['mean_profit_pct'] = new['mean_profit_pct'] * 100
new['total_profit_pct'] = new['total_profit_pct'] * 100
_print_table(new, sortcols)
_print_table(new, sortcols, name=f"Group {g}:",
to_csv=to_csv, csv_path=csv_path)
else:
logger.warning("Invalid group mask specified.")
def _do_rejected_signals_output(rejected_signals_df: pd.DataFrame,
to_csv: bool = False, csv_path=None) -> None:
cols = ['pair', 'date', 'enter_tag']
sortcols = ['date', 'pair', 'enter_tag']
_print_table(rejected_signals_df[cols],
sortcols,
show_index=False,
name="Rejected Signals:",
to_csv=to_csv,
csv_path=csv_path)
def _select_rows_within_dates(df, timerange=None, df_date_col: str = 'date'):
if timerange:
if timerange.starttype == 'date':
@@ -192,38 +214,64 @@ def prepare_results(analysed_trades, stratname,
return res_df
def print_results(res_df, analysis_groups, indicator_list):
def print_results(res_df: pd.DataFrame, analysis_groups: List[str], indicator_list: List[str],
csv_path: Path, rejected_signals=None, to_csv=False):
if res_df.shape[0] > 0:
if analysis_groups:
_do_group_table_output(res_df, analysis_groups)
_do_group_table_output(res_df, analysis_groups, to_csv=to_csv, csv_path=csv_path)
if rejected_signals is not None:
if rejected_signals.empty:
print("There were no rejected signals.")
else:
_do_rejected_signals_output(rejected_signals, to_csv=to_csv, csv_path=csv_path)
# NB this can be large for big dataframes!
if "all" in indicator_list:
print(res_df)
elif indicator_list is not None:
_print_table(res_df,
show_index=False,
name="Indicators:",
to_csv=to_csv,
csv_path=csv_path)
elif indicator_list is not None and indicator_list:
available_inds = []
for ind in indicator_list:
if ind in res_df:
available_inds.append(ind)
ilist = ["pair", "enter_reason", "exit_reason"] + available_inds
_print_table(res_df[ilist], sortcols=['exit_reason'], show_index=False)
_print_table(res_df[ilist],
sortcols=['exit_reason'],
show_index=False,
name="Indicators:",
to_csv=to_csv,
csv_path=csv_path)
else:
print("\\No trades to show")
def _print_table(df, sortcols=None, show_index=False):
def _print_table(df: pd.DataFrame, sortcols=None, *, show_index=False, name=None,
to_csv=False, csv_path: Path):
if (sortcols is not None):
data = df.sort_values(sortcols)
else:
data = df
print(
tabulate(
data,
headers='keys',
tablefmt='psql',
showindex=show_index
if to_csv:
safe_name = Path(csv_path, name.lower().replace(" ", "_").replace(":", "") + ".csv")
data.to_csv(safe_name)
print(f"Saved {name} to {safe_name}")
else:
if name is not None:
print(name)
print(
tabulate(
data,
headers='keys',
tablefmt='psql',
showindex=show_index
)
)
)
def process_entry_exit_reasons(config: Config):
@@ -232,6 +280,11 @@ def process_entry_exit_reasons(config: Config):
enter_reason_list = config.get('enter_reason_list', ["all"])
exit_reason_list = config.get('exit_reason_list', ["all"])
indicator_list = config.get('indicator_list', [])
do_rejected = config.get('analysis_rejected', False)
to_csv = config.get('analysis_to_csv', False)
csv_path = Path(config.get('analysis_csv_path', config['exportfilename']))
if to_csv and not csv_path.is_dir():
raise OperationalException(f"Specified directory {csv_path} does not exist.")
timerange = TimeRange.parse_timerange(None if config.get(
'timerange') is None else str(config.get('timerange')))
@@ -241,8 +294,16 @@ def process_entry_exit_reasons(config: Config):
for strategy_name, results in backtest_stats['strategy'].items():
trades = load_backtest_data(config['exportfilename'], strategy_name)
if not trades.empty:
if trades is not None and not trades.empty:
signal_candles = _load_signal_candles(config['exportfilename'])
rej_df = None
if do_rejected:
rejected_signals_dict = _load_rejected_signals(config['exportfilename'])
rej_df = prepare_results(rejected_signals_dict, strategy_name,
enter_reason_list, exit_reason_list,
timerange=timerange)
analysed_trades_dict = _process_candles_and_indicators(
config['exchange']['pair_whitelist'], strategy_name,
trades, signal_candles)
@@ -253,7 +314,10 @@ def process_entry_exit_reasons(config: Config):
print_results(res_df,
analysis_groups,
indicator_list)
indicator_list,
rejected_signals=rej_df,
to_csv=to_csv,
csv_path=csv_path)
except ValueError as e:
raise OperationalException(e) from e

View File

@@ -6,7 +6,7 @@ Includes:
* download data from exchange and store to disk
"""
# flake8: noqa: F401
from .history_utils import (convert_trades_to_ohlcv, get_timerange, load_data, load_pair_history,
refresh_backtest_ohlcv_data, refresh_backtest_trades_data, refresh_data,
validate_backtest_data)
from .history_utils import (convert_trades_to_ohlcv, download_data_main, get_timerange, load_data,
load_pair_history, refresh_backtest_ohlcv_data,
refresh_backtest_trades_data, refresh_data, validate_backtest_data)
from .idatahandler import get_datahandler

View File

@@ -63,10 +63,7 @@ class FeatherDataHandler(IDataHandler):
pairdata.columns = self._columns
pairdata = pairdata.astype(dtype={'open': 'float', 'high': 'float',
'low': 'float', 'close': 'float', 'volume': 'float'})
pairdata['date'] = to_datetime(pairdata['date'],
unit='ms',
utc=True,
infer_datetime_format=True)
pairdata['date'] = to_datetime(pairdata['date'], unit='ms', utc=True)
return pairdata
def ohlcv_append(

View File

@@ -1,14 +1,13 @@
import logging
import operator
from datetime import datetime
from datetime import datetime, timedelta
from pathlib import Path
from typing import Dict, List, Optional, Tuple
import arrow
from pandas import DataFrame, concat
from freqtrade.configuration import TimeRange
from freqtrade.constants import DEFAULT_DATAFRAME_COLUMNS
from freqtrade.constants import DATETIME_PRINT_FORMAT, DEFAULT_DATAFRAME_COLUMNS, Config
from freqtrade.data.converter import (clean_ohlcv_dataframe, ohlcv_to_dataframe,
trades_remove_duplicates, trades_to_ohlcv)
from freqtrade.data.history.idatahandler import IDataHandler, get_datahandler
@@ -16,6 +15,8 @@ from freqtrade.enums import CandleType
from freqtrade.exceptions import OperationalException
from freqtrade.exchange import Exchange
from freqtrade.misc import format_ms_time
from freqtrade.plugins.pairlist.pairlist_helpers import dynamic_expand_pairlist
from freqtrade.util.binance_mig import migrate_binance_futures_data
logger = logging.getLogger(__name__)
@@ -228,16 +229,18 @@ def _download_pair_history(pair: str, *,
)
logger.debug("Current Start: %s",
f"{data.iloc[0]['date']:DATETIME_PRINT_FORMAT}" if not data.empty else 'None')
f"{data.iloc[0]['date']:{DATETIME_PRINT_FORMAT}}"
if not data.empty else 'None')
logger.debug("Current End: %s",
f"{data.iloc[-1]['date']:DATETIME_PRINT_FORMAT}" if not data.empty else 'None')
f"{data.iloc[-1]['date']:{DATETIME_PRINT_FORMAT}}"
if not data.empty else 'None')
# Default since_ms to 30 days if nothing is given
new_data = exchange.get_historic_ohlcv(pair=pair,
timeframe=timeframe,
since_ms=since_ms if since_ms else
arrow.utcnow().shift(
days=-new_pairs_days).int_timestamp * 1000,
int((datetime.now() - timedelta(days=new_pairs_days)
).timestamp()) * 1000,
is_new_pair=data.empty,
candle_type=candle_type,
until_ms=until_ms if until_ms else None
@@ -253,10 +256,12 @@ def _download_pair_history(pair: str, *,
data = clean_ohlcv_dataframe(concat([data, new_dataframe], axis=0), timeframe, pair,
fill_missing=False, drop_incomplete=False)
logger.debug("New Start: %s",
f"{data.iloc[0]['date']:DATETIME_PRINT_FORMAT}" if not data.empty else 'None')
logger.debug("New Start: %s",
f"{data.iloc[0]['date']:{DATETIME_PRINT_FORMAT}}"
if not data.empty else 'None')
logger.debug("New End: %s",
f"{data.iloc[-1]['date']:DATETIME_PRINT_FORMAT}" if not data.empty else 'None')
f"{data.iloc[-1]['date']:{DATETIME_PRINT_FORMAT}}"
if not data.empty else 'None')
data_handler.ohlcv_store(pair, timeframe, data=data, candle_type=candle_type)
return True
@@ -291,7 +296,7 @@ def refresh_backtest_ohlcv_data(exchange: Exchange, pairs: List[str], timeframes
continue
for timeframe in timeframes:
logger.info(f'Downloading pair {pair}, interval {timeframe}.')
logger.debug(f'Downloading pair {pair}, {candle_type}, interval {timeframe}.')
process = f'{idx}/{len(pairs)}'
_download_pair_history(pair=pair, process=process,
datadir=datadir, exchange=exchange,
@@ -349,7 +354,7 @@ def _download_trades_history(exchange: Exchange,
trades = []
if not since:
since = arrow.utcnow().shift(days=-new_pairs_days).int_timestamp * 1000
since = int((datetime.now() - timedelta(days=-new_pairs_days)).timestamp()) * 1000
from_id = trades[-1][1] if trades else None
if trades and since < trades[-1][0]:
@@ -480,3 +485,77 @@ def validate_backtest_data(data: DataFrame, pair: str, min_date: datetime,
logger.warning("%s has missing frames: expected %s, got %s, that's %s missing values",
pair, expected_frames, dflen, expected_frames - dflen)
return found_missing
def download_data_main(config: Config) -> None:
timerange = TimeRange()
if 'days' in config:
time_since = (datetime.now() - timedelta(days=config['days'])).strftime("%Y%m%d")
timerange = TimeRange.parse_timerange(f'{time_since}-')
if 'timerange' in config:
timerange = timerange.parse_timerange(config['timerange'])
# Remove stake-currency to skip checks which are not relevant for datadownload
config['stake_currency'] = ''
pairs_not_available: List[str] = []
# Init exchange
from freqtrade.resolvers.exchange_resolver import ExchangeResolver
exchange = ExchangeResolver.load_exchange(config, validate=False)
available_pairs = [
p for p in exchange.get_markets(
tradable_only=True, active_only=not config.get('include_inactive')
).keys()
]
expanded_pairs = dynamic_expand_pairlist(config, available_pairs)
# Manual validations of relevant settings
if not config['exchange'].get('skip_pair_validation', False):
exchange.validate_pairs(expanded_pairs)
logger.info(f"About to download pairs: {expanded_pairs}, "
f"intervals: {config['timeframes']} to {config['datadir']}")
for timeframe in config['timeframes']:
exchange.validate_timeframes(timeframe)
# Start downloading
try:
if config.get('download_trades'):
if config.get('trading_mode') == 'futures':
raise OperationalException("Trade download not supported for futures.")
pairs_not_available = refresh_backtest_trades_data(
exchange, pairs=expanded_pairs, datadir=config['datadir'],
timerange=timerange, new_pairs_days=config['new_pairs_days'],
erase=bool(config.get('erase')), data_format=config['dataformat_trades'])
# Convert downloaded trade data to different timeframes
convert_trades_to_ohlcv(
pairs=expanded_pairs, timeframes=config['timeframes'],
datadir=config['datadir'], timerange=timerange, erase=bool(config.get('erase')),
data_format_ohlcv=config['dataformat_ohlcv'],
data_format_trades=config['dataformat_trades'],
)
else:
if not exchange.get_option('ohlcv_has_history', True):
raise OperationalException(
f"Historic klines not available for {exchange.name}. "
"Please use `--dl-trades` instead for this exchange "
"(will unfortunately take a long time)."
)
migrate_binance_futures_data(config)
pairs_not_available = refresh_backtest_ohlcv_data(
exchange, pairs=expanded_pairs, timeframes=config['timeframes'],
datadir=config['datadir'], timerange=timerange,
new_pairs_days=config['new_pairs_days'],
erase=bool(config.get('erase')), data_format=config['dataformat_ohlcv'],
trading_mode=config.get('trading_mode', 'spot'),
prepend=config.get('prepend_data', False)
)
finally:
if pairs_not_available:
logger.info(f"Pairs [{','.join(pairs_not_available)}] not available "
f"on exchange {exchange.name}.")

View File

@@ -75,10 +75,7 @@ class JsonDataHandler(IDataHandler):
return DataFrame(columns=self._columns)
pairdata = pairdata.astype(dtype={'open': 'float', 'high': 'float',
'low': 'float', 'close': 'float', 'volume': 'float'})
pairdata['date'] = to_datetime(pairdata['date'],
unit='ms',
utc=True,
infer_datetime_format=True)
pairdata['date'] = to_datetime(pairdata['date'], unit='ms', utc=True)
return pairdata
def ohlcv_append(

View File

@@ -62,10 +62,7 @@ class ParquetDataHandler(IDataHandler):
pairdata.columns = self._columns
pairdata = pairdata.astype(dtype={'open': 'float', 'high': 'float',
'low': 'float', 'close': 'float', 'volume': 'float'})
pairdata['date'] = to_datetime(pairdata['date'],
unit='ms',
utc=True,
infer_datetime_format=True)
pairdata['date'] = to_datetime(pairdata['date'], unit='ms', utc=True)
return pairdata
def ohlcv_append(

View File

@@ -3,9 +3,9 @@
import logging
from collections import defaultdict
from copy import deepcopy
from datetime import timedelta
from typing import Any, Dict, List, NamedTuple
import arrow
import numpy as np
import utils_find_1st as utf1st
from pandas import DataFrame
@@ -18,6 +18,7 @@ from freqtrade.exceptions import OperationalException
from freqtrade.exchange import timeframe_to_seconds
from freqtrade.plugins.pairlist.pairlist_helpers import expand_pairlist
from freqtrade.strategy.interface import IStrategy
from freqtrade.util import dt_now
logger = logging.getLogger(__name__)
@@ -79,8 +80,8 @@ class Edge:
self._stoploss_range_step
)
self._timerange: TimeRange = TimeRange.parse_timerange("%s-" % arrow.now().shift(
days=-1 * self._since_number_of_days).format('YYYYMMDD'))
self._timerange: TimeRange = TimeRange.parse_timerange(
f"{(dt_now() - timedelta(days=self._since_number_of_days)).strftime('%Y%m%d')}-")
if config.get('fee'):
self.fee = config['fee']
else:
@@ -97,7 +98,7 @@ class Edge:
heartbeat = self.edge_config.get('process_throttle_secs')
if (self._last_updated > 0) and (
self._last_updated + heartbeat > arrow.utcnow().int_timestamp):
self._last_updated + heartbeat > int(dt_now().timestamp())):
return False
data: Dict[str, Any] = {}
@@ -189,7 +190,7 @@ class Edge:
# Fill missing, calculable columns, profit, duration , abs etc.
trades_df = self._fill_calculable_fields(DataFrame(trades))
self._cached_pairs = self._process_expectancy(trades_df)
self._last_updated = arrow.utcnow().int_timestamp
self._last_updated = int(dt_now().timestamp())
return True

View File

@@ -15,6 +15,7 @@ class ExitType(Enum):
EMERGENCY_EXIT = "emergency_exit"
CUSTOM_EXIT = "custom_exit"
PARTIAL_EXIT = "partial_exit"
SOLD_ON_EXCHANGE = "sold_on_exchange"
NONE = ""
def __str__(self):

View File

@@ -1,7 +1,7 @@
from enum import Enum
class MarginMode(Enum):
class MarginMode(str, Enum):
"""
Enum to distinguish between
cross margin/futures margin_mode and

View File

@@ -1,22 +1,23 @@
# flake8: noqa: F401
# isort: off
from freqtrade.exchange.common import remove_credentials, MAP_EXCHANGE_CHILDCLASS
from freqtrade.exchange.common import remove_exchange_credentials, MAP_EXCHANGE_CHILDCLASS
from freqtrade.exchange.exchange import Exchange
# isort: on
from freqtrade.exchange.binance import Binance
from freqtrade.exchange.bitpanda import Bitpanda
from freqtrade.exchange.bittrex import Bittrex
from freqtrade.exchange.bitvavo import Bitvavo
from freqtrade.exchange.bybit import Bybit
from freqtrade.exchange.coinbasepro import Coinbasepro
from freqtrade.exchange.exchange_utils import (amount_to_contract_precision, amount_to_contracts,
amount_to_precision, available_exchanges,
ccxt_exchanges, contracts_to_amount,
date_minus_candles, is_exchange_known_ccxt,
from freqtrade.exchange.exchange_utils import (ROUND_DOWN, ROUND_UP, amount_to_contract_precision,
amount_to_contracts, amount_to_precision,
available_exchanges, ccxt_exchanges,
contracts_to_amount, date_minus_candles,
is_exchange_known_ccxt, list_available_exchanges,
market_is_active, price_to_precision,
timeframe_to_minutes, timeframe_to_msecs,
timeframe_to_next_date, timeframe_to_prev_date,
timeframe_to_seconds, validate_exchange,
validate_exchanges)
timeframe_to_seconds, validate_exchange)
from freqtrade.exchange.gate import Gate
from freqtrade.exchange.hitbtc import Hitbtc
from freqtrade.exchange.huobi import Huobi

View File

@@ -1,10 +1,9 @@
""" Binance exchange subclass """
import logging
from datetime import datetime
from datetime import datetime, timezone
from pathlib import Path
from typing import Dict, List, Optional, Tuple
import arrow
import ccxt
from freqtrade.enums import CandleType, MarginMode, PriceType, TradingMode
@@ -66,7 +65,7 @@ class Binance(Exchange):
"""
try:
if self.trading_mode == TradingMode.FUTURES and not self._config['dry_run']:
position_side = self._api.fapiPrivateGetPositionsideDual()
position_side = self._api.fapiPrivateGetPositionSideDual()
self._log_exchange_response('position_side_setting', position_side)
assets_margin = self._api.fapiPrivateGetMultiAssetsMargin()
self._log_exchange_response('multi_asset_margin', assets_margin)
@@ -105,8 +104,9 @@ class Binance(Exchange):
if x and x[3] and x[3][0] and x[3][0][0] > since_ms:
# Set starting date to first available candle.
since_ms = x[3][0][0]
logger.info(f"Candle-data for {pair} available starting with "
f"{arrow.get(since_ms // 1000).isoformat()}.")
logger.info(
f"Candle-data for {pair} available starting with "
f"{datetime.fromtimestamp(since_ms // 1000, tz=timezone.utc).isoformat()}.")
return await super()._async_get_historic_ohlcv(
pair=pair,

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
"""Kucoin exchange subclass."""
import logging
from typing import Dict
from freqtrade.exchange import Exchange
logger = logging.getLogger(__name__)
class Bitvavo(Exchange):
"""Bitvavo 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.
"""
_ft_has: Dict = {
"ohlcv_candle_limit": 1440,
}

View File

@@ -4,6 +4,7 @@ import time
from functools import wraps
from typing import Any, Callable, Optional, TypeVar, cast, overload
from freqtrade.constants import ExchangeConfig
from freqtrade.exceptions import DDosProtection, RetryableOrderError, TemporaryError
from freqtrade.mixins import LoggingMixin
@@ -84,20 +85,22 @@ EXCHANGE_HAS_OPTIONAL = [
# 'fetchPositions', # Futures trading
# 'fetchLeverageTiers', # Futures initialization
# 'fetchMarketLeverageTiers', # Futures initialization
# 'fetchOpenOrders', 'fetchClosedOrders', # 'fetchOrders', # Refinding balance...
]
def remove_credentials(config) -> None:
def remove_exchange_credentials(exchange_config: ExchangeConfig, dry_run: bool) -> None:
"""
Removes exchange keys from the configuration and specifies dry-run
Used for backtesting / hyperopt / edge and utils.
Modifies the input dict!
"""
if config.get('dry_run', False):
config['exchange']['key'] = ''
config['exchange']['secret'] = ''
config['exchange']['password'] = ''
config['exchange']['uid'] = ''
if dry_run:
exchange_config['key'] = ''
exchange_config['apiKey'] = ''
exchange_config['secret'] = ''
exchange_config['password'] = ''
exchange_config['uid'] = ''
def calculate_backoff(retrycount, max_retries):

View File

@@ -11,7 +11,6 @@ from math import floor
from threading import Lock
from typing import Any, Coroutine, Dict, List, Literal, Optional, Tuple, Union
import arrow
import ccxt
import ccxt.async_support as ccxt_async
from cachetools import TTLCache
@@ -20,27 +19,30 @@ from dateutil import parser
from pandas import DataFrame, concat
from freqtrade.constants import (DEFAULT_AMOUNT_RESERVE_PERCENT, NON_OPEN_EXCHANGE_STATES, BidAsk,
BuySell, Config, EntryExit, ListPairsWithTimeframes, MakerTaker,
OBLiteral, PairWithTimeframe)
BuySell, Config, EntryExit, ExchangeConfig,
ListPairsWithTimeframes, MakerTaker, 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)
from freqtrade.exchange.common import (API_FETCH_ORDER_RETRY_COUNT, remove_credentials, retrier,
retrier_async)
from freqtrade.exchange.exchange_utils import (CcxtModuleType, amount_to_contract_precision,
amount_to_contracts, amount_to_precision,
contracts_to_amount, date_minus_candles,
is_exchange_known_ccxt, market_is_active,
price_to_precision, timeframe_to_minutes,
timeframe_to_msecs, timeframe_to_next_date,
timeframe_to_prev_date, timeframe_to_seconds)
from freqtrade.exchange.common import (API_FETCH_ORDER_RETRY_COUNT, remove_exchange_credentials,
retrier, retrier_async)
from freqtrade.exchange.exchange_utils import (ROUND, ROUND_DOWN, ROUND_UP, CcxtModuleType,
amount_to_contract_precision, amount_to_contracts,
amount_to_precision, contracts_to_amount,
date_minus_candles, is_exchange_known_ccxt,
market_is_active, 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 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
from freqtrade.util import dt_from_ts, dt_now
from freqtrade.util.datetime_helpers import dt_humanize, dt_ts
logger = logging.getLogger(__name__)
@@ -59,6 +61,7 @@ class Exchange:
# or by specifying them in the configuration.
_ft_has_default: Dict = {
"stoploss_on_exchange": False,
"stop_price_param": "stopPrice",
"order_time_in_force": ["GTC"],
"ohlcv_params": {},
"ohlcv_candle_limit": 500,
@@ -90,8 +93,8 @@ class Exchange:
# TradingMode.SPOT always supported and not required in this list
]
def __init__(self, config: Config, validate: bool = True,
load_leverage_tiers: bool = False) -> None:
def __init__(self, config: Config, *, exchange_config: Optional[ExchangeConfig] = None,
validate: bool = True, load_leverage_tiers: bool = False) -> None:
"""
Initializes this module with the given config,
it does basic validation whether the specified exchange and pairs are valid.
@@ -105,8 +108,7 @@ class Exchange:
# Lock event loop. This is necessary to avoid race-conditions when using force* commands
# Due to funding fee fetching.
self._loop_lock = Lock()
self.loop = asyncio.new_event_loop()
asyncio.set_event_loop(self.loop)
self.loop = self._init_async_loop()
self._config: Config = {}
self._config.update(config)
@@ -130,13 +132,13 @@ class Exchange:
# Holds all open sell orders for dry_run
self._dry_run_open_orders: Dict[str, Any] = {}
remove_credentials(config)
if config['dry_run']:
logger.info('Instance is running with dry_run enabled')
logger.info(f"Using CCXT {ccxt.__version__}")
exchange_config = config['exchange']
self.log_responses = exchange_config.get('log_responses', False)
exchange_conf: Dict[str, Any] = exchange_config if exchange_config else config['exchange']
remove_exchange_credentials(exchange_conf, config.get('dry_run', False))
self.log_responses = exchange_conf.get('log_responses', False)
# Leverage properties
self.trading_mode: TradingMode = config.get('trading_mode', TradingMode.SPOT)
@@ -151,8 +153,8 @@ class Exchange:
self._ft_has = deep_merge_dicts(self._ft_has, deepcopy(self._ft_has_default))
if self.trading_mode == TradingMode.FUTURES:
self._ft_has = deep_merge_dicts(self._ft_has_futures, self._ft_has)
if exchange_config.get('_ft_has_params'):
self._ft_has = deep_merge_dicts(exchange_config.get('_ft_has_params'),
if exchange_conf.get('_ft_has_params'):
self._ft_has = deep_merge_dicts(exchange_conf.get('_ft_has_params'),
self._ft_has)
logger.info("Overriding exchange._ft_has with config params, result: %s", self._ft_has)
@@ -164,18 +166,18 @@ class Exchange:
# Initialize ccxt objects
ccxt_config = self._ccxt_config
ccxt_config = deep_merge_dicts(exchange_config.get('ccxt_config', {}), ccxt_config)
ccxt_config = deep_merge_dicts(exchange_config.get('ccxt_sync_config', {}), ccxt_config)
ccxt_config = deep_merge_dicts(exchange_conf.get('ccxt_config', {}), ccxt_config)
ccxt_config = deep_merge_dicts(exchange_conf.get('ccxt_sync_config', {}), ccxt_config)
self._api = self._init_ccxt(exchange_config, ccxt_kwargs=ccxt_config)
self._api = self._init_ccxt(exchange_conf, ccxt_kwargs=ccxt_config)
ccxt_async_config = self._ccxt_config
ccxt_async_config = deep_merge_dicts(exchange_config.get('ccxt_config', {}),
ccxt_async_config = deep_merge_dicts(exchange_conf.get('ccxt_config', {}),
ccxt_async_config)
ccxt_async_config = deep_merge_dicts(exchange_config.get('ccxt_async_config', {}),
ccxt_async_config = deep_merge_dicts(exchange_conf.get('ccxt_async_config', {}),
ccxt_async_config)
self._api_async = self._init_ccxt(
exchange_config, ccxt_async, ccxt_kwargs=ccxt_async_config)
exchange_conf, ccxt_async, ccxt_kwargs=ccxt_async_config)
logger.info(f'Using Exchange "{self.name}"')
self.required_candle_call_count = 1
@@ -188,8 +190,8 @@ class Exchange:
self._startup_candle_count, config.get('timeframe', ''))
# Converts the interval provided in minutes in config to seconds
self.markets_refresh_interval: int = exchange_config.get(
"markets_refresh_interval", 60) * 60
self.markets_refresh_interval: int = exchange_conf.get(
"markets_refresh_interval", 60) * 60 * 1000
if self.trading_mode != TradingMode.SPOT and load_leverage_tiers:
self.fill_leverage_tiers()
@@ -210,6 +212,11 @@ class Exchange:
if self.loop and not self.loop.is_closed():
self.loop.close()
def _init_async_loop(self) -> asyncio.AbstractEventLoop:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
return loop
def validate_config(self, config):
# Check if timeframe is available
self.validate_timeframes(config.get('timeframe'))
@@ -294,7 +301,7 @@ class Exchange:
return list((self._api.timeframes or {}).keys())
@property
def markets(self) -> Dict:
def markets(self) -> Dict[str, Any]:
"""exchange ccxt markets"""
if not self._markets:
logger.info("Markets were not loaded. Loading them now..")
@@ -484,7 +491,7 @@ class Exchange:
try:
self._markets = self._api.load_markets(params={})
self._load_async_markets()
self._last_markets_refresh = arrow.utcnow().int_timestamp
self._last_markets_refresh = dt_ts()
if self._ft_has['needs_trading_fees']:
self._trading_fees = self.fetch_trading_fees()
@@ -495,15 +502,14 @@ class Exchange:
"""Reload markets both sync and async if refresh interval has passed """
# Check whether markets have to be reloaded
if (self._last_markets_refresh > 0) and (
self._last_markets_refresh + self.markets_refresh_interval
> arrow.utcnow().int_timestamp):
self._last_markets_refresh + self.markets_refresh_interval > dt_ts()):
return None
logger.debug("Performing scheduled market reload..")
try:
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
self._last_markets_refresh = dt_ts()
self.fill_leverage_tiers()
except ccxt.BaseError:
logger.exception("Could not reload markets.")
@@ -734,12 +740,14 @@ class Exchange:
"""
return amount_to_precision(amount, self.get_precision_amount(pair), self.precisionMode)
def price_to_precision(self, pair: str, price: float) -> float:
def price_to_precision(self, pair: str, price: float, *, rounding_mode: int = ROUND) -> float:
"""
Returns the price rounded up to the precision the Exchange accepts.
Rounds up
Returns the price rounded to the precision the Exchange accepts.
The default price_rounding_mode in conf is ROUND.
For stoploss calculations, must use ROUND_UP for longs, and ROUND_DOWN for shorts.
"""
return price_to_precision(price, self.get_precision_price(pair), self.precisionMode)
return price_to_precision(price, self.get_precision_price(pair),
self.precisionMode, rounding_mode=rounding_mode)
def price_get_one_pip(self, pair: str, price: float) -> float:
"""
@@ -762,12 +770,12 @@ class Exchange:
return self._get_stake_amount_limit(pair, price, stoploss, 'min', leverage)
def get_max_pair_stake_amount(self, pair: str, price: float, leverage: float = 1.0) -> float:
max_stake_amount = self._get_stake_amount_limit(pair, price, 0.0, 'max')
max_stake_amount = self._get_stake_amount_limit(pair, price, 0.0, 'max', leverage)
if max_stake_amount is None:
# * Should never be executed
raise OperationalException(f'{self.name}.get_max_pair_stake_amount should'
'never set max_stake_amount to None')
return max_stake_amount / leverage
return max_stake_amount
def _get_stake_amount_limit(
self,
@@ -785,43 +793,41 @@ class Exchange:
except KeyError:
raise ValueError(f"Can't get market information for symbol {pair}")
if isMin:
# reserve some percent defined in config (5% default) + stoploss
margin_reserve: float = 1.0 + self._config.get('amount_reserve_percent',
DEFAULT_AMOUNT_RESERVE_PERCENT)
stoploss_reserve = (
margin_reserve / (1 - abs(stoploss)) if abs(stoploss) != 1 else 1.5
)
# it should not be more than 50%
stoploss_reserve = max(min(stoploss_reserve, 1.5), 1)
else:
margin_reserve = 1.0
stoploss_reserve = 1.0
stake_limits = []
limits = market['limits']
if (limits['cost'][limit] is not None):
stake_limits.append(
self._contracts_to_amount(
pair,
limits['cost'][limit]
)
self._contracts_to_amount(pair, limits['cost'][limit]) * stoploss_reserve
)
if (limits['amount'][limit] is not None):
stake_limits.append(
self._contracts_to_amount(
pair,
limits['amount'][limit] * price
)
self._contracts_to_amount(pair, limits['amount'][limit]) * price * margin_reserve
)
if not stake_limits:
return None if isMin else float('inf')
# reserve some percent defined in config (5% default) + stoploss
amount_reserve_percent = 1.0 + self._config.get('amount_reserve_percent',
DEFAULT_AMOUNT_RESERVE_PERCENT)
amount_reserve_percent = (
amount_reserve_percent / (1 - abs(stoploss)) if abs(stoploss) != 1 else 1.5
)
# it should not be more than 50%
amount_reserve_percent = max(min(amount_reserve_percent, 1.5), 1)
# The value returned should satisfy both limits: for amount (base currency) and
# for cost (quote, stake currency), so max() is used here.
# See also #2575 at github.
return self._get_stake_amount_considering_leverage(
max(stake_limits) * amount_reserve_percent,
max(stake_limits) if isMin else min(stake_limits),
leverage or 1.0
) if isMin else min(stake_limits)
)
def _get_stake_amount_considering_leverage(self, stake_amount: float, leverage: float) -> float:
"""
@@ -837,7 +843,8 @@ class Exchange:
def create_dry_run_order(self, pair: str, ordertype: str, side: str, amount: float,
rate: float, leverage: float, params: Dict = {},
stop_loss: bool = False) -> Dict[str, Any]:
order_id = f'dry_run_{side}_{datetime.now().timestamp()}'
now = dt_now()
order_id = f'dry_run_{side}_{now.timestamp()}'
# Rounding here must respect to contract sizes
_amount = self._contracts_to_amount(
pair, self.amount_to_precision(pair, self._amount_to_contracts(pair, amount)))
@@ -852,8 +859,8 @@ class Exchange:
'side': side,
'filled': 0,
'remaining': _amount,
'datetime': arrow.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ'),
'timestamp': arrow.utcnow().int_timestamp * 1000,
'datetime': now.strftime('%Y-%m-%dT%H:%M:%S.%fZ'),
'timestamp': dt_ts(now),
'status': "open",
'fee': None,
'info': {},
@@ -861,7 +868,7 @@ class Exchange:
}
if stop_loss:
dry_order["info"] = {"stopPrice": dry_order["price"]}
dry_order["stopPrice"] = dry_order["price"]
dry_order[self._ft_has['stop_price_param']] = dry_order["price"]
# Workaround to avoid filling stoploss orders immediately
dry_order["ft_order_type"] = "stoploss"
orderbook: Optional[OrderBook] = None
@@ -884,7 +891,7 @@ class Exchange:
'filled': _amount,
'remaining': 0.0,
'status': "closed",
'cost': (dry_order['amount'] * average) / leverage
'cost': (dry_order['amount'] * average)
})
# market orders will always incurr taker fees
dry_order = self.add_dry_order_fee(pair, dry_order, 'taker')
@@ -1013,7 +1020,7 @@ class Exchange:
from freqtrade.persistence import Order
order = Order.order_by_id(order_id)
if order:
ccxt_order = order.to_ccxt_object()
ccxt_order = order.to_ccxt_object(self._ft_has['stop_price_param'])
self._dry_run_open_orders[order_id] = ccxt_order
return ccxt_order
# Gracefully handle errors with dry-run orders.
@@ -1114,11 +1121,11 @@ class Exchange:
"""
if not self._ft_has.get('stoploss_on_exchange'):
raise OperationalException(f"stoploss is not implemented for {self.name}.")
price_param = self._ft_has['stop_price_param']
return (
order.get('stopPrice', None) is None
or ((side == "sell" and stop_loss > float(order['stopPrice'])) or
(side == "buy" and stop_loss < float(order['stopPrice'])))
order.get(price_param, None) is None
or ((side == "sell" and stop_loss > float(order[price_param])) or
(side == "buy" and stop_loss < float(order[price_param])))
)
def _get_stop_order_type(self, user_order_type) -> Tuple[str, str]:
@@ -1141,8 +1148,8 @@ class Exchange:
else:
limit_rate = stop_price * (2 - limit_price_pct)
bad_stop_price = ((stop_price <= limit_rate) if side ==
"sell" else (stop_price >= limit_rate))
bad_stop_price = ((stop_price < limit_rate) if side ==
"sell" else (stop_price > limit_rate))
# Ensure rate is less than stop price
if bad_stop_price:
# This can for example happen if the stop / liquidation price is set to 0
@@ -1158,8 +1165,8 @@ class Exchange:
def _get_stop_params(self, side: BuySell, ordertype: str, stop_price: float) -> Dict:
params = self._params.copy()
# Verify if stopPrice works for your exchange!
params.update({'stopPrice': stop_price})
# Verify if stopPrice works for your exchange, else configure stop_price_param
params.update({self._ft_has['stop_price_param']: stop_price})
return params
@retrier(retries=0)
@@ -1185,12 +1192,12 @@ class Exchange:
user_order_type = order_types.get('stoploss', 'market')
ordertype, user_order_type = self._get_stop_order_type(user_order_type)
stop_price_norm = self.price_to_precision(pair, stop_price)
round_mode = ROUND_DOWN if side == 'buy' else ROUND_UP
stop_price_norm = self.price_to_precision(pair, stop_price, rounding_mode=round_mode)
limit_rate = None
if user_order_type == 'limit':
limit_rate = self._get_stop_limit_rate(stop_price, order_types, side)
limit_rate = self.price_to_precision(pair, limit_rate)
limit_rate = self.price_to_precision(pair, limit_rate, rounding_mode=round_mode)
if self._config['dry_run']:
dry_order = self.create_dry_run_order(
@@ -1426,6 +1433,47 @@ class Exchange:
except ccxt.BaseError as e:
raise OperationalException(e) from e
@retrier(retries=0)
def fetch_orders(self, pair: str, since: datetime) -> List[Dict]:
"""
Fetch all orders for a pair "since"
:param pair: Pair for the query
:param since: Starting time for the query
"""
if self._config['dry_run']:
return []
def fetch_orders_emulate() -> List[Dict]:
orders = []
if self.exchange_has('fetchClosedOrders'):
orders = self._api.fetch_closed_orders(pair, since=since_ms)
if self.exchange_has('fetchOpenOrders'):
orders_open = self._api.fetch_open_orders(pair, since=since_ms)
orders.extend(orders_open)
return orders
try:
since_ms = int((since.timestamp() - 10) * 1000)
if self.exchange_has('fetchOrders'):
try:
orders: List[Dict] = self._api.fetch_orders(pair, since=since_ms)
except ccxt.NotSupported:
# Some exchanges don't support fetchOrders
# attempt to fetch open and closed orders separately
orders = fetch_orders_emulate()
else:
orders = fetch_orders_emulate()
self._log_exchange_response('fetch_orders', orders)
orders = [self._order_contracts_to_amount(o) for o in orders]
return orders
except ccxt.DDoSProtection as e:
raise DDosProtection(e) from e
except (ccxt.NetworkError, ccxt.ExchangeError) as e:
raise TemporaryError(
f'Could not fetch positions due to {e.__class__.__name__}. Message: {e}') from e
except ccxt.BaseError as e:
raise OperationalException(e) from e
@retrier
def fetch_trading_fees(self) -> Dict[str, Any]:
"""
@@ -1614,39 +1662,18 @@ class Exchange:
price_side = self._get_price_side(side, is_short, conf_strategy)
price_side_word = price_side.capitalize()
if conf_strategy.get('use_order_book', False):
order_book_top = conf_strategy.get('order_book_top', 1)
if order_book is None:
order_book = self.fetch_l2_order_book(pair, order_book_top)
logger.debug('order_book %s', order_book)
# top 1 = index 0
try:
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 "
f"could not be determined. Orderbook: {order_book}"
)
raise PricingError from e
logger.debug(f"{pair} - {name} price from orderbook {price_side_word}"
f"side - top {order_book_top} order book {side} rate {rate:.8f}")
rate = self._get_rate_from_ob(pair, side, order_book, name, price_side,
order_book_top)
else:
logger.debug(f"Using Last {price_side_word} / Last Price")
logger.debug(f"Using Last {price_side.capitalize()} / Last Price")
if ticker is None:
ticker = self.fetch_ticker(pair)
ticker_rate = ticker[price_side]
if ticker['last'] and ticker_rate:
if side == 'entry' and ticker_rate > ticker['last']:
balance = conf_strategy.get('price_last_balance', 0.0)
ticker_rate = ticker_rate + balance * (ticker['last'] - ticker_rate)
elif side == 'exit' and ticker_rate < ticker['last']:
balance = conf_strategy.get('price_last_balance', 0.0)
ticker_rate = ticker_rate - balance * (ticker_rate - ticker['last'])
rate = ticker_rate
rate = self._get_rate_from_ticker(side, ticker, conf_strategy, price_side)
if rate is None:
raise PricingError(f"{name}-Rate for {pair} was empty.")
@@ -1655,6 +1682,43 @@ class Exchange:
return rate
def _get_rate_from_ticker(self, side: EntryExit, ticker: Ticker, conf_strategy: Dict[str, Any],
price_side: BidAsk) -> Optional[float]:
"""
Get rate from ticker.
"""
ticker_rate = ticker[price_side]
if ticker['last'] and ticker_rate:
if side == 'entry' and ticker_rate > ticker['last']:
balance = conf_strategy.get('price_last_balance', 0.0)
ticker_rate = ticker_rate + balance * (ticker['last'] - ticker_rate)
elif side == 'exit' and ticker_rate < ticker['last']:
balance = conf_strategy.get('price_last_balance', 0.0)
ticker_rate = ticker_rate - balance * (ticker_rate - ticker['last'])
rate = ticker_rate
return rate
def _get_rate_from_ob(self, pair: str, side: EntryExit, order_book: OrderBook, name: str,
price_side: BidAsk, order_book_top: int) -> float:
"""
Get rate from orderbook
:raises: PricingError if rate could not be determined.
"""
logger.debug('order_book %s', order_book)
# top 1 = index 0
try:
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 "
f"could not be determined. Orderbook: {order_book}"
)
raise PricingError from e
logger.debug(f"{pair} - {name} price from orderbook {price_side.capitalize()}"
f"side - top {order_book_top} order book {side} rate {rate:.8f}")
return rate
def get_rates(self, pair: str, refresh: bool, is_short: bool) -> Tuple[float, float]:
entry_rate = None
exit_rate = None
@@ -1883,11 +1947,11 @@ class Exchange:
logger.debug(
"one_call: %s msecs (%s)",
one_call,
arrow.utcnow().shift(seconds=one_call // 1000).humanize(only_distance=True)
dt_humanize(dt_now() - timedelta(milliseconds=one_call), only_distance=True)
)
input_coroutines = [self._async_get_candle_history(
pair, timeframe, candle_type, since) for since in
range(since_ms, until_ms or (arrow.utcnow().int_timestamp * 1000), one_call)]
range(since_ms, until_ms or dt_ts(), one_call)]
data: List = []
# Chunk requests into batches of 100 to avoid overwelming ccxt Throttling
@@ -2070,7 +2134,7 @@ class Exchange:
"""
try:
# Fetch OHLCV asynchronously
s = '(' + arrow.get(since_ms // 1000).isoformat() + ') ' if since_ms is not None else ''
s = '(' + dt_from_ts(since_ms).isoformat() + ') ' if since_ms is not None else ''
logger.debug(
"Fetching pair %s, %s, interval %s, since %s %s...",
pair, candle_type, timeframe, since_ms, s
@@ -2160,7 +2224,7 @@ class Exchange:
logger.debug(
"Fetching trades for pair %s, since %s %s...",
pair, since,
'(' + arrow.get(since // 1000).isoformat() + ') ' if since is not None else ''
'(' + dt_from_ts(since).isoformat() + ') ' if since is not None else ''
)
trades = await self._api_async.fetch_trades(pair, since=since, limit=1000)
trades = self._trades_contracts_to_amount(trades)
@@ -2369,12 +2433,12 @@ class Exchange:
# Must fetch the leverage tiers for each market separately
# * This is slow(~45s) on Okx, makes ~90 api calls to load all linear swap markets
markets = self.markets
symbols = []
for symbol, market in markets.items():
symbols = [
symbol for symbol, market in markets.items()
if (self.market_is_future(market)
and market['quote'] == self._config['stake_currency']):
symbols.append(symbol)
and market['quote'] == self._config['stake_currency'])
]
tiers: Dict[str, List[Dict]] = {}
@@ -2394,25 +2458,26 @@ class Exchange:
else:
logger.info("Using cached leverage_tiers.")
async def gather_results():
async def gather_results(input_coro):
return await asyncio.gather(*input_coro, return_exceptions=True)
for input_coro in chunks(coros, 100):
with self._loop_lock:
results = self.loop.run_until_complete(gather_results())
results = self.loop.run_until_complete(gather_results(input_coro))
for symbol, res in results:
tiers[symbol] = res
for res in results:
if isinstance(res, Exception):
logger.warning(f"Leverage tier exception: {repr(res)}")
continue
symbol, tier = res
tiers[symbol] = tier
if len(coros) > 0:
self.cache_leverage_tiers(tiers, self._config['stake_currency'])
logger.info(f"Done initializing {len(symbols)} markets.")
return tiers
else:
return {}
else:
return {}
return {}
def cache_leverage_tiers(self, tiers: Dict[str, List[Dict]], stake_currency: str) -> None:
@@ -2428,14 +2493,17 @@ class Exchange:
def load_cached_leverage_tiers(self, stake_currency: str) -> Optional[Dict[str, List[Dict]]]:
filename = self._config['datadir'] / "futures" / f"leverage_tiers_{stake_currency}.json"
if filename.is_file():
tiers = file_load_json(filename)
updated = tiers.get('updated')
if updated:
updated_dt = parser.parse(updated)
if updated_dt < datetime.now(timezone.utc) - timedelta(weeks=4):
logger.info("Cached leverage tiers are outdated. Will update.")
return None
return tiers['data']
try:
tiers = file_load_json(filename)
updated = tiers.get('updated')
if updated:
updated_dt = parser.parse(updated)
if updated_dt < datetime.now(timezone.utc) - timedelta(weeks=4):
logger.info("Cached leverage tiers are outdated. Will update.")
return None
return tiers['data']
except Exception:
logger.exception("Error loading cached leverage tiers. Refreshing.")
return None
def fill_leverage_tiers(self) -> None:
@@ -2890,8 +2958,8 @@ class Exchange:
if nominal_value >= tier['minNotional']:
return (tier['maintenanceMarginRate'], tier['maintAmt'])
raise OperationalException("nominal value can not be lower than 0")
raise ExchangeError("nominal value can not be lower than 0")
# The lowest notional_floor for any pair in fetch_leverage_tiers is always 0 because it
# describes the min amt for a tier, and the lowest tier will always go down to 0
else:
raise OperationalException(f"Cannot get maintenance ratio using {self.name}")
raise ExchangeError(f"Cannot get maintenance ratio using {self.name}")

View File

@@ -2,14 +2,18 @@
Exchange support utils
"""
from datetime import datetime, timedelta, timezone
from math import ceil
from math import ceil, floor
from typing import Any, Dict, List, Optional, Tuple
import ccxt
from ccxt import ROUND_DOWN, ROUND_UP, TICK_SIZE, TRUNCATE, decimal_to_precision
from ccxt import (DECIMAL_PLACES, ROUND, ROUND_DOWN, ROUND_UP, SIGNIFICANT_DIGITS, TICK_SIZE,
TRUNCATE, decimal_to_precision)
from freqtrade.exchange.common import BAD_EXCHANGES, EXCHANGE_HAS_OPTIONAL, EXCHANGE_HAS_REQUIRED
from freqtrade.exchange.common import (BAD_EXCHANGES, EXCHANGE_HAS_OPTIONAL, EXCHANGE_HAS_REQUIRED,
SUPPORTED_EXCHANGES)
from freqtrade.types import ValidExchangesType
from freqtrade.util import FtPrecise
from freqtrade.util.datetime_helpers import dt_from_ts, dt_ts
CcxtModuleType = Any
@@ -53,14 +57,41 @@ def validate_exchange(exchange: str) -> Tuple[bool, str]:
return True, ''
def validate_exchanges(all_exchanges: bool) -> List[Tuple[str, bool, str]]:
def _build_exchange_list_entry(
exchange_name: str, exchangeClasses: Dict[str, Any]) -> ValidExchangesType:
valid, comment = validate_exchange(exchange_name)
result: ValidExchangesType = {
'name': exchange_name,
'valid': valid,
'supported': exchange_name.lower() in SUPPORTED_EXCHANGES,
'comment': comment,
'trade_modes': [{'trading_mode': 'spot', 'margin_mode': ''}],
}
if resolved := exchangeClasses.get(exchange_name.lower()):
supported_modes = [{'trading_mode': 'spot', 'margin_mode': ''}] + [
{'trading_mode': tm.value, 'margin_mode': mm.value}
for tm, mm in resolved['class']._supported_trading_mode_margin_pairs
]
result.update({
'trade_modes': supported_modes,
})
return result
def list_available_exchanges(all_exchanges: bool) -> List[ValidExchangesType]:
"""
:return: List of tuples with exchangename, valid, reason.
"""
exchanges = ccxt_exchanges() if all_exchanges else available_exchanges()
exchanges_valid = [
(e, *validate_exchange(e)) for e in exchanges
from freqtrade.resolvers.exchange_resolver import ExchangeResolver
subclassed = {e['name'].lower(): e for e in ExchangeResolver.search_all_objects({}, False)}
exchanges_valid: List[ValidExchangesType] = [
_build_exchange_list_entry(e, subclassed) for e in exchanges
]
return exchanges_valid
@@ -98,9 +129,8 @@ def timeframe_to_prev_date(timeframe: str, date: Optional[datetime] = None) -> d
if not date:
date = datetime.now(timezone.utc)
new_timestamp = ccxt.Exchange.round_timeframe(timeframe, date.timestamp() * 1000,
ROUND_DOWN) // 1000
return datetime.fromtimestamp(new_timestamp, tz=timezone.utc)
new_timestamp = ccxt.Exchange.round_timeframe(timeframe, dt_ts(date), ROUND_DOWN) // 1000
return dt_from_ts(new_timestamp)
def timeframe_to_next_date(timeframe: str, date: Optional[datetime] = None) -> datetime:
@@ -112,9 +142,8 @@ def timeframe_to_next_date(timeframe: str, date: Optional[datetime] = None) -> d
"""
if not date:
date = datetime.now(timezone.utc)
new_timestamp = ccxt.Exchange.round_timeframe(timeframe, date.timestamp() * 1000,
ROUND_UP) // 1000
return datetime.fromtimestamp(new_timestamp, tz=timezone.utc)
new_timestamp = ccxt.Exchange.round_timeframe(timeframe, dt_ts(date), ROUND_UP) // 1000
return dt_from_ts(new_timestamp)
def date_minus_candles(
@@ -219,35 +248,51 @@ def amount_to_contract_precision(
return amount
def price_to_precision(price: float, price_precision: Optional[float],
precisionMode: Optional[int]) -> float:
def price_to_precision(
price: float,
price_precision: Optional[float],
precisionMode: Optional[int],
*,
rounding_mode: int = ROUND,
) -> float:
"""
Returns the price rounded up to the precision the Exchange accepts.
Returns the price rounded to the precision the Exchange accepts.
Partial Re-implementation of ccxt internal method decimal_to_precision(),
which does not support rounding up
which does not support rounding up.
For stoploss calculations, must use ROUND_UP for longs, and ROUND_DOWN for shorts.
TODO: If ccxt supports ROUND_UP for decimal_to_precision(), we could remove this and
align with amount_to_precision().
!!! Rounds up
:param price: price to convert
:param price_precision: price precision to use. Used from markets[pair]['precision']['price']
:param precisionMode: precision mode to use. Should be used from precisionMode
one of ccxt's DECIMAL_PLACES, SIGNIFICANT_DIGITS, or TICK_SIZE
:param rounding_mode: rounding mode to use. Defaults to ROUND
:return: price rounded up to the precision the Exchange accepts
"""
if price_precision is not None and precisionMode is not None:
# price = float(decimal_to_precision(price, rounding_mode=ROUND,
# precision=price_precision,
# counting_mode=self.precisionMode,
# ))
if precisionMode == TICK_SIZE:
if rounding_mode == ROUND:
ticks = price / price_precision
rounded_ticks = round(ticks)
return rounded_ticks * price_precision
precision = FtPrecise(price_precision)
price_str = FtPrecise(price)
missing = price_str % precision
if not missing == FtPrecise("0"):
price = round(float(str(price_str - missing + precision)), 14)
else:
symbol_prec = price_precision
big_price = price * pow(10, symbol_prec)
price = ceil(big_price) / pow(10, symbol_prec)
return round(float(str(price_str - missing + precision)), 14)
return price
elif precisionMode in (SIGNIFICANT_DIGITS, DECIMAL_PLACES):
ndigits = round(price_precision)
if rounding_mode == ROUND:
return round(price, ndigits)
ticks = price * (10**ndigits)
if rounding_mode == ROUND_UP:
return ceil(ticks) / (10**ndigits)
if rounding_mode == TRUNCATE:
return int(ticks) / (10**ndigits)
if rounding_mode == ROUND_DOWN:
return floor(ticks) / (10**ndigits)
raise ValueError(f"Unknown rounding_mode {rounding_mode}")
raise ValueError(f"Unknown precisionMode {precisionMode}")
return price

View File

@@ -33,7 +33,6 @@ class Gate(Exchange):
_ft_has_futures: Dict = {
"needs_trading_fees": True,
"marketOrderRequiresPrice": False,
"tickers_have_bid_ask": False,
"fee_cost_in_contracts": False, # Set explicitly to false for clarity
"order_props_in_contracts": ['amount', 'filled', 'remaining'],
"stop_price_type_field": "price_type",

View File

@@ -12,6 +12,7 @@ from freqtrade.exceptions import (DDosProtection, InsufficientFundsError, Invali
OperationalException, TemporaryError)
from freqtrade.exchange import Exchange
from freqtrade.exchange.common import retrier
from freqtrade.exchange.exchange_utils import ROUND_DOWN, ROUND_UP
from freqtrade.exchange.types import Tickers
@@ -109,6 +110,7 @@ class Kraken(Exchange):
if self.trading_mode == TradingMode.FUTURES:
params.update({'reduceOnly': True})
round_mode = ROUND_DOWN if side == 'buy' else ROUND_UP
if order_types.get('stoploss', 'market') == 'limit':
ordertype = "stop-loss-limit"
limit_price_pct = order_types.get('stoploss_on_exchange_limit_ratio', 0.99)
@@ -116,11 +118,11 @@ class Kraken(Exchange):
limit_rate = stop_price * limit_price_pct
else:
limit_rate = stop_price * (2 - limit_price_pct)
params['price2'] = self.price_to_precision(pair, limit_rate)
params['price2'] = self.price_to_precision(pair, limit_rate, rounding_mode=round_mode)
else:
ordertype = "stop-loss"
stop_price = self.price_to_precision(pair, stop_price)
stop_price = self.price_to_precision(pair, stop_price, rounding_mode=round_mode)
if self._config['dry_run']:
dry_order = self.create_dry_run_order(

View File

@@ -28,6 +28,7 @@ class Okx(Exchange):
"funding_fee_timeframe": "8h",
"stoploss_order_types": {"limit": "limit"},
"stoploss_on_exchange": True,
"stop_price_param": "stopLossPrice",
}
_ft_has_futures: Dict = {
"tickers_have_quoteVolume": False,
@@ -124,6 +125,20 @@ class Okx(Exchange):
params['posSide'] = self._get_posSide(side, reduceOnly)
return params
def __fetch_leverage_already_set(self, pair: str, leverage: float, side: BuySell) -> bool:
try:
res_lev = self._api.fetch_leverage(symbol=pair, params={
"mgnMode": self.margin_mode.value,
"posSide": self._get_posSide(side, False),
})
self._log_exchange_response('get_leverage', res_lev)
already_set = all(float(x['lever']) == leverage for x in res_lev['data'])
return already_set
except ccxt.BaseError:
# Assume all errors as "not set yet"
return False
@retrier
def _lev_prep(self, pair: str, leverage: float, side: BuySell, accept_fail: bool = False):
if self.trading_mode != TradingMode.SPOT and self.margin_mode is not None:
@@ -140,8 +155,11 @@ class Okx(Exchange):
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
already_set = self.__fetch_leverage_already_set(pair, leverage, side)
if not already_set:
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
@@ -162,28 +180,28 @@ class Okx(Exchange):
return pair_tiers[-1]['maxNotional'] / leverage
def _get_stop_params(self, side: BuySell, ordertype: str, stop_price: float) -> Dict:
params = self._params.copy()
# Verify if stopPrice works for your exchange!
params.update({'stopLossPrice': stop_price})
params = super()._get_stop_params(side, ordertype, stop_price)
if self.trading_mode == TradingMode.FUTURES and self.margin_mode:
params['tdMode'] = self.margin_mode.value
params['posSide'] = self._get_posSide(side, True)
return params
def stoploss_adjust(self, stop_loss: float, order: Dict, side: str) -> bool:
"""
OKX uses non-default stoploss price naming.
"""
if not self._ft_has.get('stoploss_on_exchange'):
raise OperationalException(f"stoploss is not implemented for {self.name}.")
return (
order.get('stopLossPrice', None) is None
or ((side == "sell" and stop_loss > float(order['stopLossPrice'])) or
(side == "buy" and stop_loss < float(order['stopLossPrice'])))
)
def _convert_stop_order(self, pair: str, order_id: str, order: Dict) -> Dict:
if (
order['status'] == 'closed'
and (real_order_id := order.get('info', {}).get('ordId')) is not None
):
# Once a order triggered, we fetch the regular followup order.
order_reg = self.fetch_order(real_order_id, pair)
self._log_exchange_response('fetch_stoploss_order1', order_reg)
order_reg['id_stop'] = order_reg['id']
order_reg['id'] = order_id
order_reg['type'] = 'stoploss'
order_reg['status_stop'] = 'triggered'
return order_reg
order = self._order_contracts_to_amount(order)
order['type'] = 'stoploss'
return order
def fetch_stoploss_order(self, order_id: str, pair: str, params: Dict = {}) -> Dict:
if self._config['dry_run']:
@@ -193,7 +211,7 @@ class Okx(Exchange):
params1 = {'stop': True}
order_reg = self._api.fetch_order(order_id, pair, params=params1)
self._log_exchange_response('fetch_stoploss_order', order_reg)
return order_reg
return self._convert_stop_order(pair, order_id, order_reg)
except ccxt.OrderNotFound:
pass
params2 = {'stop': True, 'ordType': 'conditional'}
@@ -204,18 +222,7 @@ class Okx(Exchange):
orders_f = [order for order in orders if order['id'] == order_id]
if orders_f:
order = orders_f[0]
if (order['status'] == 'closed'
and (real_order_id := order.get('info', {}).get('ordId')) is not None):
# Once a order triggered, we fetch the regular followup order.
order_reg = self.fetch_order(real_order_id, pair)
self._log_exchange_response('fetch_stoploss_order1', order_reg)
order_reg['id_stop'] = order_reg['id']
order_reg['id'] = order_id
order_reg['type'] = 'stoploss'
order_reg['status_stop'] = 'triggered'
return order_reg
order['type'] = 'stoploss'
return order
return self._convert_stop_order(pair, order_id, order)
except ccxt.BaseError:
pass
raise RetryableOrderError(

View File

@@ -1,7 +1,7 @@
import logging
from enum import Enum
from gym import spaces
from gymnasium import spaces
from freqtrade.freqai.RL.BaseEnvironment import BaseEnvironment, Positions
@@ -66,7 +66,7 @@ class Base3ActionRLEnv(BaseEnvironment):
elif action == Actions.Sell.value and not self.can_short:
self._update_total_profit()
self._position = Positions.Neutral
trade_type = "neutral"
trade_type = "exit"
self._last_trade_tick = None
else:
print("case not defined")
@@ -74,7 +74,7 @@ class Base3ActionRLEnv(BaseEnvironment):
if trade_type is not None:
self.trade_history.append(
{'price': self.current_price(), 'index': self._current_tick,
'type': trade_type})
'type': trade_type, 'profit': self.get_unrealized_profit()})
if (self._total_profit < self.max_drawdown or
self._total_unrealized_profit < self.max_drawdown):
@@ -94,9 +94,12 @@ class Base3ActionRLEnv(BaseEnvironment):
observation = self._get_observation()
# user can play with time if they want
truncated = False
self._update_history(info)
return observation, step_reward, self._done, info
return observation, step_reward, self._done, truncated, info
def is_tradesignal(self, action: int) -> bool:
"""

View File

@@ -1,7 +1,7 @@
import logging
from enum import Enum
from gym import spaces
from gymnasium import spaces
from freqtrade.freqai.RL.BaseEnvironment import BaseEnvironment, Positions
@@ -52,16 +52,6 @@ class Base4ActionRLEnv(BaseEnvironment):
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
@@ -69,16 +59,16 @@ class Base4ActionRLEnv(BaseEnvironment):
self._last_trade_tick = None
elif action == Actions.Long_enter.value:
self._position = Positions.Long
trade_type = "long"
trade_type = "enter_long"
self._last_trade_tick = self._current_tick
elif action == Actions.Short_enter.value:
self._position = Positions.Short
trade_type = "short"
trade_type = "enter_short"
self._last_trade_tick = self._current_tick
elif action == Actions.Exit.value:
self._update_total_profit()
self._position = Positions.Neutral
trade_type = "neutral"
trade_type = "exit"
self._last_trade_tick = None
else:
print("case not defined")
@@ -86,7 +76,7 @@ class Base4ActionRLEnv(BaseEnvironment):
if trade_type is not None:
self.trade_history.append(
{'price': self.current_price(), 'index': self._current_tick,
'type': trade_type})
'type': trade_type, 'profit': self.get_unrealized_profit()})
if (self._total_profit < self.max_drawdown or
self._total_unrealized_profit < self.max_drawdown):
@@ -106,9 +96,12 @@ class Base4ActionRLEnv(BaseEnvironment):
observation = self._get_observation()
# user can play with time if they want
truncated = False
self._update_history(info)
return observation, step_reward, self._done, info
return observation, step_reward, self._done, truncated, info
def is_tradesignal(self, action: int) -> bool:
"""

View File

@@ -1,7 +1,7 @@
import logging
from enum import Enum
from gym import spaces
from gymnasium import spaces
from freqtrade.freqai.RL.BaseEnvironment import BaseEnvironment, Positions
@@ -53,16 +53,6 @@ class Base5ActionRLEnv(BaseEnvironment):
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
@@ -70,21 +60,21 @@ class Base5ActionRLEnv(BaseEnvironment):
self._last_trade_tick = None
elif action == Actions.Long_enter.value:
self._position = Positions.Long
trade_type = "long"
trade_type = "enter_long"
self._last_trade_tick = self._current_tick
elif action == Actions.Short_enter.value:
self._position = Positions.Short
trade_type = "short"
trade_type = "enter_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"
trade_type = "exit_long"
self._last_trade_tick = None
elif action == Actions.Short_exit.value:
self._update_total_profit()
self._position = Positions.Neutral
trade_type = "neutral"
trade_type = "exit_short"
self._last_trade_tick = None
else:
print("case not defined")
@@ -92,7 +82,7 @@ class Base5ActionRLEnv(BaseEnvironment):
if trade_type is not None:
self.trade_history.append(
{'price': self.current_price(), 'index': self._current_tick,
'type': trade_type})
'type': trade_type, 'profit': self.get_unrealized_profit()})
if (self._total_profit < self.max_drawdown or
self._total_unrealized_profit < self.max_drawdown):
@@ -111,10 +101,12 @@ class Base5ActionRLEnv(BaseEnvironment):
)
observation = self._get_observation()
# user can play with time if they want
truncated = False
self._update_history(info)
return observation, step_reward, self._done, info
return observation, step_reward, self._done, truncated, info
def is_tradesignal(self, action: int) -> bool:
"""

View File

@@ -2,13 +2,13 @@ import logging
import random
from abc import abstractmethod
from enum import Enum
from typing import Optional, Type, Union
from typing import List, Optional, Type, Union
import gym
import gymnasium as gym
import numpy as np
import pandas as pd
from gym import spaces
from gym.utils import seeding
from gymnasium import spaces
from gymnasium.utils import seeding
from pandas import DataFrame
@@ -127,12 +127,23 @@ class BaseEnvironment(gym.Env):
self.history: dict = {}
self.trade_history: list = []
def get_attr(self, attr: str):
"""
Returns the attribute of the environment
:param attr: attribute to return
:return: attribute
"""
return getattr(self, attr)
@abstractmethod
def set_action_space(self):
"""
Unique to the environment action count. Must be inherited.
"""
def action_masks(self) -> List[bool]:
return [self._is_valid(action.value) for action in self.actions]
def seed(self, seed: int = 1):
self.np_random, seed = seeding.np_random(seed)
return [seed]
@@ -172,7 +183,7 @@ class BaseEnvironment(gym.Env):
def reset_tensorboard_log(self):
self.tensorboard_metrics = {}
def reset(self):
def reset(self, seed=None):
"""
Reset is called at the beginning of every episode
"""
@@ -203,7 +214,7 @@ class BaseEnvironment(gym.Env):
self.close_trade_profit = []
self._total_unrealized_profit = 1
return self._get_observation()
return self._get_observation(), self.history
@abstractmethod
def step(self, action: int):
@@ -298,6 +309,12 @@ class BaseEnvironment(gym.Env):
"""
An example reward function. This is the one function that users will likely
wish to inject their own creativity into.
Warning!
This is function is a showcase of functionality designed to show as many possible
environment control features as possible. It is also designed to run quickly
on small computers. This is a benchmark, it is *not* for live production.
: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

View File

@@ -6,24 +6,25 @@ from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Callable, Dict, Optional, Tuple, Type, Union
import gym
import gymnasium as 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 sb3_contrib.common.maskable.callbacks import MaskableEvalCallback
from sb3_contrib.common.maskable.utils import is_masking_supported
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 stable_baselines3.common.vec_env import SubprocVecEnv, VecMonitor
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.freqai.RL.BaseEnvironment import BaseActions, BaseEnvironment, Positions
from freqtrade.freqai.tensorboard.TensorboardCallback import TensorboardCallback
from freqtrade.persistence import Trade
@@ -46,9 +47,9 @@ class BaseReinforcementLearningModel(IFreqaiModel):
'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.train_env: Union[VecMonitor, SubprocVecEnv, gym.Env] = gym.Env()
self.eval_env: Union[VecMonitor, SubprocVecEnv, gym.Env] = gym.Env()
self.eval_callback: Optional[MaskableEvalCallback] = None
self.model_type = self.freqai_info['rl_config']['model_type']
self.rl_config = self.freqai_info['rl_config']
self.df_raw: DataFrame = DataFrame()
@@ -82,6 +83,9 @@ class BaseReinforcementLearningModel(IFreqaiModel):
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.ft_params.get('DI_threshold', False):
self.ft_params.update({'DI_threshold': False})
logger.warning('User tried to use DI_threshold with RL. Deactivating DI_threshold.')
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')
@@ -107,27 +111,37 @@ class BaseReinforcementLearningModel(IFreqaiModel):
training_filter=True,
)
data_dictionary: Dict[str, Any] = dk.make_train_test_datasets(
dd: Dict[str, Any] = dk.make_train_test_datasets(
features_filtered, labels_filtered)
self.df_raw = copy.deepcopy(data_dictionary["train_features"])
self.df_raw = copy.deepcopy(dd["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)
dk.feature_pipeline = self.define_data_pipeline(threads=dk.thread_count)
# data cleaning/analysis
self.data_cleaning_train(dk)
(dd["train_features"],
dd["train_labels"],
dd["train_weights"]) = dk.feature_pipeline.fit_transform(dd["train_features"],
dd["train_labels"],
dd["train_weights"])
if self.freqai_info.get('data_split_parameters', {}).get('test_size', 0.1) != 0:
(dd["test_features"],
dd["test_labels"],
dd["test_weights"]) = dk.feature_pipeline.transform(dd["test_features"],
dd["test_labels"],
dd["test_weights"])
logger.info(
f'Training model on {len(dk.data_dictionary["train_features"].columns)}'
f' features and {len(data_dictionary["train_features"])} data points'
f' features and {len(dd["train_features"])} data points'
)
self.set_train_and_eval_environments(data_dictionary, prices_train, prices_test, dk)
self.set_train_and_eval_environments(dd, prices_train, prices_test, dk)
model = self.fit(data_dictionary, dk)
model = self.fit(dd, dk)
logger.info(f"--------------------done training {pair}--------------------")
@@ -151,9 +165,11 @@ class BaseReinforcementLearningModel(IFreqaiModel):
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))
self.eval_callback = MaskableEvalCallback(self.eval_env, deterministic=True,
render=False, eval_freq=len(train_df),
best_model_save_path=str(dk.data_path),
use_masking=(self.model_type == 'MaskablePPO' and
is_masking_supported(self.eval_env)))
actions = self.train_env.get_actions()
self.tensorboard_callback = TensorboardCallback(verbose=1, actions=actions)
@@ -236,13 +252,10 @@ class BaseReinforcementLearningModel(IFreqaiModel):
unfiltered_df, dk.training_features_list, training_filter=False
)
filtered_dataframe = self.drop_ohlc_from_df(filtered_dataframe, dk)
dk.data_dictionary["prediction_features"] = self.drop_ohlc_from_df(filtered_dataframe, dk)
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)
dk.data_dictionary["prediction_features"], _, _ = dk.feature_pipeline.transform(
dk.data_dictionary["prediction_features"], outlier_check=True)
pred_df = self.rl_model_predict(
dk.data_dictionary["prediction_features"], dk, self.model)
@@ -371,6 +384,12 @@ class BaseReinforcementLearningModel(IFreqaiModel):
"""
An example reward function. This is the one function that users will likely
wish to inject their own creativity into.
Warning!
This is function is a showcase of functionality designed to show as many possible
environment control features as possible. It is also designed to run quickly
on small computers. This is a benchmark, it is *not* for live production.
: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
@@ -431,9 +450,8 @@ class BaseReinforcementLearningModel(IFreqaiModel):
return 0.
def make_env(MyRLEnv: Type[gym.Env], env_id: str, rank: int,
def make_env(MyRLEnv: Type[BaseEnvironment], 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.
@@ -450,8 +468,7 @@ def make_env(MyRLEnv: Type[gym.Env], env_id: str, rank: int,
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

View File

@@ -17,8 +17,8 @@ logger = logging.getLogger(__name__)
class BaseClassifierModel(IFreqaiModel):
"""
Base class for regression type models (e.g. Catboost, LightGBM, XGboost etc.).
User *must* inherit from this class and set fit() and predict(). See example scripts
such as prediction_models/CatboostPredictionModel.py for guidance.
User *must* inherit from this class and set fit(). See example scripts
such as prediction_models/CatboostClassifier.py for guidance.
"""
def train(
@@ -50,21 +50,30 @@ class BaseClassifierModel(IFreqaiModel):
logger.info(f"-------------------- Training on data from {start_date} to "
f"{end_date} --------------------")
# split data into train/test data.
data_dictionary = dk.make_train_test_datasets(features_filtered, labels_filtered)
dd = dk.make_train_test_datasets(features_filtered, labels_filtered)
if not self.freqai_info.get("fit_live_predictions_candles", 0) or not self.live:
dk.fit_labels()
# normalize all data based on train_dataset only
data_dictionary = dk.normalize_data(data_dictionary)
dk.feature_pipeline = self.define_data_pipeline(threads=dk.thread_count)
# optional additional data cleaning/analysis
self.data_cleaning_train(dk)
(dd["train_features"],
dd["train_labels"],
dd["train_weights"]) = dk.feature_pipeline.fit_transform(dd["train_features"],
dd["train_labels"],
dd["train_weights"])
if self.freqai_info.get('data_split_parameters', {}).get('test_size', 0.1) != 0:
(dd["test_features"],
dd["test_labels"],
dd["test_weights"]) = dk.feature_pipeline.transform(dd["test_features"],
dd["test_labels"],
dd["test_weights"])
logger.info(
f"Training model on {len(dk.data_dictionary['train_features'].columns)} features"
)
logger.info(f"Training model on {len(data_dictionary['train_features'])} data points")
logger.info(f"Training model on {len(dd['train_features'])} data points")
model = self.fit(data_dictionary, dk)
model = self.fit(dd, dk)
end_time = time()
@@ -89,10 +98,11 @@ class BaseClassifierModel(IFreqaiModel):
filtered_df, _ = dk.filter_features(
unfiltered_df, dk.training_features_list, training_filter=False
)
filtered_df = dk.normalize_data_from_metadata(filtered_df)
dk.data_dictionary["prediction_features"] = filtered_df
self.data_cleaning_predict(dk)
dk.data_dictionary["prediction_features"], outliers, _ = dk.feature_pipeline.transform(
dk.data_dictionary["prediction_features"], outlier_check=True)
predictions = self.model.predict(dk.data_dictionary["prediction_features"])
if self.CONV_WIDTH == 1:
@@ -107,4 +117,10 @@ class BaseClassifierModel(IFreqaiModel):
pred_df = pd.concat([pred_df, pred_df_prob], axis=1)
if dk.feature_pipeline["di"]:
dk.DI_values = dk.feature_pipeline["di"].di_values
else:
dk.DI_values = np.zeros(outliers.shape[0])
dk.do_predict = outliers
return (pred_df, dk.do_predict)

View File

@@ -0,0 +1,218 @@
import logging
from time import time
from typing import Any, Dict, List, Tuple
import numpy as np
import numpy.typing as npt
import pandas as pd
import torch
from pandas import DataFrame
from torch.nn import functional as F
from freqtrade.exceptions import OperationalException
from freqtrade.freqai.base_models.BasePyTorchModel import BasePyTorchModel
from freqtrade.freqai.data_kitchen import FreqaiDataKitchen
logger = logging.getLogger(__name__)
class BasePyTorchClassifier(BasePyTorchModel):
"""
A PyTorch implementation of a classifier.
User must implement fit method
Important!
- User must declare the target class names in the strategy,
under IStrategy.set_freqai_targets method.
for example, in your strategy:
```
def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs):
self.freqai.class_names = ["down", "up"]
dataframe['&s-up_or_down'] = np.where(dataframe["close"].shift(-100) >
dataframe["close"], 'up', 'down')
return dataframe
"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.class_name_to_index = None
self.index_to_class_name = None
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 dk: dk: The datakitchen object
:param unfiltered_df: 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)
:raises ValueError: if 'class_names' doesn't exist in model meta_data.
"""
class_names = self.model.model_meta_data.get("class_names", None)
if not class_names:
raise ValueError(
"Missing class names. "
"self.model.model_meta_data['class_names'] is None."
)
if not self.class_name_to_index:
self.init_class_names_to_index_mapping(class_names)
dk.find_features(unfiltered_df)
filtered_df, _ = dk.filter_features(
unfiltered_df, dk.training_features_list, training_filter=False
)
dk.data_dictionary["prediction_features"] = filtered_df
dk.data_dictionary["prediction_features"], outliers, _ = dk.feature_pipeline.transform(
dk.data_dictionary["prediction_features"], outlier_check=True)
x = self.data_convertor.convert_x(
dk.data_dictionary["prediction_features"],
device=self.device
)
self.model.model.eval()
logits = self.model.model(x)
probs = F.softmax(logits, dim=-1)
predicted_classes = torch.argmax(probs, dim=-1)
predicted_classes_str = self.decode_class_names(predicted_classes)
# used .tolist to convert probs into an iterable, in this way Tensors
# are automatically moved to the CPU first if necessary.
pred_df_prob = DataFrame(probs.detach().tolist(), columns=class_names)
pred_df = DataFrame(predicted_classes_str, columns=[dk.label_list[0]])
pred_df = pd.concat([pred_df, pred_df_prob], axis=1)
if dk.feature_pipeline["di"]:
dk.DI_values = dk.feature_pipeline["di"].di_values
else:
dk.DI_values = np.zeros(outliers.shape[0])
dk.do_predict = outliers
return (pred_df, dk.do_predict)
def encode_class_names(
self,
data_dictionary: Dict[str, pd.DataFrame],
dk: FreqaiDataKitchen,
class_names: List[str],
):
"""
encode class name, str -> int
assuming first column of *_labels data frame to be the target column
containing the class names
"""
target_column_name = dk.label_list[0]
for split in self.splits:
label_df = data_dictionary[f"{split}_labels"]
self.assert_valid_class_names(label_df[target_column_name], class_names)
label_df[target_column_name] = list(
map(lambda x: self.class_name_to_index[x], label_df[target_column_name])
)
@staticmethod
def assert_valid_class_names(
target_column: pd.Series,
class_names: List[str]
):
non_defined_labels = set(target_column) - set(class_names)
if len(non_defined_labels) != 0:
raise OperationalException(
f"Found non defined labels: {non_defined_labels}, ",
f"expecting labels: {class_names}"
)
def decode_class_names(self, class_ints: torch.Tensor) -> List[str]:
"""
decode class name, int -> str
"""
return list(map(lambda x: self.index_to_class_name[x.item()], class_ints))
def init_class_names_to_index_mapping(self, class_names):
self.class_name_to_index = {s: i for i, s in enumerate(class_names)}
self.index_to_class_name = {i: s for i, s in enumerate(class_names)}
logger.info(f"encoded class name to index: {self.class_name_to_index}")
def convert_label_column_to_int(
self,
data_dictionary: Dict[str, pd.DataFrame],
dk: FreqaiDataKitchen,
class_names: List[str]
):
self.init_class_names_to_index_mapping(class_names)
self.encode_class_names(data_dictionary, dk, class_names)
def get_class_names(self) -> List[str]:
if not self.class_names:
raise ValueError(
"self.class_names is empty, "
"set self.freqai.class_names = ['class a', 'class b', 'class c'] "
"inside IStrategy.set_freqai_targets method."
)
return self.class_names
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
:return:
:model: Trained model which can be used to inference (self.predict)
"""
logger.info(f"-------------------- Starting training {pair} --------------------")
start_time = time()
features_filtered, labels_filtered = dk.filter_features(
unfiltered_df,
dk.training_features_list,
dk.label_list,
training_filter=True,
)
# split data into train/test data.
dd = dk.make_train_test_datasets(features_filtered, labels_filtered)
if not self.freqai_info.get("fit_live_predictions_candles", 0) or not self.live:
dk.fit_labels()
dk.feature_pipeline = self.define_data_pipeline(threads=dk.thread_count)
(dd["train_features"],
dd["train_labels"],
dd["train_weights"]) = dk.feature_pipeline.fit_transform(dd["train_features"],
dd["train_labels"],
dd["train_weights"])
if self.freqai_info.get('data_split_parameters', {}).get('test_size', 0.1) != 0:
(dd["test_features"],
dd["test_labels"],
dd["test_weights"]) = dk.feature_pipeline.transform(dd["test_features"],
dd["test_labels"],
dd["test_weights"])
logger.info(
f"Training model on {len(dk.data_dictionary['train_features'].columns)} features"
)
logger.info(f"Training model on {len(dd['train_features'])} data points")
model = self.fit(dd, dk)
end_time = time()
logger.info(f"-------------------- Done training {pair} "
f"({end_time - start_time:.2f} secs) --------------------")
return model

View File

@@ -0,0 +1,35 @@
import logging
from abc import ABC, abstractmethod
import torch
from freqtrade.freqai.freqai_interface import IFreqaiModel
from freqtrade.freqai.torch.PyTorchDataConvertor import PyTorchDataConvertor
logger = logging.getLogger(__name__)
class BasePyTorchModel(IFreqaiModel, ABC):
"""
Base class for PyTorch type models.
User *must* inherit from this class and set fit() and predict() and
data_convertor property.
"""
def __init__(self, **kwargs):
super().__init__(config=kwargs["config"])
self.dd.model_type = "pytorch"
self.device = "cuda" if torch.cuda.is_available() else "cpu"
test_size = self.freqai_info.get('data_split_parameters', {}).get('test_size')
self.splits = ["train", "test"] if test_size != 0 else ["train"]
self.window_size = self.freqai_info.get("conv_width", 1)
@property
@abstractmethod
def data_convertor(self) -> PyTorchDataConvertor:
"""
a class responsible for converting `*_features` & `*_labels` pandas dataframes
to pytorch tensors.
"""
raise NotImplementedError("Abstract property")

View File

@@ -0,0 +1,120 @@
import logging
from time import time
from typing import Any, Tuple
import numpy as np
import numpy.typing as npt
from pandas import DataFrame
from freqtrade.freqai.base_models.BasePyTorchModel import BasePyTorchModel
from freqtrade.freqai.data_kitchen import FreqaiDataKitchen
logger = logging.getLogger(__name__)
class BasePyTorchRegressor(BasePyTorchModel):
"""
A PyTorch implementation of a regressor.
User must implement fit method
"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
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_df: 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_df, _ = dk.filter_features(
unfiltered_df, dk.training_features_list, training_filter=False
)
dk.data_dictionary["prediction_features"] = filtered_df
dk.data_dictionary["prediction_features"], outliers, _ = dk.feature_pipeline.transform(
dk.data_dictionary["prediction_features"], outlier_check=True)
x = self.data_convertor.convert_x(
dk.data_dictionary["prediction_features"],
device=self.device
)
self.model.model.eval()
y = self.model.model(x)
pred_df = DataFrame(y.detach().tolist(), columns=[dk.label_list[0]])
pred_df, _, _ = dk.label_pipeline.inverse_transform(pred_df)
if dk.feature_pipeline["di"]:
dk.DI_values = dk.feature_pipeline["di"].di_values
else:
dk.DI_values = np.zeros(outliers.shape[0])
dk.do_predict = outliers
return (pred_df, dk.do_predict)
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
:return:
:model: Trained model which can be used to inference (self.predict)
"""
logger.info(f"-------------------- Starting training {pair} --------------------")
start_time = time()
features_filtered, labels_filtered = dk.filter_features(
unfiltered_df,
dk.training_features_list,
dk.label_list,
training_filter=True,
)
# split data into train/test data.
dd = dk.make_train_test_datasets(features_filtered, labels_filtered)
if not self.freqai_info.get("fit_live_predictions_candles", 0) or not self.live:
dk.fit_labels()
dk.feature_pipeline = self.define_data_pipeline(threads=dk.thread_count)
dk.label_pipeline = self.define_label_pipeline(threads=dk.thread_count)
dd["train_labels"], _, _ = dk.label_pipeline.fit_transform(dd["train_labels"])
dd["test_labels"], _, _ = dk.label_pipeline.transform(dd["test_labels"])
(dd["train_features"],
dd["train_labels"],
dd["train_weights"]) = dk.feature_pipeline.fit_transform(dd["train_features"],
dd["train_labels"],
dd["train_weights"])
dd["train_labels"], _, _ = dk.label_pipeline.fit_transform(dd["train_labels"])
if self.freqai_info.get('data_split_parameters', {}).get('test_size', 0.1) != 0:
(dd["test_features"],
dd["test_labels"],
dd["test_weights"]) = dk.feature_pipeline.transform(dd["test_features"],
dd["test_labels"],
dd["test_weights"])
dd["test_labels"], _, _ = dk.label_pipeline.transform(dd["test_labels"])
logger.info(
f"Training model on {len(dk.data_dictionary['train_features'].columns)} features"
)
logger.info(f"Training model on {len(dd['train_features'])} data points")
model = self.fit(dd, dk)
end_time = time()
logger.info(f"-------------------- Done training {pair} "
f"({end_time - start_time:.2f} secs) --------------------")
return model

View File

@@ -16,8 +16,8 @@ logger = logging.getLogger(__name__)
class BaseRegressionModel(IFreqaiModel):
"""
Base class for regression type models (e.g. Catboost, LightGBM, XGboost etc.).
User *must* inherit from this class and set fit() and predict(). See example scripts
such as prediction_models/CatboostPredictionModel.py for guidance.
User *must* inherit from this class and set fit(). See example scripts
such as prediction_models/CatboostRegressor.py for guidance.
"""
def train(
@@ -49,21 +49,33 @@ class BaseRegressionModel(IFreqaiModel):
logger.info(f"-------------------- Training on data from {start_date} to "
f"{end_date} --------------------")
# split data into train/test data.
data_dictionary = dk.make_train_test_datasets(features_filtered, labels_filtered)
dd = dk.make_train_test_datasets(features_filtered, labels_filtered)
if not self.freqai_info.get("fit_live_predictions_candles", 0) or not self.live:
dk.fit_labels()
# normalize all data based on train_dataset only
data_dictionary = dk.normalize_data(data_dictionary)
dk.feature_pipeline = self.define_data_pipeline(threads=dk.thread_count)
dk.label_pipeline = self.define_label_pipeline(threads=dk.thread_count)
# optional additional data cleaning/analysis
self.data_cleaning_train(dk)
(dd["train_features"],
dd["train_labels"],
dd["train_weights"]) = dk.feature_pipeline.fit_transform(dd["train_features"],
dd["train_labels"],
dd["train_weights"])
dd["train_labels"], _, _ = dk.label_pipeline.fit_transform(dd["train_labels"])
if self.freqai_info.get('data_split_parameters', {}).get('test_size', 0.1) != 0:
(dd["test_features"],
dd["test_labels"],
dd["test_weights"]) = dk.feature_pipeline.transform(dd["test_features"],
dd["test_labels"],
dd["test_weights"])
dd["test_labels"], _, _ = dk.label_pipeline.transform(dd["test_labels"])
logger.info(
f"Training model on {len(dk.data_dictionary['train_features'].columns)} features"
)
logger.info(f"Training model on {len(data_dictionary['train_features'])} data points")
logger.info(f"Training model on {len(dd['train_features'])} data points")
model = self.fit(data_dictionary, dk)
model = self.fit(dd, dk)
end_time = time()
@@ -85,14 +97,12 @@ class BaseRegressionModel(IFreqaiModel):
"""
dk.find_features(unfiltered_df)
filtered_df, _ = dk.filter_features(
dk.data_dictionary["prediction_features"], _ = dk.filter_features(
unfiltered_df, dk.training_features_list, training_filter=False
)
filtered_df = dk.normalize_data_from_metadata(filtered_df)
dk.data_dictionary["prediction_features"] = filtered_df
# optional additional data cleaning/analysis
self.data_cleaning_predict(dk)
dk.data_dictionary["prediction_features"], outliers, _ = dk.feature_pipeline.transform(
dk.data_dictionary["prediction_features"], outlier_check=True)
predictions = self.model.predict(dk.data_dictionary["prediction_features"])
if self.CONV_WIDTH == 1:
@@ -100,6 +110,11 @@ class BaseRegressionModel(IFreqaiModel):
pred_df = DataFrame(predictions, columns=dk.label_list)
pred_df = dk.denormalize_labels_from_metadata(pred_df)
pred_df, _, _ = dk.label_pipeline.inverse_transform(pred_df)
if dk.feature_pipeline["di"]:
dk.DI_values = dk.feature_pipeline["di"].di_values
else:
dk.DI_values = np.zeros(outliers.shape[0])
dk.do_predict = outliers
return (pred_df, dk.do_predict)

View File

@@ -1,70 +0,0 @@
import logging
from time import time
from typing import Any
from pandas import DataFrame
from freqtrade.freqai.data_kitchen import FreqaiDataKitchen
from freqtrade.freqai.freqai_interface import IFreqaiModel
logger = logging.getLogger(__name__)
class BaseTensorFlowModel(IFreqaiModel):
"""
Base class for TensorFlow type models.
User *must* inherit from this class and set fit() and predict().
"""
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.
:return:
:model: Trained model which can be used to inference (self.predict)
"""
logger.info(f"-------------------- Starting training {pair} --------------------")
start_time = time()
# filter the features requested by user in the configuration file and elegantly handle NaNs
features_filtered, labels_filtered = dk.filter_features(
unfiltered_df,
dk.training_features_list,
dk.label_list,
training_filter=True,
)
start_date = unfiltered_df["date"].iloc[0].strftime("%Y-%m-%d")
end_date = unfiltered_df["date"].iloc[-1].strftime("%Y-%m-%d")
logger.info(f"-------------------- Training on data from {start_date} to "
f"{end_date} --------------------")
# split data into train/test data.
data_dictionary = dk.make_train_test_datasets(features_filtered, labels_filtered)
if not self.freqai_info.get("fit_live_predictions_candles", 0) or not self.live:
dk.fit_labels()
# normalize all data based on train_dataset only
data_dictionary = dk.normalize_data(data_dictionary)
# optional additional data cleaning/analysis
self.data_cleaning_train(dk)
logger.info(
f"Training model on {len(dk.data_dictionary['train_features'].columns)} features"
)
logger.info(f"Training model on {len(data_dictionary['train_features'])} data points")
model = self.fit(data_dictionary, dk)
end_time = time()
logger.info(f"-------------------- Done training {pair} "
f"({end_time - start_time:.2f} secs) --------------------")
return model

View File

@@ -20,6 +20,7 @@ from pandas import DataFrame
from freqtrade.configuration import TimeRange
from freqtrade.constants import Config
from freqtrade.data.history import load_pair_history
from freqtrade.enums import CandleType
from freqtrade.exceptions import OperationalException
from freqtrade.freqai.data_kitchen import FreqaiDataKitchen
from freqtrade.strategy.interface import IStrategy
@@ -27,6 +28,11 @@ from freqtrade.strategy.interface import IStrategy
logger = logging.getLogger(__name__)
FEATURE_PIPELINE = "feature_pipeline"
LABEL_PIPELINE = "label_pipeline"
TRAINDF = "trained_df"
METADATA = "metadata"
class pair_info(TypedDict):
model_filename: str
@@ -424,7 +430,7 @@ class FreqaiDataDrawer:
dk.data["training_features_list"] = list(dk.data_dictionary["train_features"].columns)
dk.data["label_list"] = dk.label_list
with (save_path / f"{dk.model_filename}_metadata.json").open("w") as fp:
with (save_path / f"{dk.model_filename}_{METADATA}.json").open("w") as fp:
rapidjson.dump(dk.data, fp, default=self.np_encoder, number_mode=rapidjson.NM_NATIVE)
return
@@ -446,42 +452,42 @@ class FreqaiDataDrawer:
dump(model, save_path / f"{dk.model_filename}_model.joblib")
elif self.model_type == 'keras':
model.save(save_path / f"{dk.model_filename}_model.h5")
elif 'stable_baselines' in self.model_type or 'sb3_contrib' == self.model_type:
elif self.model_type in ["stable_baselines3", "sb3_contrib", "pytorch"]:
model.save(save_path / f"{dk.model_filename}_model.zip")
if dk.svm_model is not None:
dump(dk.svm_model, save_path / f"{dk.model_filename}_svm_model.joblib")
dk.data["data_path"] = str(dk.data_path)
dk.data["model_filename"] = str(dk.model_filename)
dk.data["training_features_list"] = dk.training_features_list
dk.data["label_list"] = dk.label_list
# store the metadata
with (save_path / f"{dk.model_filename}_metadata.json").open("w") as fp:
with (save_path / f"{dk.model_filename}_{METADATA}.json").open("w") as fp:
rapidjson.dump(dk.data, fp, default=self.np_encoder, number_mode=rapidjson.NM_NATIVE)
# save the train data to file so we can check preds for area of applicability later
# save the pipelines to pickle files
with (save_path / f"{dk.model_filename}_{FEATURE_PIPELINE}.pkl").open("wb") as fp:
cloudpickle.dump(dk.feature_pipeline, fp)
with (save_path / f"{dk.model_filename}_{LABEL_PIPELINE}.pkl").open("wb") as fp:
cloudpickle.dump(dk.label_pipeline, fp)
# save the train data to file for post processing if desired
dk.data_dictionary["train_features"].to_pickle(
save_path / f"{dk.model_filename}_trained_df.pkl"
save_path / f"{dk.model_filename}_{TRAINDF}.pkl"
)
dk.data_dictionary["train_dates"].to_pickle(
save_path / f"{dk.model_filename}_trained_dates_df.pkl"
)
if self.freqai_info["feature_parameters"].get("principal_component_analysis"):
cloudpickle.dump(
dk.pca, (dk.data_path / f"{dk.model_filename}_pca_object.pkl").open("wb")
)
self.model_dictionary[coin] = model
self.pair_dict[coin]["model_filename"] = dk.model_filename
self.pair_dict[coin]["data_path"] = str(dk.data_path)
if coin not in self.meta_data_dictionary:
self.meta_data_dictionary[coin] = {}
self.meta_data_dictionary[coin]["train_df"] = dk.data_dictionary["train_features"]
self.meta_data_dictionary[coin]["meta_data"] = dk.data
self.meta_data_dictionary[coin][METADATA] = dk.data
self.meta_data_dictionary[coin][FEATURE_PIPELINE] = dk.feature_pipeline
self.meta_data_dictionary[coin][LABEL_PIPELINE] = dk.label_pipeline
self.save_drawer_to_disk()
return
@@ -491,12 +497,12 @@ class FreqaiDataDrawer:
Load only metadata into datakitchen to increase performance during
presaved backtesting (prediction file loading).
"""
with (dk.data_path / f"{dk.model_filename}_metadata.json").open("r") as fp:
with (dk.data_path / f"{dk.model_filename}_{METADATA}.json").open("r") as fp:
dk.data = rapidjson.load(fp, number_mode=rapidjson.NM_NATIVE)
dk.training_features_list = dk.data["training_features_list"]
dk.label_list = dk.data["label_list"]
def load_data(self, coin: str, dk: FreqaiDataKitchen) -> Any:
def load_data(self, coin: str, dk: FreqaiDataKitchen) -> Any: # noqa: C901
"""
loads all data required to make a prediction on a sub-train time range
:returns:
@@ -511,15 +517,17 @@ class FreqaiDataDrawer:
dk.data_path = Path(self.pair_dict[coin]["data_path"])
if coin in self.meta_data_dictionary:
dk.data = self.meta_data_dictionary[coin]["meta_data"]
dk.data_dictionary["train_features"] = self.meta_data_dictionary[coin]["train_df"]
dk.data = self.meta_data_dictionary[coin][METADATA]
dk.feature_pipeline = self.meta_data_dictionary[coin][FEATURE_PIPELINE]
dk.label_pipeline = self.meta_data_dictionary[coin][LABEL_PIPELINE]
else:
with (dk.data_path / f"{dk.model_filename}_metadata.json").open("r") as fp:
with (dk.data_path / f"{dk.model_filename}_{METADATA}.json").open("r") as fp:
dk.data = rapidjson.load(fp, number_mode=rapidjson.NM_NATIVE)
dk.data_dictionary["train_features"] = pd.read_pickle(
dk.data_path / f"{dk.model_filename}_trained_df.pkl"
)
with (dk.data_path / f"{dk.model_filename}_{FEATURE_PIPELINE}.pkl").open("rb") as fp:
dk.feature_pipeline = cloudpickle.load(fp)
with (dk.data_path / f"{dk.model_filename}_{LABEL_PIPELINE}.pkl").open("rb") as fp:
dk.label_pipeline = cloudpickle.load(fp)
dk.training_features_list = dk.data["training_features_list"]
dk.label_list = dk.data["label_list"]
@@ -529,17 +537,16 @@ class FreqaiDataDrawer:
model = self.model_dictionary[coin]
elif self.model_type == 'joblib':
model = load(dk.data_path / f"{dk.model_filename}_model.joblib")
elif self.model_type == 'keras':
from tensorflow import keras
model = keras.models.load_model(dk.data_path / f"{dk.model_filename}_model.h5")
elif 'stable_baselines' in self.model_type or 'sb3_contrib' == self.model_type:
mod = importlib.import_module(
self.model_type, self.freqai_info['rl_config']['model_type'])
MODELCLASS = getattr(mod, self.freqai_info['rl_config']['model_type'])
model = MODELCLASS.load(dk.data_path / f"{dk.model_filename}_model")
if Path(dk.data_path / f"{dk.model_filename}_svm_model.joblib").is_file():
dk.svm_model = load(dk.data_path / f"{dk.model_filename}_svm_model.joblib")
elif self.model_type == 'pytorch':
import torch
zip = torch.load(dk.data_path / f"{dk.model_filename}_model.zip")
model = zip["pytrainer"]
model = model.load_from_checkpoint(zip)
if not model:
raise OperationalException(
@@ -550,11 +557,6 @@ class FreqaiDataDrawer:
if coin not in self.model_dictionary:
self.model_dictionary[coin] = model
if self.config["freqai"]["feature_parameters"]["principal_component_analysis"]:
dk.pca = cloudpickle.load(
(dk.data_path / f"{dk.model_filename}_pca_object.pkl").open("rb")
)
return model
def update_historic_data(self, strategy: IStrategy, dk: FreqaiDataKitchen) -> None:
@@ -634,7 +636,7 @@ class FreqaiDataDrawer:
pair=pair,
timerange=timerange,
data_format=self.config.get("dataformat_ohlcv", "json"),
candle_type=self.config.get("trading_mode", "spot"),
candle_type=self.config.get("candle_type_def", CandleType.SPOT),
)
def get_base_and_corr_dataframes(

View File

@@ -4,7 +4,6 @@ import logging
import random
import shutil
from datetime import datetime, timezone
from math import cos, sin
from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple
@@ -12,16 +11,12 @@ import numpy as np
import numpy.typing as npt
import pandas as pd
import psutil
from datasieve.pipeline import Pipeline
from pandas import DataFrame
from scipy import stats
from sklearn import linear_model
from sklearn.cluster import DBSCAN
from sklearn.metrics.pairwise import pairwise_distances
from sklearn.model_selection import train_test_split
from sklearn.neighbors import NearestNeighbors
from freqtrade.configuration import TimeRange
from freqtrade.constants import Config
from freqtrade.constants import DOCS_LINK, Config
from freqtrade.data.converter import reduce_dataframe_footprint
from freqtrade.exceptions import OperationalException
from freqtrade.exchange import timeframe_to_seconds
@@ -81,11 +76,12 @@ class FreqaiDataKitchen:
self.backtest_predictions_folder: str = "backtesting_predictions"
self.live = live
self.pair = pair
self.svm_model: linear_model.SGDOneClassSVM = None
self.keras: bool = self.freqai_config.get("keras", False)
self.set_all_pairs()
self.backtest_live_models = config.get("freqai_backtest_live_models", False)
self.feature_pipeline = Pipeline()
self.label_pipeline = Pipeline()
self.DI_values: npt.NDArray = np.array([])
if not self.live:
self.full_path = self.get_full_models_path(self.config)
@@ -227,13 +223,7 @@ class FreqaiDataKitchen:
drop_index = pd.isnull(filtered_df).any(axis=1) # get the rows that have NaNs,
drop_index = drop_index.replace(True, 1).replace(False, 0) # pep8 requirement.
if (training_filter):
const_cols = list((filtered_df.nunique() == 1).loc[lambda x: x].index)
if const_cols:
filtered_df = filtered_df.filter(filtered_df.columns.difference(const_cols))
self.data['constant_features_list'] = const_cols
logger.warning(f"Removed features {const_cols} with constant values.")
else:
self.data['constant_features_list'] = []
# we don't care about total row number (total no. datapoints) in training, we only care
# about removing any row with NaNs
# if labels has multiple columns (user wants to train multiple modelEs), we detect here
@@ -264,8 +254,7 @@ class FreqaiDataKitchen:
self.data["filter_drop_index_training"] = drop_index
else:
if 'constant_features_list' in self.data and len(self.data['constant_features_list']):
filtered_df = self.check_pred_labels(filtered_df)
# we are backtesting so we need to preserve row number to send back to strategy,
# so now we use do_predict to avoid any prediction based on a NaN
drop_index = pd.isnull(filtered_df).any(axis=1)
@@ -307,107 +296,6 @@ class FreqaiDataKitchen:
return self.data_dictionary
def normalize_data(self, data_dictionary: Dict) -> Dict[Any, Any]:
"""
Normalize all data in the data_dictionary according to the training dataset
:param data_dictionary: dictionary containing the cleaned and
split training/test data/labels
:returns:
:data_dictionary: updated dictionary with standardized values.
"""
# standardize the data by training stats
train_max = data_dictionary["train_features"].max()
train_min = data_dictionary["train_features"].min()
data_dictionary["train_features"] = (
2 * (data_dictionary["train_features"] - train_min) / (train_max - train_min) - 1
)
data_dictionary["test_features"] = (
2 * (data_dictionary["test_features"] - train_min) / (train_max - train_min) - 1
)
for item in train_max.keys():
self.data[item + "_max"] = train_max[item]
self.data[item + "_min"] = train_min[item]
for item in data_dictionary["train_labels"].keys():
if data_dictionary["train_labels"][item].dtype == object:
continue
train_labels_max = data_dictionary["train_labels"][item].max()
train_labels_min = data_dictionary["train_labels"][item].min()
data_dictionary["train_labels"][item] = (
2
* (data_dictionary["train_labels"][item] - train_labels_min)
/ (train_labels_max - train_labels_min)
- 1
)
if self.freqai_config.get('data_split_parameters', {}).get('test_size', 0.1) != 0:
data_dictionary["test_labels"][item] = (
2
* (data_dictionary["test_labels"][item] - train_labels_min)
/ (train_labels_max - train_labels_min)
- 1
)
self.data[f"{item}_max"] = train_labels_max
self.data[f"{item}_min"] = train_labels_min
return data_dictionary
def normalize_single_dataframe(self, df: DataFrame) -> DataFrame:
train_max = df.max()
train_min = df.min()
df = (
2 * (df - train_min) / (train_max - train_min) - 1
)
for item in train_max.keys():
self.data[item + "_max"] = train_max[item]
self.data[item + "_min"] = train_min[item]
return df
def normalize_data_from_metadata(self, df: DataFrame) -> DataFrame:
"""
Normalize a set of data using the mean and standard deviation from
the associated training data.
:param df: Dataframe to be standardized
"""
train_max = [None] * len(df.keys())
train_min = [None] * len(df.keys())
for i, item in enumerate(df.keys()):
train_max[i] = self.data[f"{item}_max"]
train_min[i] = self.data[f"{item}_min"]
train_max_series = pd.Series(train_max, index=df.keys())
train_min_series = pd.Series(train_min, index=df.keys())
df = (
2 * (df - train_min_series) / (train_max_series - train_min_series) - 1
)
return df
def denormalize_labels_from_metadata(self, df: DataFrame) -> DataFrame:
"""
Denormalize a set of data using the mean and standard deviation from
the associated training data.
:param df: Dataframe of predictions to be denormalized
"""
for label in df.columns:
if df[label].dtype == object or label in self.unique_class_list:
continue
df[label] = (
(df[label] + 1)
* (self.data[f"{label}_max"] - self.data[f"{label}_min"])
/ 2
) + self.data[f"{label}_min"]
return df
def split_timerange(
self, tr: str, train_split: int = 28, bt_split: float = 7
) -> Tuple[list, list]:
@@ -452,9 +340,7 @@ class FreqaiDataKitchen:
tr_training_list_timerange.append(copy.deepcopy(timerange_train))
# associated backtest period
timerange_backtest.startts = timerange_train.stopts
timerange_backtest.stopts = timerange_backtest.startts + int(bt_period)
if timerange_backtest.stopts > config_timerange.stopts:
@@ -485,426 +371,6 @@ class FreqaiDataKitchen:
return df
def check_pred_labels(self, df_predictions: DataFrame) -> DataFrame:
"""
Check that prediction feature labels match training feature labels.
:param df_predictions: incoming predictions
"""
constant_labels = self.data['constant_features_list']
df_predictions = df_predictions.filter(
df_predictions.columns.difference(constant_labels)
)
logger.warning(
f"Removed {len(constant_labels)} features from prediction features, "
f"these were considered constant values during most recent training."
)
return df_predictions
def principal_component_analysis(self) -> None:
"""
Performs Principal Component Analysis on the data for dimensionality reduction
and outlier detection (see self.remove_outliers())
No parameters or returns, it acts on the data_dictionary held by the DataHandler.
"""
from sklearn.decomposition import PCA # avoid importing if we dont need it
pca = PCA(0.999)
pca = pca.fit(self.data_dictionary["train_features"])
n_keep_components = pca.n_components_
self.data["n_kept_components"] = n_keep_components
n_components = self.data_dictionary["train_features"].shape[1]
logger.info("reduced feature dimension by %s", n_components - n_keep_components)
logger.info("explained variance %f", np.sum(pca.explained_variance_ratio_))
train_components = pca.transform(self.data_dictionary["train_features"])
self.data_dictionary["train_features"] = pd.DataFrame(
data=train_components,
columns=["PC" + str(i) for i in range(0, n_keep_components)],
index=self.data_dictionary["train_features"].index,
)
# normalsing transformed training features
self.data_dictionary["train_features"] = self.normalize_single_dataframe(
self.data_dictionary["train_features"])
# keeping a copy of the non-transformed features so we can check for errors during
# model load from disk
self.data["training_features_list_raw"] = copy.deepcopy(self.training_features_list)
self.training_features_list = self.data_dictionary["train_features"].columns
if self.freqai_config.get('data_split_parameters', {}).get('test_size', 0.1) != 0:
test_components = pca.transform(self.data_dictionary["test_features"])
self.data_dictionary["test_features"] = pd.DataFrame(
data=test_components,
columns=["PC" + str(i) for i in range(0, n_keep_components)],
index=self.data_dictionary["test_features"].index,
)
# normalise transformed test feature to transformed training features
self.data_dictionary["test_features"] = self.normalize_data_from_metadata(
self.data_dictionary["test_features"])
self.data["n_kept_components"] = n_keep_components
self.pca = pca
logger.info(f"PCA reduced total features from {n_components} to {n_keep_components}")
if not self.data_path.is_dir():
self.data_path.mkdir(parents=True, exist_ok=True)
return None
def pca_transform(self, filtered_dataframe: DataFrame) -> None:
"""
Use an existing pca transform to transform data into components
:param filtered_dataframe: DataFrame = the cleaned dataframe
"""
pca_components = self.pca.transform(filtered_dataframe)
self.data_dictionary["prediction_features"] = pd.DataFrame(
data=pca_components,
columns=["PC" + str(i) for i in range(0, self.data["n_kept_components"])],
index=filtered_dataframe.index,
)
# normalise transformed predictions to transformed training features
self.data_dictionary["prediction_features"] = self.normalize_data_from_metadata(
self.data_dictionary["prediction_features"])
def compute_distances(self) -> float:
"""
Compute distances between each training point and every other training
point. This metric defines the neighborhood of trained data and is used
for prediction confidence in the Dissimilarity Index
"""
# logger.info("computing average mean distance for all training points")
pairwise = pairwise_distances(
self.data_dictionary["train_features"], n_jobs=self.thread_count)
# remove the diagonal distances which are itself distances ~0
np.fill_diagonal(pairwise, np.NaN)
pairwise = pairwise.reshape(-1, 1)
avg_mean_dist = pairwise[~np.isnan(pairwise)].mean()
return avg_mean_dist
def get_outlier_percentage(self, dropped_pts: npt.NDArray) -> float:
"""
Check if more than X% of points werer dropped during outlier detection.
"""
outlier_protection_pct = self.freqai_config["feature_parameters"].get(
"outlier_protection_percentage", 30)
outlier_pct = (dropped_pts.sum() / len(dropped_pts)) * 100
if outlier_pct >= outlier_protection_pct:
return outlier_pct
else:
return 0.0
def use_SVM_to_remove_outliers(self, predict: bool) -> None:
"""
Build/inference a Support Vector Machine to detect outliers
in training data and prediction
:param predict: bool = If true, inference an existing SVM model, else construct one
"""
if self.keras:
logger.warning(
"SVM outlier removal not currently supported for Keras based models. "
"Skipping user requested function."
)
if predict:
self.do_predict = np.ones(len(self.data_dictionary["prediction_features"]))
return
if predict:
if not self.svm_model:
logger.warning("No svm model available for outlier removal")
return
y_pred = self.svm_model.predict(self.data_dictionary["prediction_features"])
do_predict = np.where(y_pred == -1, 0, y_pred)
if (len(do_predict) - do_predict.sum()) > 0:
logger.info(f"SVM tossed {len(do_predict) - do_predict.sum()} predictions.")
self.do_predict += do_predict
self.do_predict -= 1
else:
# use SGDOneClassSVM to increase speed?
svm_params = self.freqai_config["feature_parameters"].get(
"svm_params", {"shuffle": False, "nu": 0.1})
self.svm_model = linear_model.SGDOneClassSVM(**svm_params).fit(
self.data_dictionary["train_features"]
)
y_pred = self.svm_model.predict(self.data_dictionary["train_features"])
kept_points = np.where(y_pred == -1, 0, y_pred)
# keep_index = np.where(y_pred == 1)
outlier_pct = self.get_outlier_percentage(1 - kept_points)
if outlier_pct:
logger.warning(
f"SVM detected {outlier_pct:.2f}% of the points as outliers. "
f"Keeping original dataset."
)
self.svm_model = None
return
self.data_dictionary["train_features"] = self.data_dictionary["train_features"][
(y_pred == 1)
]
self.data_dictionary["train_labels"] = self.data_dictionary["train_labels"][
(y_pred == 1)
]
self.data_dictionary["train_weights"] = self.data_dictionary["train_weights"][
(y_pred == 1)
]
logger.info(
f"SVM tossed {len(y_pred) - kept_points.sum()}"
f" train points from {len(y_pred)} total points."
)
# same for test data
# TODO: This (and the part above) could be refactored into a separate function
# to reduce code duplication
if self.freqai_config['data_split_parameters'].get('test_size', 0.1) != 0:
y_pred = self.svm_model.predict(self.data_dictionary["test_features"])
kept_points = np.where(y_pred == -1, 0, y_pred)
self.data_dictionary["test_features"] = self.data_dictionary["test_features"][
(y_pred == 1)
]
self.data_dictionary["test_labels"] = self.data_dictionary["test_labels"][(
y_pred == 1)]
self.data_dictionary["test_weights"] = self.data_dictionary["test_weights"][
(y_pred == 1)
]
logger.info(
f"{self.pair}: SVM tossed {len(y_pred) - kept_points.sum()}"
f" test points from {len(y_pred)} total points."
)
return
def use_DBSCAN_to_remove_outliers(self, predict: bool, eps=None) -> None:
"""
Use DBSCAN to cluster training data and remove "noisy" data (read outliers).
User controls this via the config param `DBSCAN_outlier_pct` which indicates the
pct of training data that they want to be considered outliers.
:param predict: bool = If False (training), iterate to find the best hyper parameters
to match user requested outlier percent target.
If True (prediction), use the parameters determined from
the previous training to estimate if the current prediction point
is an outlier.
"""
if predict:
if not self.data['DBSCAN_eps']:
return
train_ft_df = self.data_dictionary['train_features']
pred_ft_df = self.data_dictionary['prediction_features']
num_preds = len(pred_ft_df)
df = pd.concat([train_ft_df, pred_ft_df], axis=0, ignore_index=True)
clustering = DBSCAN(eps=self.data['DBSCAN_eps'],
min_samples=self.data['DBSCAN_min_samples'],
n_jobs=self.thread_count
).fit(df)
do_predict = np.where(clustering.labels_[-num_preds:] == -1, 0, 1)
if (len(do_predict) - do_predict.sum()) > 0:
logger.info(f"DBSCAN tossed {len(do_predict) - do_predict.sum()} predictions")
self.do_predict += do_predict
self.do_predict -= 1
else:
def normalise_distances(distances):
normalised_distances = (distances - distances.min()) / \
(distances.max() - distances.min())
return normalised_distances
def rotate_point(origin, point, angle):
# rotate a point counterclockwise by a given angle (in radians)
# around a given origin
x = origin[0] + cos(angle) * (point[0] - origin[0]) - \
sin(angle) * (point[1] - origin[1])
y = origin[1] + sin(angle) * (point[0] - origin[0]) + \
cos(angle) * (point[1] - origin[1])
return (x, y)
MinPts = int(len(self.data_dictionary['train_features'].index) * 0.25)
# measure pairwise distances to nearest neighbours
neighbors = NearestNeighbors(
n_neighbors=MinPts, n_jobs=self.thread_count)
neighbors_fit = neighbors.fit(self.data_dictionary['train_features'])
distances, _ = neighbors_fit.kneighbors(self.data_dictionary['train_features'])
distances = np.sort(distances, axis=0).mean(axis=1)
normalised_distances = normalise_distances(distances)
x_range = np.linspace(0, 1, len(distances))
line = np.linspace(normalised_distances[0],
normalised_distances[-1], len(normalised_distances))
deflection = np.abs(normalised_distances - line)
max_deflection_loc = np.where(deflection == deflection.max())[0][0]
origin = x_range[max_deflection_loc], line[max_deflection_loc]
point = x_range[max_deflection_loc], normalised_distances[max_deflection_loc]
rot_angle = np.pi / 4
elbow_loc = rotate_point(origin, point, rot_angle)
epsilon = elbow_loc[1] * (distances[-1] - distances[0]) + distances[0]
clustering = DBSCAN(eps=epsilon, min_samples=MinPts,
n_jobs=int(self.thread_count)).fit(
self.data_dictionary['train_features']
)
logger.info(f'DBSCAN found eps of {epsilon:.2f}.')
self.data['DBSCAN_eps'] = epsilon
self.data['DBSCAN_min_samples'] = MinPts
dropped_points = np.where(clustering.labels_ == -1, 1, 0)
outlier_pct = self.get_outlier_percentage(dropped_points)
if outlier_pct:
logger.warning(
f"DBSCAN detected {outlier_pct:.2f}% of the points as outliers. "
f"Keeping original dataset."
)
self.data['DBSCAN_eps'] = 0
return
self.data_dictionary['train_features'] = self.data_dictionary['train_features'][
(clustering.labels_ != -1)
]
self.data_dictionary["train_labels"] = self.data_dictionary["train_labels"][
(clustering.labels_ != -1)
]
self.data_dictionary["train_weights"] = self.data_dictionary["train_weights"][
(clustering.labels_ != -1)
]
logger.info(
f"DBSCAN tossed {dropped_points.sum()}"
f" train points from {len(clustering.labels_)}"
)
return
def compute_inlier_metric(self, set_='train') -> None:
"""
Compute inlier metric from backwards distance distributions.
This metric defines how well features from a timepoint fit
into previous timepoints.
"""
def normalise(dataframe: DataFrame, key: str) -> DataFrame:
if set_ == 'train':
min_value = dataframe.min()
max_value = dataframe.max()
self.data[f'{key}_min'] = min_value
self.data[f'{key}_max'] = max_value
else:
min_value = self.data[f'{key}_min']
max_value = self.data[f'{key}_max']
return (dataframe - min_value) / (max_value - min_value)
no_prev_pts = self.freqai_config["feature_parameters"]["inlier_metric_window"]
if set_ == 'train':
compute_df = copy.deepcopy(self.data_dictionary['train_features'])
elif set_ == 'test':
compute_df = copy.deepcopy(self.data_dictionary['test_features'])
else:
compute_df = copy.deepcopy(self.data_dictionary['prediction_features'])
compute_df_reindexed = compute_df.reindex(
index=np.flip(compute_df.index)
)
pairwise = pd.DataFrame(
np.triu(
pairwise_distances(compute_df_reindexed, n_jobs=self.thread_count)
),
columns=compute_df_reindexed.index,
index=compute_df_reindexed.index
)
pairwise = pairwise.round(5)
column_labels = [
'{}{}'.format('d', i) for i in range(1, no_prev_pts + 1)
]
distances = pd.DataFrame(
columns=column_labels, index=compute_df.index
)
for index in compute_df.index[no_prev_pts:]:
current_row = pairwise.loc[[index]]
current_row_no_zeros = current_row.loc[
:, (current_row != 0).any(axis=0)
]
distances.loc[[index]] = current_row_no_zeros.iloc[
:, :no_prev_pts
]
distances = distances.replace([np.inf, -np.inf], np.nan)
drop_index = pd.isnull(distances).any(axis=1)
distances = distances[drop_index == 0]
inliers = pd.DataFrame(index=distances.index)
for key in distances.keys():
current_distances = distances[key].dropna()
current_distances = normalise(current_distances, key)
if set_ == 'train':
fit_params = stats.weibull_min.fit(current_distances)
self.data[f'{key}_fit_params'] = fit_params
else:
fit_params = self.data[f'{key}_fit_params']
quantiles = stats.weibull_min.cdf(current_distances, *fit_params)
df_inlier = pd.DataFrame(
{key: quantiles}, index=distances.index
)
inliers = pd.concat(
[inliers, df_inlier], axis=1
)
inlier_metric = pd.DataFrame(
data=inliers.sum(axis=1) / no_prev_pts,
columns=['%-inlier_metric'],
index=compute_df.index
)
inlier_metric = (2 * (inlier_metric - inlier_metric.min()) /
(inlier_metric.max() - inlier_metric.min()) - 1)
if set_ in ('train', 'test'):
inlier_metric = inlier_metric.iloc[no_prev_pts:]
compute_df = compute_df.iloc[no_prev_pts:]
self.remove_beginning_points_from_data_dict(set_, no_prev_pts)
self.data_dictionary[f'{set_}_features'] = pd.concat(
[compute_df, inlier_metric], axis=1)
else:
self.data_dictionary['prediction_features'] = pd.concat(
[compute_df, inlier_metric], axis=1)
self.data_dictionary['prediction_features'].fillna(0, inplace=True)
logger.info('Inlier metric computed and added to features.')
return None
def remove_beginning_points_from_data_dict(self, set_='train', no_prev_pts: int = 10):
features = self.data_dictionary[f'{set_}_features']
weights = self.data_dictionary[f'{set_}_weights']
labels = self.data_dictionary[f'{set_}_labels']
self.data_dictionary[f'{set_}_weights'] = weights[no_prev_pts:]
self.data_dictionary[f'{set_}_features'] = features.iloc[no_prev_pts:]
self.data_dictionary[f'{set_}_labels'] = labels.iloc[no_prev_pts:]
def add_noise_to_training_features(self) -> None:
"""
Add noise to train features to reduce the risk of overfitting.
"""
mu = 0 # no shift
sigma = self.freqai_config["feature_parameters"]["noise_standard_deviation"]
compute_df = self.data_dictionary['train_features']
noise = np.random.normal(mu, sigma, [compute_df.shape[0], compute_df.shape[1]])
self.data_dictionary['train_features'] += noise
return
def find_features(self, dataframe: DataFrame) -> None:
"""
Find features in the strategy provided dataframe
@@ -925,37 +391,6 @@ class FreqaiDataKitchen:
labels = [c for c in column_names if "&" in c]
self.label_list = labels
def check_if_pred_in_training_spaces(self) -> None:
"""
Compares the distance from each prediction point to each training data
point. It uses this information to estimate a Dissimilarity Index (DI)
and avoid making predictions on any points that are too far away
from the training data set.
"""
distance = pairwise_distances(
self.data_dictionary["train_features"],
self.data_dictionary["prediction_features"],
n_jobs=self.thread_count,
)
self.DI_values = distance.min(axis=0) / self.data["avg_mean_dist"]
do_predict = np.where(
self.DI_values < self.freqai_config["feature_parameters"]["DI_threshold"],
1,
0,
)
if (len(do_predict) - do_predict.sum()) > 0:
logger.info(
f"{self.pair}: DI tossed {len(do_predict) - do_predict.sum()} predictions for "
"being too far from training data."
)
self.do_predict += do_predict
self.do_predict -= 1
def set_weights_higher_recent(self, num_weights: int) -> npt.ArrayLike:
"""
Set weights so that recent data is more heavily weighted during
@@ -1291,7 +726,7 @@ class FreqaiDataKitchen:
return dataframe
def use_strategy_to_populate_indicators(
def use_strategy_to_populate_indicators( # noqa: C901
self,
strategy: IStrategy,
corr_dataframes: dict = {},
@@ -1325,9 +760,9 @@ class FreqaiDataKitchen:
" which was deprecated on March 1, 2023. Please refer "
"to the strategy migration guide to use the new "
"feature_engineering_* methods: \n"
"https://www.freqtrade.io/en/stable/strategy_migration/#freqai-strategy \n"
f"{DOCS_LINK}/strategy_migration/#freqai-strategy \n"
"And the feature_engineering_* documentation: \n"
"https://www.freqtrade.io/en/latest/freqai-feature-engineering/"
f"{DOCS_LINK}/freqai-feature-engineering/"
)
tfs: List[str] = self.freqai_config["feature_parameters"].get("include_timeframes")
@@ -1362,12 +797,12 @@ class FreqaiDataKitchen:
dataframe = self.populate_features(dataframe.copy(), corr_pair, strategy,
corr_dataframes, base_dataframes, True)
dataframe = strategy.set_freqai_targets(dataframe.copy(), metadata=metadata)
if self.live:
dataframe = strategy.set_freqai_targets(dataframe.copy(), metadata=metadata)
dataframe = self.remove_special_chars_from_feature_names(dataframe)
self.get_unique_classes_from_labels(dataframe)
dataframe = self.remove_special_chars_from_feature_names(dataframe)
if self.config.get('reduce_df_footprint', False):
dataframe = reduce_dataframe_footprint(dataframe)
@@ -1515,3 +950,32 @@ class FreqaiDataKitchen:
timerange.startts += buffer * timeframe_to_seconds(self.config["timeframe"])
return timerange
# deprecated functions
def normalize_data(self, data_dictionary: Dict) -> Dict[Any, Any]:
"""
Deprecation warning, migration assistance
"""
logger.warning(f"Your custom IFreqaiModel relies on the deprecated"
" data pipeline. Please update your model to use the new data pipeline."
" This can be achieved by following the migration guide at "
f"{DOCS_LINK}/strategy_migration/#freqai-new-data-pipeline "
"We added a basic pipeline for you, but this will be removed "
"in a future version.")
return data_dictionary
def denormalize_labels_from_metadata(self, df: DataFrame) -> DataFrame:
"""
Deprecation warning, migration assistance
"""
logger.warning(f"Your custom IFreqaiModel relies on the deprecated"
" data pipeline. Please update your model to use the new data pipeline."
" This can be achieved by following the migration guide at "
f"{DOCS_LINK}/strategy_migration/#freqai-new-data-pipeline "
"We added a basic pipeline for you, but this will be removed "
"in a future version.")
pred_df, _, _ = self.label_pipeline.inverse_transform(df)
return pred_df

View File

@@ -7,21 +7,25 @@ from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Dict, List, Literal, Optional, Tuple
import datasieve.transforms as ds
import numpy as np
import pandas as pd
import psutil
from datasieve.pipeline import Pipeline
from datasieve.transforms import SKLearnWrapper
from numpy.typing import NDArray
from pandas import DataFrame
from sklearn.preprocessing import MinMaxScaler
from freqtrade.configuration import TimeRange
from freqtrade.constants import Config
from freqtrade.constants import DOCS_LINK, Config
from freqtrade.data.dataprovider import DataProvider
from freqtrade.enums import RunMode
from freqtrade.exceptions import OperationalException
from freqtrade.exchange import timeframe_to_seconds
from freqtrade.freqai.data_drawer import FreqaiDataDrawer
from freqtrade.freqai.data_kitchen import FreqaiDataKitchen
from freqtrade.freqai.utils import plot_feature_importance, record_params
from freqtrade.freqai.utils import get_tb_logger, plot_feature_importance, record_params
from freqtrade.strategy.interface import IStrategy
@@ -80,9 +84,11 @@ class IFreqaiModel(ABC):
if self.keras and self.ft_params.get("DI_threshold", 0):
self.ft_params["DI_threshold"] = 0
logger.warning("DI threshold is not configured for Keras models yet. Deactivating.")
self.CONV_WIDTH = self.freqai_info.get('conv_width', 1)
if self.ft_params.get("inlier_metric_window", 0):
self.CONV_WIDTH = self.ft_params.get("inlier_metric_window", 0) * 2
self.class_names: List[str] = [] # used in classification subclasses
self.pair_it = 0
self.pair_it_train = 0
self.total_pairs = len(self.config.get("exchange", {}).get("pair_whitelist"))
@@ -108,6 +114,7 @@ class IFreqaiModel(ABC):
if self.ft_params.get('principal_component_analysis', False) and self.continual_learning:
self.ft_params.update({'principal_component_analysis': False})
logger.warning('User tried to use PCA with continual learning. Deactivating PCA.')
self.activate_tensorboard: bool = self.freqai_info.get('activate_tensorboard', True)
record_params(config, self.full_path)
@@ -241,8 +248,8 @@ class IFreqaiModel(ABC):
new_trained_timerange, pair, strategy, dk, data_load_timerange
)
except Exception as msg:
logger.warning(f"Training {pair} raised exception {msg.__class__.__name__}. "
f"Message: {msg}, skipping.")
logger.exception(f"Training {pair} raised exception {msg.__class__.__name__}. "
f"Message: {msg}, skipping.")
self.train_timer('stop', pair)
@@ -305,10 +312,11 @@ class IFreqaiModel(ABC):
if dk.check_if_backtest_prediction_is_valid(len_backtest_df):
if check_features:
self.dd.load_metadata(dk)
dataframe_dummy_features = self.dk.use_strategy_to_populate_indicators(
strategy, prediction_dataframe=dataframe.tail(1), pair=metadata["pair"]
df_fts = self.dk.use_strategy_to_populate_indicators(
strategy, prediction_dataframe=dataframe.tail(1), pair=pair
)
dk.find_features(dataframe_dummy_features)
df_fts = dk.remove_special_chars_from_feature_names(df_fts)
dk.find_features(df_fts)
self.check_if_feature_list_matches_strategy(dk)
check_features = False
append_df = dk.get_backtesting_prediction()
@@ -316,7 +324,7 @@ class IFreqaiModel(ABC):
else:
if populate_indicators:
dataframe = self.dk.use_strategy_to_populate_indicators(
strategy, prediction_dataframe=dataframe, pair=metadata["pair"]
strategy, prediction_dataframe=dataframe, pair=pair
)
populate_indicators = False
@@ -332,12 +340,19 @@ class IFreqaiModel(ABC):
dataframe_train = dk.slice_dataframe(tr_train, dataframe_base_train)
dataframe_backtest = dk.slice_dataframe(tr_backtest, dataframe_base_backtest)
dataframe_train = dk.remove_special_chars_from_feature_names(dataframe_train)
dataframe_backtest = dk.remove_special_chars_from_feature_names(dataframe_backtest)
dk.get_unique_classes_from_labels(dataframe_train)
if not self.model_exists(dk):
dk.find_features(dataframe_train)
dk.find_labels(dataframe_train)
try:
self.tb_logger = get_tb_logger(self.dd.model_type, dk.data_path,
self.activate_tensorboard)
self.model = self.train(dataframe_train, pair, dk)
self.tb_logger.close()
except Exception as msg:
logger.warning(
f"Training {pair} raised exception {msg.__class__.__name__}. "
@@ -484,76 +499,51 @@ class IFreqaiModel(ABC):
if dk.training_features_list != feature_list:
raise OperationalException(
"Trying to access pretrained model with `identifier` "
"but found different features furnished by current strategy."
"Change `identifier` to train from scratch, or ensure the"
"strategy is furnishing the same features as the pretrained"
"but found different features furnished by current strategy. "
"Change `identifier` to train from scratch, or ensure the "
"strategy is furnishing the same features as the pretrained "
"model. In case of --strategy-list, please be aware that FreqAI "
"requires all strategies to maintain identical "
"feature_engineering_* functions"
)
def data_cleaning_train(self, dk: FreqaiDataKitchen) -> None:
"""
Base data cleaning method for train.
Functions here improve/modify the input data by identifying outliers,
computing additional metrics, adding noise, reducing dimensionality etc.
"""
def define_data_pipeline(self, threads=-1) -> Pipeline:
ft_params = self.freqai_info["feature_parameters"]
pipe_steps = [
('const', ds.VarianceThreshold(threshold=0)),
('scaler', SKLearnWrapper(MinMaxScaler(feature_range=(-1, 1))))
]
if ft_params.get('inlier_metric_window', 0):
dk.compute_inlier_metric(set_='train')
if self.freqai_info["data_split_parameters"]["test_size"] > 0:
dk.compute_inlier_metric(set_='test')
if ft_params.get(
"principal_component_analysis", False
):
dk.principal_component_analysis()
if ft_params.get("principal_component_analysis", False):
pipe_steps.append(('pca', ds.PCA(n_components=0.999)))
pipe_steps.append(('post-pca-scaler',
SKLearnWrapper(MinMaxScaler(feature_range=(-1, 1)))))
if ft_params.get("use_SVM_to_remove_outliers", False):
dk.use_SVM_to_remove_outliers(predict=False)
svm_params = ft_params.get(
"svm_params", {"shuffle": False, "nu": 0.01})
pipe_steps.append(('svm', ds.SVMOutlierExtractor(**svm_params)))
if ft_params.get("DI_threshold", 0):
dk.data["avg_mean_dist"] = dk.compute_distances()
di = ft_params.get("DI_threshold", 0)
if di:
pipe_steps.append(('di', ds.DissimilarityIndex(di_threshold=di, n_jobs=threads)))
if ft_params.get("use_DBSCAN_to_remove_outliers", False):
if dk.pair in self.dd.old_DBSCAN_eps:
eps = self.dd.old_DBSCAN_eps[dk.pair]
else:
eps = None
dk.use_DBSCAN_to_remove_outliers(predict=False, eps=eps)
self.dd.old_DBSCAN_eps[dk.pair] = dk.data['DBSCAN_eps']
pipe_steps.append(('dbscan', ds.DBSCAN(n_jobs=threads)))
if self.freqai_info["feature_parameters"].get('noise_standard_deviation', 0):
dk.add_noise_to_training_features()
sigma = self.freqai_info["feature_parameters"].get('noise_standard_deviation', 0)
if sigma:
pipe_steps.append(('noise', ds.Noise(sigma=sigma)))
def data_cleaning_predict(self, dk: FreqaiDataKitchen) -> None:
"""
Base data cleaning method for predict.
Functions here are complementary to the functions of data_cleaning_train.
"""
ft_params = self.freqai_info["feature_parameters"]
return Pipeline(pipe_steps)
# ensure user is feeding the correct indicators to the model
self.check_if_feature_list_matches_strategy(dk)
def define_label_pipeline(self, threads=-1) -> Pipeline:
if ft_params.get('inlier_metric_window', 0):
dk.compute_inlier_metric(set_='predict')
label_pipeline = Pipeline([
('scaler', SKLearnWrapper(MinMaxScaler(feature_range=(-1, 1))))
])
if ft_params.get(
"principal_component_analysis", False
):
dk.pca_transform(dk.data_dictionary['prediction_features'])
if ft_params.get("use_SVM_to_remove_outliers", False):
dk.use_SVM_to_remove_outliers(predict=True)
if ft_params.get("DI_threshold", 0):
dk.check_if_pred_in_training_spaces()
if ft_params.get("use_DBSCAN_to_remove_outliers", False):
dk.use_DBSCAN_to_remove_outliers(predict=True)
return label_pipeline
def model_exists(self, dk: FreqaiDataKitchen) -> bool:
"""
@@ -565,10 +555,9 @@ class IFreqaiModel(ABC):
"""
if self.dd.model_type == 'joblib':
file_type = ".joblib"
elif self.dd.model_type == 'keras':
file_type = ".h5"
elif 'stable_baselines' in self.dd.model_type or 'sb3_contrib' == self.dd.model_type:
elif self.dd.model_type in ["stable_baselines3", "sb3_contrib", "pytorch"]:
file_type = ".zip"
path_to_modelfile = Path(dk.data_path / f"{dk.model_filename}_model{file_type}")
file_exists = path_to_modelfile.is_file()
if file_exists:
@@ -614,18 +603,23 @@ class IFreqaiModel(ABC):
strategy, corr_dataframes, base_dataframes, pair
)
new_trained_timerange = dk.buffer_timerange(new_trained_timerange)
trained_timestamp = new_trained_timerange.stopts
unfiltered_dataframe = dk.slice_dataframe(new_trained_timerange, unfiltered_dataframe)
buffered_timerange = dk.buffer_timerange(new_trained_timerange)
unfiltered_dataframe = dk.slice_dataframe(buffered_timerange, unfiltered_dataframe)
# find the features indicated by strategy and store in datakitchen
dk.find_features(unfiltered_dataframe)
dk.find_labels(unfiltered_dataframe)
self.tb_logger = get_tb_logger(self.dd.model_type, dk.data_path,
self.activate_tensorboard)
model = self.train(unfiltered_dataframe, pair, dk)
self.tb_logger.close()
self.dd.pair_dict[pair]["trained_timestamp"] = new_trained_timerange.stopts
dk.set_new_model_names(pair, new_trained_timerange.stopts)
self.dd.pair_dict[pair]["trained_timestamp"] = trained_timestamp
dk.set_new_model_names(pair, trained_timestamp)
self.dd.save_data(model, pair, dk)
if self.plot_features:
@@ -684,7 +678,7 @@ class IFreqaiModel(ABC):
# # for keras type models, the conv_window needs to be prepended so
# # viewing is correct in frequi
if self.freqai_info.get('keras', False) or self.ft_params.get('inlier_metric_window', 0):
if self.ft_params.get('inlier_metric_window', 0):
n_lost_points = self.freqai_info.get('conv_width', 2)
zeros_df = DataFrame(np.zeros((n_lost_points, len(hist_preds_df.columns))),
columns=hist_preds_df.columns)
@@ -974,3 +968,50 @@ class IFreqaiModel(ABC):
:do_predict: np.array of 1s and 0s to indicate places where freqai needed to remove
data (NaNs) or felt uncertain about data (i.e. SVM and/or DI index)
"""
# deprecated functions
def data_cleaning_train(self, dk: FreqaiDataKitchen, pair: str):
"""
throw deprecation warning if this function is called
"""
logger.warning(f"Your model {self.__class__.__name__} relies on the deprecated"
" data pipeline. Please update your model to use the new data pipeline."
" This can be achieved by following the migration guide at "
f"{DOCS_LINK}/strategy_migration/#freqai-new-data-pipeline")
dk.feature_pipeline = self.define_data_pipeline(threads=dk.thread_count)
dd = dk.data_dictionary
(dd["train_features"],
dd["train_labels"],
dd["train_weights"]) = dk.feature_pipeline.fit_transform(dd["train_features"],
dd["train_labels"],
dd["train_weights"])
(dd["test_features"],
dd["test_labels"],
dd["test_weights"]) = dk.feature_pipeline.transform(dd["test_features"],
dd["test_labels"],
dd["test_weights"])
dk.label_pipeline = self.define_label_pipeline(threads=dk.thread_count)
dd["train_labels"], _, _ = dk.label_pipeline.fit_transform(dd["train_labels"])
dd["test_labels"], _, _ = dk.label_pipeline.transform(dd["test_labels"])
return
def data_cleaning_predict(self, dk: FreqaiDataKitchen, pair: str):
"""
throw deprecation warning if this function is called
"""
logger.warning(f"Your model {self.__class__.__name__} relies on the deprecated"
" data pipeline. Please update your model to use the new data pipeline."
" This can be achieved by following the migration guide at "
f"{DOCS_LINK}/strategy_migration/#freqai-new-data-pipeline")
dd = dk.data_dictionary
dd["predict_features"], outliers, _ = dk.feature_pipeline.transform(
dd["predict_features"], outlier_check=True)
if self.freqai_info.get("DI_threshold", 0) > 0:
dk.DI_values = dk.feature_pipeline["di"].di_values
else:
dk.DI_values = np.zeros(outliers.shape[0])
dk.do_predict = outliers
return

View File

@@ -14,16 +14,20 @@ logger = logging.getLogger(__name__)
class CatboostClassifier(BaseClassifierModel):
"""
User created prediction model. The class needs to override three necessary
functions, predict(), train(), fit(). The class inherits ModelHandler which
has its own DataHandler where data is held, saved, loaded, and managed.
User created prediction model. The class inherits IFreqaiModel, which
means it has full access to all Frequency AI functionality. Typically,
users would use this to override the common `fit()`, `train()`, or
`predict()` methods to add their custom data handling tools or change
various aspects of the training that cannot be configured via the
top level config.json file.
"""
def fit(self, data_dictionary: Dict, dk: FreqaiDataKitchen, **kwargs) -> Any:
"""
User sets up the training and test data to fit their desired model here
:param data_dictionary: the dictionary constructed by DataHandler to hold
all the training and test data/labels.
:param data_dictionary: the dictionary holding all data for train, test,
labels, weights
:param dk: The datakitchen object for the current coin/model
"""
train_data = Pool(

View File

@@ -15,16 +15,20 @@ logger = logging.getLogger(__name__)
class CatboostClassifierMultiTarget(BaseClassifierModel):
"""
User created prediction model. The class needs to override three necessary
functions, predict(), train(), fit(). The class inherits ModelHandler which
has its own DataHandler where data is held, saved, loaded, and managed.
User created prediction model. The class inherits IFreqaiModel, which
means it has full access to all Frequency AI functionality. Typically,
users would use this to override the common `fit()`, `train()`, or
`predict()` methods to add their custom data handling tools or change
various aspects of the training that cannot be configured via the
top level config.json file.
"""
def fit(self, data_dictionary: Dict, dk: FreqaiDataKitchen, **kwargs) -> Any:
"""
User sets up the training and test data to fit their desired model here
:param data_dictionary: the dictionary constructed by DataHandler to hold
all the training and test data/labels.
:param data_dictionary: the dictionary holding all data for train, test,
labels, weights
:param dk: The datakitchen object for the current coin/model
"""
cbc = CatBoostClassifier(

View File

@@ -14,16 +14,20 @@ logger = logging.getLogger(__name__)
class CatboostRegressor(BaseRegressionModel):
"""
User created prediction model. The class needs to override three necessary
functions, predict(), train(), fit(). The class inherits ModelHandler which
has its own DataHandler where data is held, saved, loaded, and managed.
User created prediction model. The class inherits IFreqaiModel, which
means it has full access to all Frequency AI functionality. Typically,
users would use this to override the common `fit()`, `train()`, or
`predict()` methods to add their custom data handling tools or change
various aspects of the training that cannot be configured via the
top level config.json file.
"""
def fit(self, data_dictionary: Dict, dk: FreqaiDataKitchen, **kwargs) -> Any:
"""
User sets up the training and test data to fit their desired model here
:param data_dictionary: the dictionary constructed by DataHandler to hold
all the training and test data/labels.
:param data_dictionary: the dictionary holding all data for train, test,
labels, weights
:param dk: The datakitchen object for the current coin/model
"""
train_data = Pool(

View File

@@ -15,16 +15,20 @@ logger = logging.getLogger(__name__)
class CatboostRegressorMultiTarget(BaseRegressionModel):
"""
User created prediction model. The class needs to override three necessary
functions, predict(), train(), fit(). The class inherits ModelHandler which
has its own DataHandler where data is held, saved, loaded, and managed.
User created prediction model. The class inherits IFreqaiModel, which
means it has full access to all Frequency AI functionality. Typically,
users would use this to override the common `fit()`, `train()`, or
`predict()` methods to add their custom data handling tools or change
various aspects of the training that cannot be configured via the
top level config.json file.
"""
def fit(self, data_dictionary: Dict, dk: FreqaiDataKitchen, **kwargs) -> Any:
"""
User sets up the training and test data to fit their desired model here
:param data_dictionary: the dictionary constructed by DataHandler to hold
all the training and test data/labels.
:param data_dictionary: the dictionary holding all data for train, test,
labels, weights
:param dk: The datakitchen object for the current coin/model
"""
cbr = CatBoostRegressor(

View File

@@ -12,16 +12,20 @@ logger = logging.getLogger(__name__)
class LightGBMClassifier(BaseClassifierModel):
"""
User created prediction model. The class needs to override three necessary
functions, predict(), train(), fit(). The class inherits ModelHandler which
has its own DataHandler where data is held, saved, loaded, and managed.
User created prediction model. The class inherits IFreqaiModel, which
means it has full access to all Frequency AI functionality. Typically,
users would use this to override the common `fit()`, `train()`, or
`predict()` methods to add their custom data handling tools or change
various aspects of the training that cannot be configured via the
top level config.json file.
"""
def fit(self, data_dictionary: Dict, dk: FreqaiDataKitchen, **kwargs) -> Any:
"""
User sets up the training and test data to fit their desired model here
:param data_dictionary: the dictionary constructed by DataHandler to hold
all the training and test data/labels.
:param data_dictionary: the dictionary holding all data for train, test,
labels, weights
:param dk: The datakitchen object for the current coin/model
"""
if self.freqai_info.get('data_split_parameters', {}).get('test_size', 0.1) == 0:

View File

@@ -13,16 +13,20 @@ logger = logging.getLogger(__name__)
class LightGBMClassifierMultiTarget(BaseClassifierModel):
"""
User created prediction model. The class needs to override three necessary
functions, predict(), train(), fit(). The class inherits ModelHandler which
has its own DataHandler where data is held, saved, loaded, and managed.
User created prediction model. The class inherits IFreqaiModel, which
means it has full access to all Frequency AI functionality. Typically,
users would use this to override the common `fit()`, `train()`, or
`predict()` methods to add their custom data handling tools or change
various aspects of the training that cannot be configured via the
top level config.json file.
"""
def fit(self, data_dictionary: Dict, dk: FreqaiDataKitchen, **kwargs) -> Any:
"""
User sets up the training and test data to fit their desired model here
:param data_dictionary: the dictionary constructed by DataHandler to hold
all the training and test data/labels.
:param data_dictionary: the dictionary holding all data for train, test,
labels, weights
:param dk: The datakitchen object for the current coin/model
"""
lgb = LGBMClassifier(**self.model_training_parameters)

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