Compare commits

...

1211 Commits

Author SHA1 Message Date
robcaulk
755041c134 add noise feature, improve docstrings 2022-08-19 18:35:24 +02:00
robcaulk
98c62dad91 integrate inlier metric function 2022-08-19 15:22:54 +02:00
th0rntwig
52ee7fc981 Add inlier metric computation 2022-08-19 15:22:54 +02:00
Matthias
16af10a5bc Update notebook sample with simplified datadir configuration
closes #7252
2022-08-19 14:05:27 +02:00
Matthias
7d84ef2e2c Remove unused imports 2022-08-19 13:45:10 +02:00
Matthias
b420614d65 Reduce code duplication in datahandlers 2022-08-19 09:33:07 +02:00
Matthias
975bf8fe88 Update Docstring to match actual return values 2022-08-19 09:23:53 +02:00
Matthias
47b3143534 Simplify and fix some tests 2022-08-19 09:10:54 +02:00
Matthias
42eb508515 Attempt fix of #7184 2022-08-19 07:09:46 +02:00
Matthias
76a3e97e05 Add migrations end message
closes #7251
2022-08-19 06:39:51 +02:00
Matthias
70a77ba3d9 Check for "last" availability in PrecisionFilter
closes #7250
2022-08-18 20:07:50 +02:00
Matthias
85b43ec1a1 Remove double-check for "isolated margin" 2022-08-18 15:23:58 +02:00
Matthias
fde469a253 Remove unnecessary check 2022-08-18 14:53:44 +02:00
Matthias
075e9b8526 Log Exchange responses for set_leverage 2022-08-18 09:52:03 +02:00
Matthias
46e8d9a5e4 Reduce verbosity when whitelist is empty 2022-08-18 09:09:37 +02:00
Matthias
18fab86431 Add dock segment about webserver mode for docker 2022-08-18 08:32:15 +02:00
Matthias
0461a89348 Fix test failures 2022-08-18 07:20:49 +02:00
Matthias
66910bfe63 Don't fail if mark candles are missing
closes #7239
2022-08-17 20:01:57 +02:00
Matthias
3983368228 gateio futures is showing base currency in volume! 2022-08-17 14:51:48 +02:00
Matthias
83ca168bb8 Merge pull request #7216 from freqtrade/precise_calcs
Precise calcs
2022-08-17 14:32:02 +02:00
Matthias
c615e1bc62 Avoid loop error during ccxt tests 2022-08-17 14:31:40 +02:00
Matthias
b9667f50cf Fix random test failure 2022-08-17 14:05:12 +02:00
Matthias
e7902bffa0 Remove checks for dataprovider existance - it's available in all modes. 2022-08-17 10:57:25 +02:00
Matthias
e0883a4ea0 Improve doc wording 2022-08-17 10:55:59 +02:00
Matthias
819bc71941 Update docs for freqai docker container 2022-08-17 10:35:56 +02:00
Matthias
463cf66881 Fix bad image name 2022-08-17 10:32:29 +02:00
Matthias
c8d7c2caac Update CI to build and push freqAI images 2022-08-17 10:32:29 +02:00
Matthias
8d182768f9 stoploss should also use trimmed prices 2022-08-17 09:57:11 +02:00
Matthias
0b0e7eaf96 Mutex TTL Cache accesses which can be accessed by multiple threads
Apparently, cachetools is (intentionally) not threadsafe
when using the Caches directly.
It's therefore recommended to wrap these with an explicit lock to avoid
problems.

source: https://github.com/tkem/cachetools/issues/245

closes #7215
2022-08-16 19:48:21 +02:00
Matthias
24690c1918 Don't convert open_rate to precision
this may cause more problems than it solves.
2022-08-16 18:32:00 +02:00
Matthias
3b44dc52e1 Minor corrections 2022-08-16 18:10:48 +02:00
Matthias
ea6bc47d7a gateio default configs should specify unknown_fee_rate 2022-08-16 17:26:53 +02:00
Matthias
5dde011b31 Add unknown_fee_rate to full sample config 2022-08-16 17:23:49 +02:00
Matthias
a1e4fbf313 Run price_to_precision for dry-run orders 2022-08-16 17:23:49 +02:00
Matthias
1ac81aa316 Show message if fee update failed due to missing
closes #7234
2022-08-16 17:09:23 +02:00
Matthias
c865814a8e Merge pull request #7236 from freqtrade/fix-lgbm-warning
Fix input shape for LighGBMClassifier
2022-08-16 13:49:25 +02:00
robcaulk
4c0fda400f fix input shape warning for LGBMClassifier, add sample_weights/eval_weights 2022-08-16 11:41:53 +02:00
Matthias
fa89368c02 Add test for precision backpopulation 2022-08-16 11:11:52 +02:00
Matthias
96d2f61812 Properly round timestamps to avoid constant log messages 2022-08-16 10:22:59 +02:00
Matthias
b8c1cf0107 Fix test leakage if config is available 2022-08-16 10:19:19 +02:00
Matthias
15a1c59a91 Backtesting should cache precisionMode 2022-08-16 10:15:19 +02:00
Matthias
a73e4f8e41 Truncate amount before comparing for closure 2022-08-16 09:49:53 +02:00
Matthias
2fb7a3091d Improve backfill of precisions 2022-08-16 09:32:31 +02:00
Matthias
711b6b1a1a Merge branch 'develop' into precise_calcs 2022-08-16 09:29:39 +02:00
Matthias
a5b438e41e Run price_to_precision for dry-run orders 2022-08-16 09:28:23 +02:00
Matthias
1dd56e35d5 Ensure comparisions align when closing a trade 2022-08-16 08:21:02 +02:00
Matthias
e4b7bcaeab Fix some tests 2022-08-16 08:01:07 +02:00
Matthias
e818797427 Minor fix in amount_to_precision logic 2022-08-15 20:29:05 +02:00
Matthias
c0bdb71810 Update docstring 2022-08-15 20:06:29 +02:00
Matthias
f2b6ff910f Accept wrong pair in get_precision_amount 2022-08-15 20:05:22 +02:00
Matthias
09ee9089fb Merge pull request #6832 from freqtrade/feat/freqai
Freqai: an interface for users to build/train/backtest predictive models and run them live
2022-08-15 20:03:08 +02:00
Matthias
e6af9a6903 Allow empty precisionMode on conversions 2022-08-15 20:00:15 +02:00
Matthias
c3f159bd57 Add precision fields to database 2022-08-15 19:58:40 +02:00
Matthias
22241c55d5 Add methods to get precision_amount from markets 2022-08-15 19:56:25 +02:00
Matthias
15e85797c2 Simplify to_precision tests and imports 2022-08-15 08:51:15 +02:00
Matthias
6c32331740 Move precision calculations to standalone functions 2022-08-15 08:43:58 +02:00
Matthias
053ab12ba6 Merge pull request #7227 from freqtrade/dependabot/pip/develop/plotly-5.10.0
Bump plotly from 5.9.0 to 5.10.0
2022-08-15 08:11:38 +02:00
Matthias
c7e1719215 Fix interface import sorting 2022-08-15 06:53:02 +02:00
Matthias
686b72a82d Merge pull request #7229 from freqtrade/dependabot/pip/develop/ccxt-1.92.20
Bump ccxt from 1.91.93 to 1.92.20
2022-08-15 06:49:54 +02:00
Matthias
398b2946b5 Update test formatting 2022-08-15 06:49:28 +02:00
Matthias
490c3a30ed Merge pull request #7225 from freqtrade/dependabot/pip/develop/nbconvert-6.5.3
Bump nbconvert from 6.5.0 to 6.5.3
2022-08-15 06:32:54 +02:00
Matthias
3caf0f9df3 Merge pull request #7231 from freqtrade/dependabot/pip/develop/orjson-3.7.12
Bump orjson from 3.7.11 to 3.7.12
2022-08-15 06:32:31 +02:00
Matthias
b7b74a430c Merge pull request #7230 from freqtrade/dependabot/pip/develop/mkdocs-material-8.4.0
Bump mkdocs-material from 8.3.9 to 8.4.0
2022-08-15 06:31:40 +02:00
Matthias
4ae9b48d89 Merge pull request #7228 from freqtrade/dependabot/pip/develop/filelock-3.8.0
Bump filelock from 3.7.1 to 3.8.0
2022-08-15 06:31:19 +02:00
dependabot[bot]
dba7d7fd65 Bump ccxt from 1.91.93 to 1.92.20
Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.91.93 to 1.92.20.
- [Release notes](https://github.com/ccxt/ccxt/releases)
- [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg)
- [Commits](https://github.com/ccxt/ccxt/compare/1.91.93...1.92.20)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-15 04:29:20 +00:00
Matthias
a0c348cf97 Merge pull request #7226 from freqtrade/dependabot/pip/develop/numpy-1.23.2
Bump numpy from 1.23.1 to 1.23.2
2022-08-15 06:28:53 +02:00
Matthias
ce892d4cde Merge pull request #7224 from freqtrade/dependabot/pip/develop/sqlalchemy-1.4.40
Bump sqlalchemy from 1.4.39 to 1.4.40
2022-08-15 06:28:17 +02:00
dependabot[bot]
6fb5fbdd30 Bump orjson from 3.7.11 to 3.7.12
Bumps [orjson](https://github.com/ijl/orjson) from 3.7.11 to 3.7.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.7.11...3.7.12)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-15 03:01:56 +00:00
dependabot[bot]
bc79027cf4 Bump mkdocs-material from 8.3.9 to 8.4.0
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 8.3.9 to 8.4.0.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/8.3.9...8.4.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-15 03:01:51 +00:00
dependabot[bot]
2581acd75e Bump filelock from 3.7.1 to 3.8.0
Bumps [filelock](https://github.com/tox-dev/py-filelock) from 3.7.1 to 3.8.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.7.1...3.8.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-15 03:01:36 +00:00
dependabot[bot]
baa0af68b2 Bump plotly from 5.9.0 to 5.10.0
Bumps [plotly](https://github.com/plotly/plotly.py) from 5.9.0 to 5.10.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.9.0...v5.10.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-15 03:01:33 +00:00
dependabot[bot]
025ff27dd2 Bump numpy from 1.23.1 to 1.23.2
Bumps [numpy](https://github.com/numpy/numpy) from 1.23.1 to 1.23.2.
- [Release notes](https://github.com/numpy/numpy/releases)
- [Changelog](https://github.com/numpy/numpy/blob/main/doc/RELEASE_WALKTHROUGH.rst)
- [Commits](https://github.com/numpy/numpy/compare/v1.23.1...v1.23.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-15 03:01:29 +00:00
dependabot[bot]
96c279f86c Bump nbconvert from 6.5.0 to 6.5.3
Bumps [nbconvert](https://github.com/jupyter/nbconvert) from 6.5.0 to 6.5.3.
- [Release notes](https://github.com/jupyter/nbconvert/releases)
- [Commits](https://github.com/jupyter/nbconvert/compare/6.5...6.5.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-15 03:01:22 +00:00
dependabot[bot]
4b708caa6a Bump sqlalchemy from 1.4.39 to 1.4.40
Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 1.4.39 to 1.4.40.
- [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases)
- [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst)
- [Commits](https://github.com/sqlalchemy/sqlalchemy/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-15 03:01:19 +00:00
robcaulk
3f6d427084 add a check for number of training features in tests 2022-08-14 21:46:37 +02:00
robcaulk
006b11e5d5 fix leftover bug in indicator population 2022-08-14 21:42:55 +02:00
robcaulk
8961b8d560 merge in inference timer and historic predictions handling improvements. 2022-08-14 20:31:15 +02:00
robcaulk
ad846cdb76 fix lock bug, update docstring 2022-08-14 20:24:29 +02:00
Matthias
464d99808f Update doc table formatting 2022-08-14 18:22:01 +02:00
Matthias
d442383a15 Fix ta-lib install script 2022-08-14 18:17:17 +02:00
Matthias
a29402ddde Rename and move analysis_lock to data_kitchen 2022-08-14 17:23:14 +02:00
Matthias
3a9ec76c91 Move "freqai.lock" to backend to simplify user interface 2022-08-14 17:19:50 +02:00
Matthias
a5e96881f4 slightly update doc wording 2022-08-14 17:08:29 +02:00
Matthias
c08a89378d Merge pull request #7192 from AchmadFathoni/patch_conda_ta-lib
Add script for patching conda libta-lib
2022-08-14 09:46:33 +02:00
Matthias
e7513c96b3 install py-find-1st from conda forge
closes #7193
2022-08-14 09:36:38 +02:00
Matthias
24f1dc4ecc Update patched ta-lib install for conda 2022-08-14 09:06:04 +02:00
Matthias
044cf8bb2e Allow new whitelist combination in "button" commands 2022-08-14 08:41:25 +02:00
Matthias
22ac291c3a Merge pull request #7211 from ecoppen/rpc/whitelist_options
Optional /whitelist args - sorted, nobase
2022-08-14 08:26:21 +02:00
Robert Caulk
c9c128f781 finalize logo, improve doc, improve algo overview, fix base tensorflowmodel for mypy 2022-08-14 02:49:01 +02:00
Matthias
8d9284a524 Fix docs edit button 2022-08-13 20:20:09 +02:00
Matthias
7a2b4dbb99 Fix docs edit button 2022-08-13 20:16:36 +02:00
robcaulk
58de20af0f make BaseClassifierModel. Add predict_proba to lightgbm 2022-08-13 20:07:31 +02:00
robcaulk
31be707cc8 clean up code, add docstrings 2022-08-13 19:40:24 +02:00
robcaulk
3e38c1b0bd take dynamic sized tail off historic_predictions as return dataframe to strategy. 2022-08-13 19:40:24 +02:00
robcaulk
7d448fd4ac allow fit_live_predictions access to current pair 2022-08-13 19:40:24 +02:00
robcaulk
1f192be43b avoid denormalizing labels twice 2022-08-13 19:40:24 +02:00
robcaulk
b1b76a2dbe debug classifier with predict proba 2022-08-13 19:40:24 +02:00
robcaulk
23cc21ce59 add predict_proba to base classifier, improve historic predictions handling 2022-08-13 19:40:24 +02:00
Matthias
61acbf21d0 Fix broken telegram tests 2022-08-13 15:46:06 +02:00
Matthias
7075b00e20 Remove odd dry run stoploss behavior
closes #7208
2022-08-13 11:37:23 +02:00
Matthias
7c18ec4053 Add missing key to "full" config sample 2022-08-13 11:24:55 +02:00
Matthias
e09fbe9e53 Improve test resiliance 2022-08-13 11:17:22 +02:00
Matthias
d36da95941 Fix bad import 2022-08-13 11:07:58 +02:00
Matthias
82ac8cb41f Add freqai backtesting_load test 2022-08-13 10:48:57 +02:00
Matthias
0b92c30abd Fix typo in test file 2022-08-13 10:19:46 +02:00
Matthias
5aaab75d1c Add test for dynamic_pairlist_expand 2022-08-13 10:18:57 +02:00
Matthias
1ac6ec1446 Fix failing test... 2022-08-13 09:56:21 +02:00
Matthias
b682fc446e Graciously fail if strategy has freqAI code, but freqAI is not enabled. 2022-08-13 09:53:18 +02:00
Matthias
c190d57f1a Test populate_any_indicator interface 2022-08-13 09:48:59 +02:00
Matthias
3918f4abbd Simplify strategy interface by removing explicit self.freqai_info assignment 2022-08-13 09:27:56 +02:00
Matthias
3b827ee60a Add "freqai.enabled" flag to disable freqAI via config flag
aligns with how other optional modules work in freqtrade.
2022-08-13 09:24:04 +02:00
Matthias
49989012ab Bump catboost requirement to latest 2022-08-13 09:20:58 +02:00
Matthias
f6545ebdb8 Disallow backtesting with --strategy-list for now. 2022-08-13 09:10:03 +02:00
Matthias
e3a5b97b45 Update recalc_from_trades to use FtPrecise 2022-08-13 08:43:56 +02:00
Matthias
9513c39a17 Fix migration rounding test 2022-08-13 08:43:56 +02:00
Matthias
3bcb47d75d Remove usage of Decimal 2022-08-13 08:43:56 +02:00
Matthias
902afc2f02 Use FtPrecise in interest calculation 2022-08-13 08:43:56 +02:00
Matthias
da253f12fe Bump CCXT to required version 2022-08-13 08:43:56 +02:00
Matthias
0e61c2d057 Replace Decimal with FtPrecise in trade_model 2022-08-13 08:43:56 +02:00
Matthias
df701b5862 Merge branch 'develop' into feat/freqai 2022-08-13 08:43:24 +02:00
ecoppen
2312b86a66 Update telegram-usage.md
Add the optional arguments to the documentation.
2022-08-12 19:59:08 +01:00
ecoppen
ccc0ad6f64 fix - reload whitelist
Should fix the issue, if not I'll move development to a different computer and get local testing running properly.
2022-08-12 19:58:41 +01:00
ecoppen
923f73a516 nobase -> baseonly 2022-08-12 19:56:46 +01:00
robcaulk
fb4b73ce89 ensure dates are saved 2022-08-12 12:03:44 +02:00
Matthias
b427c7ff13 Use diff. close time to avoid buggy behavior 2022-08-12 07:28:19 +00:00
Matthias
d93bb82193 Add more Commits to failing test 2022-08-12 08:19:40 +02:00
Matthias
aa1bf2adbd Try fix windows testfailure 2022-08-12 06:43:34 +02:00
Matthias
cc885e25ac Improve NAN Handling in RPC 2022-08-11 20:16:07 +02:00
Matthias
de690b0a69 Use PEP440 compatible versioning 2022-08-11 20:08:40 +02:00
Matthias
dd4e44931e Improve NAN handling in RPC module 2022-08-11 15:02:52 +00:00
Matthias
f7502bcc92 slightly update dca_short test 2022-08-11 11:35:24 +00:00
robcaulk
2cae3c42e6 remove trade database analyzer, clean up a bit 2022-08-10 17:43:06 +02:00
ecoppen
ace9626483 Update tests for sorted and nobase
Tests for PR #7211
2022-08-10 15:04:24 +01:00
ecoppen
c0d60c63ab Optional /whitelist args - sorted, nobase
Added two optional arguments for whitelist - `sorted` for alphabetical order and `nobase` for displaying the whitelist without base currency e.g. /USDT.

Updated help with optional commands.

Added a space in an unrelated help message.
2022-08-10 14:56:38 +01:00
Matthias
ed004236ce Add float initializer to FtPrecise 2022-08-10 11:54:07 +00:00
Matthias
e7cb1b7375 Wrap Precise into FtPecise 2022-08-10 11:26:06 +00:00
robcaulk
91d0c91287 improve docs 2022-08-10 11:56:42 +02:00
Matthias
adc8ee88e2 Move periodicCache to Utils package 2022-08-10 08:57:19 +00:00
Matthias
573964b19f Dry Market orders should update "remaining" 2022-08-10 07:12:56 +02:00
Matthias
53251e7140 Merge pull request #7194 from freqtrade/rpc/partial_forceexit
Partial forceExit
2022-08-10 07:12:40 +02:00
Matthias
ce2c9bf26d Slight renaming of variable 2022-08-10 06:44:41 +02:00
Matthias
736884c5a9 Orders should be allowed to have empty fill/remaining values 2022-08-09 20:43:58 +02:00
Matthias
b5c5a95b64 FTX: Use conditionalOrders endpoint to get proper stop-market order id
closes #7165
2022-08-09 20:09:35 +02:00
robcaulk
4289c5c684 update freqai logo 2022-08-09 16:51:57 +02:00
robcaulk
5a16d5a512 Deactivate database analyzer if user does not use sqlite 2022-08-09 16:36:22 +02:00
robcaulk
e7de812948 Allow user to user pair_dict for persistent storage of custom data 2022-08-09 16:03:10 +02:00
robcaulk
aef086b02e Improved dict typing, timeframe parser, collect dates associated with training data points 2022-08-09 15:30:25 +02:00
Matthias
02646a4a08 Update scikit-learn in freqai deps 2022-08-09 06:23:16 +02:00
Matthias
9a82898d6b Merge branch 'develop' into feat/freqai 2022-08-09 06:22:57 +02:00
Matthias
77b3b8a134 Use main exchange instead of creating a separate instance. 2022-08-08 18:34:11 +00:00
Matthias
20b4134787 Properly exclude catboost in ARM 2022-08-08 18:15:18 +00:00
Matthias
8a18609be4 Merge pull request #7201 from freqtrade/dependabot/pip/develop/types-requests-2.28.8
Bump types-requests from 2.28.6 to 2.28.8
2022-08-08 07:18:27 +02:00
Matthias
0c7d862aae types-requests bump pre-commit 2022-08-08 06:54:00 +02:00
Matthias
05fb4de68b Merge pull request #7198 from freqtrade/dependabot/pip/develop/flake8-5.0.4
Bump flake8 from 5.0.1 to 5.0.4
2022-08-08 06:53:09 +02:00
Matthias
21649712a9 Merge pull request #7202 from freqtrade/dependabot/pip/develop/ccxt-1.91.93
Bump ccxt from 1.91.55 to 1.91.93
2022-08-08 06:52:14 +02:00
Matthias
001b6c087a Merge pull request #7199 from freqtrade/dependabot/pip/develop/scikit-learn-1.1.2
Bump scikit-learn from 1.1.1 to 1.1.2
2022-08-08 06:50:09 +02:00
Matthias
77b6025f12 Merge pull request #7200 from freqtrade/dependabot/pip/develop/jsonschema-4.9.1
Bump jsonschema from 4.9.0 to 4.9.1
2022-08-08 06:49:49 +02:00
dependabot[bot]
71c88244fe Bump ccxt from 1.91.55 to 1.91.93
Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.91.55 to 1.91.93.
- [Release notes](https://github.com/ccxt/ccxt/releases)
- [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg)
- [Commits](https://github.com/ccxt/ccxt/compare/1.91.55...1.91.93)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-08 03:01:38 +00:00
dependabot[bot]
97c077171a Bump types-requests from 2.28.6 to 2.28.8
Bumps [types-requests](https://github.com/python/typeshed) from 2.28.6 to 2.28.8.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-08 03:01:28 +00:00
dependabot[bot]
a45a35f38c Bump jsonschema from 4.9.0 to 4.9.1
Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.9.0 to 4.9.1.
- [Release notes](https://github.com/python-jsonschema/jsonschema/releases)
- [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.9.0...v4.9.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-08 03:01:25 +00:00
dependabot[bot]
7fd3f98ae8 Bump scikit-learn from 1.1.1 to 1.1.2
Bumps [scikit-learn](https://github.com/scikit-learn/scikit-learn) from 1.1.1 to 1.1.2.
- [Release notes](https://github.com/scikit-learn/scikit-learn/releases)
- [Commits](https://github.com/scikit-learn/scikit-learn/compare/1.1.1...1.1.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-08 03:01:20 +00:00
dependabot[bot]
11a2eb6cc5 Bump flake8 from 5.0.1 to 5.0.4
Bumps [flake8](https://github.com/pycqa/flake8) from 5.0.1 to 5.0.4.
- [Release notes](https://github.com/pycqa/flake8/releases)
- [Commits](https://github.com/pycqa/flake8/compare/5.0.1...5.0.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-08 03:01:16 +00:00
robcaulk
ea64f43e52 bring back auto DF resizing for okx 2022-08-08 01:13:13 +02:00
robcaulk
67c722c9c8 fix asyncio bug 2022-08-07 14:48:39 +02:00
Matthias
e48e82232d Force response API to js to fix faulty system configs
closes #7147
2022-08-07 10:42:56 +02:00
Matthias
0b2104fc7a Properly increment the api version 2022-08-07 10:13:36 +02:00
Matthias
5182f755f1 Add debug setup documentation
closes #7167
2022-08-07 10:08:48 +02:00
Matthias
6ded2d5b7c Improve forceexit API test 2022-08-07 09:47:11 +02:00
Matthias
d3780b931c Add test passing leverage to execute_entry 2022-08-07 09:47:11 +02:00
Matthias
d1998f7ed0 Fix forceexit calling 2022-08-07 09:47:11 +02:00
Matthias
eff8cd7ecb Add leverage to force_entry 2022-08-07 09:47:11 +02:00
Matthias
daf015d007 extract nested force_exit function to private instance function 2022-08-07 09:47:11 +02:00
Matthias
82aecc81f3 Accept parameters to forceexit 2022-08-07 09:47:11 +02:00
Achmad Fathoni
aaa5349003 Add script for patching conda libta-lib 2022-08-07 13:44:09 +07:00
Matthias
78e129034e Update docs to specify trading limit behaviour
closes #7183
2022-08-06 17:59:08 +02:00
robcaulk
eb8bde37c1 Add lightgbm classifier, add classifier check test, fix classifier bug. 2022-08-06 17:51:21 +02:00
Matthias
bfa859e618 Remove unnecessary method (simplify) 2022-08-06 17:46:58 +02:00
Matthias
5250189f77 Add Rollback function to Trade
simplifies Session work
2022-08-06 17:03:49 +02:00
Matthias
47a30047eb Fix typo 2022-08-06 15:03:10 +02:00
Matthias
b16f57cb0d Minor stylistic fixes 2022-08-06 14:55:46 +02:00
Robert Caulk
c172ce1011 improve flexibility of user defined prediction dataframe 2022-08-06 13:51:19 +02:00
Matthias
45d68222a1 Reduce verbosity of Fiat Converter 2022-08-06 13:18:40 +02:00
Robert Caulk
fdc82f8302 add doc section for classifier 2022-08-06 09:45:26 +02:00
Matthias
f8f1ade163 Reduce function complexity by extracting message sending 2022-08-06 09:21:11 +02:00
Matthias
2687633941 Test iterative sending of /status 2022-08-06 09:16:04 +02:00
Matthias
b12dd15f4f Send multiple messages in /status if required 2022-08-06 09:10:12 +02:00
Robert Caulk
07763d0d4f add classifier, improve model naming scheme 2022-08-06 08:33:55 +02:00
Robert Caulk
ce8fbbf743 ensure loading historical df matches frequi indices 2022-08-06 07:25:59 +02:00
robcaulk
60d782e5c5 remove unnecessary function 2022-08-05 21:31:32 +02:00
robcaulk
a42a060ab5 fix DB once and for all. Make DBSCAN more efficient and robust. 2022-08-05 21:29:03 +02:00
Robert Caulk
a3799c4d5d start frequi with historical data if available 2022-08-05 18:27:47 +02:00
robcaulk
29b7b014e5 fix bug in DB path initialization 2022-08-05 18:19:26 +02:00
robcaulk
db1d367941 fix bug associated to fit_live_predictions_candles 2022-08-05 13:46:20 +02:00
robcaulk
26de992d20 ensure user sets startup candles in backtesting mode 2022-08-05 12:23:14 +02:00
robcaulk
05ec5c5e54 generalize database url path for any db type 2022-08-05 12:19:29 +02:00
Matthias
9545402452 Improve defaults for config builder 2022-08-05 11:58:09 +02:00
Matthias
29e41cc817 Update docs to reflect correct result
closes #7181
2022-08-05 11:15:44 +02:00
Matthias
7675187c37 Use telegram message length to avoid constants 2022-08-05 07:31:19 +02:00
Matthias
cffc769549 Fix /profit endpoint calculations for partial sells
* don't recalculate for closed trades
* include realized_profit in the calculation

part of #7178
2022-08-05 07:26:41 +02:00
Matthias
c6e121ffb4 Update tests with correct usdt mock trades 2022-08-05 07:21:46 +02:00
OGSK
a8541d86fb Edit index of custom_stake_amount 2022-08-05 06:25:21 +02:00
OGSK
debc73b654 Edit Typo Custom-stake-amount
Edit Custom-stake-amount to `custom_stake_amount`
2022-08-05 06:25:08 +02:00
Matthias
c2a3e2776e Merge pull request #7180 from freqtrade/dependabot/docker/python-3.10.6-slim-bullseye
Bump python from 3.10.5-slim-bullseye to 3.10.6-slim-bullseye
2022-08-05 06:24:00 +02:00
dependabot[bot]
df4a5a7573 Bump python from 3.10.5-slim-bullseye to 3.10.6-slim-bullseye
Bumps python from 3.10.5-slim-bullseye to 3.10.6-slim-bullseye.

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-05 03:02:12 +00:00
Robert Caulk
51a6b4289f improve DBSCAN performance for subsequent trainings 2022-08-04 17:41:58 +02:00
Robert Caulk
fe1b8515a8 fix bug in DBSCAN, update doc 2022-08-04 17:00:59 +02:00
Matthias
55360b4c08 Merge pull request #7174 from stash86/patch-3
Fix typo
2022-08-04 16:27:22 +02:00
Stefano Ariestasia
febd809119 Fix typo
adjust_trade_position should return stake_amount, not amount
2022-08-04 20:55:52 +09:00
robcaulk
29225e4baf add DBSCAN outlier detection feature, add supporting documentation 2022-08-04 12:15:16 +02:00
Matthias
778833f90e Modify comment in new test-strategies to point out their purpose 2022-08-04 07:17:26 +02:00
Matthias
95327750dc Final abs. profit should not be doubled in rpc messages 2022-08-04 07:07:54 +02:00
robcaulk
eae82d0222 fix bug with database url during backtesting. comment out example trade db analysis. 2022-08-03 16:17:57 +02:00
robcaulk
95d3009a95 give user ability to analyze live trade dataframe inside custom prediction model. Add documentation to explain new functionality 2022-08-02 20:14:02 +02:00
Matthias
9df10c6b5b Merge pull request #7155 from freqtrade/dependabot/pip/develop/scipy-1.9.0
Bump scipy from 1.8.1 to 1.9.0
2022-08-01 19:54:20 +02:00
Matthias
ae0d6f63fa Version bump ccxt to 1.91.55
closes #7151
2022-08-01 19:43:13 +02:00
Matthias
87e5460aed Merge pull request #7157 from freqtrade/dependabot/pip/develop/types-requests-2.28.6
Bump types-requests from 2.28.3 to 2.28.6
2022-08-01 09:46:34 +02:00
Matthias
895ebbfd18 Exclude aarch64 from catboost requirements 2022-08-01 07:34:27 +00:00
Matthias
694bea133b Merge pull request #7156 from freqtrade/dependabot/pip/develop/flake8-5.0.1
Bump flake8 from 4.0.1 to 5.0.1
2022-08-01 08:39:06 +02:00
Matthias
3b90bdf980 Merge pull request #7160 from freqtrade/dependabot/pip/develop/jsonschema-4.9.0
Bump jsonschema from 4.7.2 to 4.9.0
2022-08-01 07:02:30 +02:00
Matthias
d75e0a9820 Fix Flake8 errors after flake update 2022-08-01 06:43:59 +02:00
Matthias
707a4e7c9e types-requests bump pre-commit 2022-08-01 06:41:08 +02:00
dependabot[bot]
f3154a4313 Bump jsonschema from 4.7.2 to 4.9.0
Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.7.2 to 4.9.0.
- [Release notes](https://github.com/python-jsonschema/jsonschema/releases)
- [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.7.2...v4.9.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-01 04:35:30 +00:00
Matthias
e9b7e1e600 Merge pull request #7161 from freqtrade/dependabot/pip/develop/urllib3-1.26.11
Bump urllib3 from 1.26.10 to 1.26.11
2022-08-01 06:34:37 +02:00
Matthias
70dcff3b23 Merge pull request #7154 from freqtrade/dependabot/pip/develop/ccxt-1.91.52
Bump ccxt from 1.91.29 to 1.91.52
2022-08-01 06:34:16 +02:00
Matthias
dce16909b4 Merge pull request #7162 from freqtrade/dependabot/github_actions/develop/pypa/gh-action-pypi-publish-1.5.1
Bump pypa/gh-action-pypi-publish from 1.5.0 to 1.5.1
2022-08-01 06:33:52 +02:00
Matthias
f82724bbc1 Merge pull request #7158 from freqtrade/dependabot/pip/develop/orjson-3.7.11
Bump orjson from 3.7.8 to 3.7.11
2022-08-01 06:33:34 +02:00
robcaulk
3013282dbf remove non-catboost stuff from schema 2022-08-01 05:39:38 +02:00
dependabot[bot]
97064a9ce3 Bump pypa/gh-action-pypi-publish from 1.5.0 to 1.5.1
Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.5.0 to 1.5.1.
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.5.0...v1.5.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-01 03:13:38 +00:00
dependabot[bot]
79b650258e Bump urllib3 from 1.26.10 to 1.26.11
Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.10 to 1.26.11.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/1.26.11/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/1.26.10...1.26.11)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-01 03:02:02 +00:00
dependabot[bot]
ed230dd750 Bump orjson from 3.7.8 to 3.7.11
Bumps [orjson](https://github.com/ijl/orjson) from 3.7.8 to 3.7.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.7.8...3.7.11)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-01 03:01:52 +00:00
dependabot[bot]
372be54252 Bump types-requests from 2.28.3 to 2.28.6
Bumps [types-requests](https://github.com/python/typeshed) from 2.28.3 to 2.28.6.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-01 03:01:46 +00:00
dependabot[bot]
b4ded59c63 Bump flake8 from 4.0.1 to 5.0.1
Bumps [flake8](https://github.com/pycqa/flake8) from 4.0.1 to 5.0.1.
- [Release notes](https://github.com/pycqa/flake8/releases)
- [Commits](https://github.com/pycqa/flake8/compare/4.0.1...5.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-01 03:01:43 +00:00
dependabot[bot]
a75fa26caf Bump scipy from 1.8.1 to 1.9.0
Bumps [scipy](https://github.com/scipy/scipy) from 1.8.1 to 1.9.0.
- [Release notes](https://github.com/scipy/scipy/releases)
- [Commits](https://github.com/scipy/scipy/compare/v1.8.1...v1.9.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-01 03:01:38 +00:00
dependabot[bot]
7a696f58f9 Bump ccxt from 1.91.29 to 1.91.52
Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.91.29 to 1.91.52.
- [Release notes](https://github.com/ccxt/ccxt/releases)
- [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg)
- [Commits](https://github.com/ccxt/ccxt/compare/1.91.29...1.91.52)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-01 03:01:30 +00:00
robcaulk
946d4c7cfc fix trailing whitespace for flake8 2022-07-31 18:39:46 +02:00
robcaulk
4e68626bcb ensure convolutional window is prepended for frequi consistency 2022-07-31 17:51:19 +02:00
robcaulk
d830105605 *BREAKING CHANGE* remove unnecessary arguments from populate_any_indicators(), accommodate tests 2022-07-31 17:05:29 +02:00
robcaulk
153336d424 move corr_pairlist expansion to after expand_pairlist() 2022-07-31 15:45:28 +02:00
Matthias
659870312d Use JSON Schema validation for freaAI schema validation 2022-07-31 15:23:27 +02:00
Matthias
cbb05354a8 Add install variant for freqai 2022-07-31 15:10:01 +02:00
Kavinkumar
a4bada3ebe Partial exit using average price (#6545)
Introduce Partial exits
2022-07-31 14:19:04 +02:00
robcaulk
61693f6c8b fix tests after changing config_example file 2022-07-31 13:20:11 +02:00
robcaulk
e6ebc0443e make single generalized config for freqai. update docs to reflect that. 2022-07-31 13:08:43 +02:00
Matthias
369c6da5d8 Merge pull request #7146 from freqtrade/fix/liquidation
Update liquidation price handling
2022-07-31 08:09:54 +02:00
Matthias
15424169ad Merge pull request #7108 from rzrymiak/develop
Added description heading to README.md
2022-07-31 07:10:37 +02:00
rzrymiak
09e5fb2f55 Removed description header 2022-07-30 22:37:46 +00:00
Robert Caulk
c2eaa3d2cd add image of algorithmic overview to doc 2022-07-30 18:51:00 +02:00
Matthias
bad15f077c Simplify fetch_positions by using already existing method 2022-07-30 17:49:06 +02:00
Matthias
dc82675f00 Add Test for liquidation in stop-loss-reached 2022-07-30 17:28:19 +02:00
Matthias
fc31c890e3 Merge pull request #7135 from freqtrade/rpc/sendmsg
Strategy allow rpc messages
2022-07-30 16:15:00 +02:00
Matthias
d046f0cc5e Improve method wording for liquidation price setter 2022-07-30 16:11:31 +02:00
Matthias
dba7a7257d Use stop_or_liquidation instead of stop_loss 2022-07-30 16:10:16 +02:00
Matthias
845cecd38f Add stoploss or liquidation property 2022-07-30 16:10:16 +02:00
Matthias
4da96bc511 Update docs 2022-07-30 16:10:16 +02:00
Matthias
15752ce3c2 Rename set_stoploss method to be fully private 2022-07-30 16:10:16 +02:00
Matthias
ff4cc5d316 Revamp liquidation test to actually make sense 2022-07-30 16:10:16 +02:00
Matthias
9852733ef7 Improve tests to align with modified logic 2022-07-30 16:10:16 +02:00
Matthias
f57ecb1861 Simplify adjust_stop test 2022-07-30 16:10:16 +02:00
Matthias
8711b7d99f Liquidations cannot be rejected. 2022-07-30 16:10:16 +02:00
Matthias
995be90f91 Liquidation should be a separate exit type 2022-07-30 16:10:16 +02:00
robcaulk
dd8288c090 expose full parameter set for SVM outlier detection. Set default shuffle to false to improve reproducibility 2022-07-30 13:40:05 +02:00
Matthias
d70650b074 Add note for plot-dataframe and current-whitelist
closes #7142
2022-07-30 08:20:22 +02:00
robcaulk
f22b140782 fix backtesting bug, undo move of label stat calc, fix example strat exit logic 2022-07-29 17:27:35 +02:00
robcaulk
08d3ac7ef8 add keras and conv_width to schema and documentation 2022-07-29 08:49:35 +02:00
robcaulk
59624181bd isort BaseRegressionModel imports 2022-07-29 08:23:44 +02:00
robcaulk
c84d54b35e Fix typing issue, avoid using .get() when unnecessary, convert to fstrings 2022-07-29 08:12:50 +02:00
Matthias
efbd83c56d Small type and typo fixes in freqai_interface 2022-07-28 07:24:30 +02:00
Matthias
a2a0d35a24 Update missing typehints 2022-07-28 07:07:40 +02:00
Matthias
3273881282 Merge branch 'develop' into feat/freqai 2022-07-28 06:36:38 +02:00
Matthias
cc3ead9d7b Set required_profit for stoploss guard, allowing to ignore small stoplosses.
closes #7076
2022-07-27 19:52:39 +02:00
Matthias
f31106dc61 Minor comment fixes 2022-07-27 07:27:24 +02:00
Matthias
31ddec8348 Add missing test to confirm backtesting won't send messages 2022-07-27 06:51:56 +02:00
Matthias
2595e40e47 Remove unused test-strategy 2022-07-27 06:47:16 +02:00
Matthias
0adfa4d9ef Add tests for dataprovider send-message methods 2022-07-27 06:34:15 +02:00
Matthias
7bac054668 Add documentation and clarity for send_msg 2022-07-26 20:24:52 +02:00
Matthias
229e8864bb Add send_msg capability to dataprovider 2022-07-26 20:15:49 +02:00
Matthias
bc760b7eb2 Simplify small segment in datadrawer 2022-07-26 19:41:49 +02:00
Matthias
a0b9388757 Bump ccxt to 1.91.29
closes #7132
2022-07-26 17:57:25 +02:00
robcaulk
324e54c015 fix possible memory leak associated with Catboost Pool object 2022-07-26 17:29:29 +02:00
robcaulk
3f149c4067 fix return type in BaseTensorFlowModel 2022-07-26 16:01:54 +02:00
robcaulk
ad25a4cb56 reduce number of pair_dict lookups, remove coin_first 2022-07-26 15:58:40 +02:00
robcaulk
fb4e8430cd isort auto import sorting 2022-07-26 10:51:39 +02:00
robcaulk
e213d0ad55 isolate data_drawer functions from data_kitchen, accommodate tests, add new test 2022-07-26 10:24:14 +02:00
robcaulk
56b17e6f3c allow user to pass test_size = 0 and avoid using eval sets in prediction models 2022-07-25 19:40:13 +02:00
Matthias
4c68bec171 Fix problem in is_cancel_order_result_suitable
fixes #7119
2022-07-25 17:47:52 +02:00
Matthias
ea112fb583 Add test for empty order (cancelled order) 2022-07-25 17:47:28 +02:00
robcaulk
55cf378ec2 remove leftover breakpoint from test file 2022-07-25 17:13:24 +02:00
Robert Caulk
897f18a8c8 ensure proper integer type casting for timestamps. Add check test for backtesting subdaily time periods 2022-07-25 15:07:09 +02:00
Robert Caulk
7b105532d1 fix mypy error and add test for principal component analysis 2022-07-25 11:46:59 +02:00
Robert Caulk
4abc26b582 add test for follow_mode 2022-07-25 10:48:04 +02:00
Robert Caulk
c9d46a5237 finish bringing follow_mode up to date 2022-07-25 09:24:40 +02:00
Matthias
0806f253b1 Merge pull request #7125 from freqtrade/dependabot/pip/develop/types-python-dateutil-2.8.19
Bump types-python-dateutil from 2.8.18 to 2.8.19
2022-07-25 08:43:58 +02:00
Matthias
4b8132f3c6 Merge pull request #7128 from freqtrade/dependabot/pip/develop/mypy-0.971
Bump mypy from 0.961 to 0.971
2022-07-25 08:42:16 +02:00
Matthias
47b52d4bab Bump types-dateutil in pre-commit 2022-07-25 07:58:16 +02:00
dependabot[bot]
40969f20bf Bump types-python-dateutil from 2.8.18 to 2.8.19
Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.8.18 to 2.8.19.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-25 05:53:15 +00:00
dependabot[bot]
93340f546b Bump mypy from 0.961 to 0.971
Bumps [mypy](https://github.com/python/mypy) from 0.961 to 0.971.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.961...v0.971)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-25 05:53:10 +00:00
Matthias
b7f5beea40 Merge pull request #7124 from freqtrade/dependabot/pip/develop/mkdocs-1.3.1
Bump mkdocs from 1.3.0 to 1.3.1
2022-07-25 07:52:38 +02:00
Matthias
c0080f2241 Merge pull request #7126 from freqtrade/dependabot/pip/develop/types-requests-2.28.3
Bump types-requests from 2.28.1 to 2.28.3
2022-07-25 07:52:16 +02:00
Matthias
43343d0e55 Revert markdown to 3.3.7 2022-07-25 07:21:12 +02:00
Matthias
3ce46ff09e Bump types-requests in pre-commit 2022-07-25 07:19:21 +02:00
Matthias
fba3c3c649 Merge pull request #7127 from freqtrade/dependabot/pip/develop/ccxt-1.91.22
Bump ccxt from 1.90.89 to 1.91.22
2022-07-25 07:17:14 +02:00
Matthias
bc87171243 Merge pull request #7123 from freqtrade/dependabot/pip/develop/orjson-3.7.8
Bump orjson from 3.7.7 to 3.7.8
2022-07-25 07:17:00 +02:00
dependabot[bot]
f93a3a5fca Bump ccxt from 1.90.89 to 1.91.22
Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.90.89 to 1.91.22.
- [Release notes](https://github.com/ccxt/ccxt/releases)
- [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg)
- [Commits](https://github.com/ccxt/ccxt/compare/1.90.89...1.91.22)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-25 03:01:52 +00:00
dependabot[bot]
98d0ad76bf Bump types-requests from 2.28.1 to 2.28.3
Bumps [types-requests](https://github.com/python/typeshed) from 2.28.1 to 2.28.3.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-25 03:01:44 +00:00
dependabot[bot]
d5933fb2af Bump mkdocs from 1.3.0 to 1.3.1
Bumps [mkdocs](https://github.com/mkdocs/mkdocs) from 1.3.0 to 1.3.1.
- [Release notes](https://github.com/mkdocs/mkdocs/releases)
- [Commits](https://github.com/mkdocs/mkdocs/compare/1.3.0...1.3.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-25 03:01:37 +00:00
dependabot[bot]
1b49e45222 Bump orjson from 3.7.7 to 3.7.8
Bumps [orjson](https://github.com/ijl/orjson) from 3.7.7 to 3.7.8.
- [Release notes](https://github.com/ijl/orjson/releases)
- [Changelog](https://github.com/ijl/orjson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ijl/orjson/compare/3.7.7...3.7.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-25 03:01:32 +00:00
Robert Caulk
ab587747fb first fix for follower path bug 2022-07-24 23:32:24 +02:00
Matthias
520ee3f7a1 Convert freqAI into packages 2022-07-24 17:07:45 +02:00
Matthias
1885deb632 More docstring changes 2022-07-24 16:54:39 +02:00
Matthias
70b7a254af Update some areas to use default docstring formatting 2022-07-24 16:51:48 +02:00
Matthias
61c41fd919 Merge branch 'develop' into feat/freqai 2022-07-24 16:18:58 +02:00
Matthias
83cac7bee2 Improve some more tests by adding proper orders 2022-07-24 10:51:13 +02:00
Matthias
6e691a016d Use leverage-tiers loading in tests 2022-07-24 10:24:59 +02:00
Robert Caulk
88e10f7306 add exception for not passing timerange. Remove hard coded arguments for CatboostPredictionModels. Update docs 2022-07-24 09:01:23 +02:00
Robert Caulk
fff39eff9e fix multitarget bug 2022-07-24 08:42:50 +02:00
Matthias
95f5218ceb Reenable Catboost test (#7118)
* Reenable Catboost test

* Simplify freqAI tests, ensure they use a tempdir for modelstorage
2022-07-24 07:32:13 +02:00
Matthias
2eb1d18c2a Don't load leverage tiers when not necessary 2022-07-23 19:56:38 +02:00
robcaulk
f3d46613ee move prediction denormalization into datakitchen. remove duplicate associated code. avoid normalization/denormalization for string dtypes. 2022-07-23 17:14:33 +02:00
Matthias
81c1aa3c13 Update imports in freqAI sample strategies 2022-07-23 17:08:05 +02:00
Matthias
8a3cffcd1b Remove remaining CustomModel references 2022-07-23 17:08:05 +02:00
Matthias
62f7606d2c Update tests to new variant 2022-07-23 17:08:05 +02:00
Matthias
8fa6e8b4ba Remove freqAI model bridge in favor of self.freqai 2022-07-23 17:08:05 +02:00
robcaulk
c91e23dc50 let user avoid normalizing labels 2022-07-23 16:14:13 +02:00
Matthias
7682c9ace7 Update trade_close test to include orders 2022-07-23 15:27:52 +02:00
Matthias
24a786bedd Update rpc test to contain sell order 2022-07-23 15:23:24 +02:00
Matthias
80845807e1 Improve some test resiliance 2022-07-23 15:14:38 +02:00
Matthias
a02d02ac12 Enhance protections tests to have orders in mock trade 2022-07-23 14:43:52 +02:00
robcaulk
50d630a155 remove unnecessary comments from data_drawer.py 2022-07-23 13:35:44 +02:00
robcaulk
a1cff377ec add record of contribution to data_kitchen.py 2022-07-23 13:32:04 +02:00
robcaulk
c2d6a0e891 add record of contribution to doc and source 2022-07-23 13:04:06 +02:00
robcaulk
3acc869570 improve the dataframe key description, update outdated parts of doc 2022-07-23 12:42:24 +02:00
Matthias
5c4f60f376 Improve configuration table formatting and ordering 2022-07-23 09:11:22 +02:00
Matthias
e97468964a Add support for --timeframe-detail in hyperopt
fix #7070
2022-07-23 08:52:03 +02:00
Matthias
36dc9be7aa Update some docs wording 2022-07-22 20:27:25 +02:00
Matthias
32c3f62934 Fix documentation typo
closes #7115
2022-07-22 19:45:50 +02:00
robcaulk
5559e605b8 small PR conversation resolutions 2022-07-22 17:46:14 +02:00
robcaulk
40f00196eb use cloudpickle in place of pickle. define Paths once in data_drawer. 2022-07-22 17:37:51 +02:00
robcaulk
accc629e32 set separate table sections in doc 2022-07-22 12:44:43 +02:00
robcaulk
98c8a447b2 add LightGBMPredictionMultiModel 2022-07-22 12:40:51 +02:00
robcaulk
afcb0bec00 clean up obsolete comments, move remove_features_from_df to datakitchen 2022-07-22 12:29:20 +02:00
Matthias
0b21750e76 Reorder advanced topics 2022-07-22 07:22:06 +02:00
robcaulk
ac0f484918 add freqai logo to top of doc 2022-07-22 00:02:07 +02:00
robcaulk
3205788bce extend doc to include descriptions of the return values from FreqAI to the strategy 2022-07-21 22:11:46 +02:00
robcaulk
8033e0bf23 add counter to backtesting log so users know how many more pairs and how many more models will need to be trained 2022-07-21 13:22:12 +02:00
robcaulk
183dec866a remove ability to backtest open ended timeranges (safer) 2022-07-21 13:02:52 +02:00
robcaulk
e694ea1cfd make sure backtesting gets the populated indicators with slimmed down user strat 2022-07-21 12:48:09 +02:00
robcaulk
ca4dd58642 remove superceded function from datakitchen 2022-07-21 12:40:54 +02:00
robcaulk
8f86b0deaa *breaking change* simplify user strat by consolidating feature loops into backend 2022-07-21 12:24:22 +02:00
robcaulk
e7337728bf add separator in folder name just incase an asset ends in an integer 2022-07-21 11:25:28 +02:00
robcaulk
c9a6dc88a1 add parameter list/discriptions to doc 2022-07-21 11:11:36 +02:00
Matthias
6c5e48dd4f dev-dependencies should include freqAI 2022-07-21 07:26:44 +02:00
robcaulk
a99c126266 help windows builds pass freqai tests. Add freqai to README.md 2022-07-20 16:14:19 +02:00
robcaulk
4e5d60fdc9 match scikit-learn version to hyperopt required version 2022-07-20 15:54:22 +02:00
robcaulk
921a7ef216 add requirements-freqai.txt to builds 2022-07-20 15:51:25 +02:00
robcaulk
286bd0c40b follow string for adding a strat to tests/strategy/strats 2022-07-20 15:00:02 +02:00
robcaulk
c43935e82a create dedicated minimal freqai test strat 2022-07-20 14:39:28 +02:00
robcaulk
88d769d801 comment out problematic catboost test 2022-07-20 14:18:06 +02:00
robcaulk
d43c146676 add more tests for datakitchen functionalities, add regression tests for freqai_interface train/backtest 2022-07-20 12:56:46 +02:00
Matthias
78f77f6d35 Merge pull request #7101 from freqtrade/dependabot/pip/develop/markdown-3.4.1
Bump markdown from 3.3.7 to 3.4.1
2022-07-20 06:48:28 +02:00
rzrymiak
ac2e8d760e Added description heading to README.md 2022-07-19 14:24:44 -07:00
Matthias
b609dbcd86 Update mdx_truly_sane_lists to be compatible with markdown again 2022-07-19 19:51:03 +02:00
lolong
9c051958a6 Feat/freqai (#7105)
Vectorize weight setting, log training dates

Co-authored-by: robcaulk <rob.caulk@gmail.com>
2022-07-19 17:49:18 +02:00
robcaulk
714d9534b6 start adding tests 2022-07-19 16:16:44 +02:00
Matthias
75e190ff1d Update sell-test without filled buy order 2022-07-19 07:20:36 +02:00
lolong
ed0f8b1189 Improve FreqAI documentation (#7072)
Improve doc + some other small fixes

Co-authored-by: robcaulk <rob.caulk@gmail.com>
2022-07-18 11:57:52 +02:00
Matthias
99d5fbc9c0 Merge pull request #7102 from freqtrade/dependabot/pip/develop/types-requests-2.28.1
Bump types-requests from 2.28.0 to 2.28.1
2022-07-18 08:38:35 +02:00
Matthias
0daa9d3e57 Bump types-requests in pre-commit 2022-07-18 07:56:41 +02:00
Matthias
7365d23db8 Merge pull request #7099 from freqtrade/dependabot/pip/develop/fastapi-0.79.0
Bump fastapi from 0.78.0 to 0.79.0
2022-07-18 07:55:29 +02:00
Matthias
df538f9cd6 Merge pull request #7097 from freqtrade/dependabot/pip/develop/jsonschema-4.7.2
Bump jsonschema from 4.6.2 to 4.7.2
2022-07-18 07:54:55 +02:00
Matthias
9d261c88e6 Merge pull request #7098 from freqtrade/dependabot/pip/develop/pytest-asyncio-0.19.0
Bump pytest-asyncio from 0.18.3 to 0.19.0
2022-07-18 07:54:31 +02:00
Matthias
8a1c95247d Merge pull request #7100 from freqtrade/dependabot/pip/develop/ccxt-1.90.89
Bump ccxt from 1.90.88 to 1.90.89
2022-07-18 07:53:52 +02:00
dependabot[bot]
ea523136fc Bump types-requests from 2.28.0 to 2.28.1
Bumps [types-requests](https://github.com/python/typeshed) from 2.28.0 to 2.28.1.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-18 03:01:49 +00:00
dependabot[bot]
d2ef248781 Bump markdown from 3.3.7 to 3.4.1
Bumps [markdown](https://github.com/Python-Markdown/markdown) from 3.3.7 to 3.4.1.
- [Release notes](https://github.com/Python-Markdown/markdown/releases)
- [Commits](https://github.com/Python-Markdown/markdown/compare/3.3.7...3.4.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-18 03:01:43 +00:00
dependabot[bot]
f07ad7aa87 Bump ccxt from 1.90.88 to 1.90.89
Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.90.88 to 1.90.89.
- [Release notes](https://github.com/ccxt/ccxt/releases)
- [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg)
- [Commits](https://github.com/ccxt/ccxt/compare/1.90.88...1.90.89)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-18 03:01:40 +00:00
dependabot[bot]
cb63d5e3df Bump fastapi from 0.78.0 to 0.79.0
Bumps [fastapi](https://github.com/tiangolo/fastapi) from 0.78.0 to 0.79.0.
- [Release notes](https://github.com/tiangolo/fastapi/releases)
- [Commits](https://github.com/tiangolo/fastapi/compare/0.78.0...0.79.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-18 03:01:31 +00:00
dependabot[bot]
5f820ab0a6 Bump pytest-asyncio from 0.18.3 to 0.19.0
Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.18.3 to 0.19.0.
- [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases)
- [Changelog](https://github.com/pytest-dev/pytest-asyncio/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.18.3...v0.19.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-18 03:01:26 +00:00
dependabot[bot]
2c6fb617a6 Bump jsonschema from 4.6.2 to 4.7.2
Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.6.2 to 4.7.2.
- [Release notes](https://github.com/python-jsonschema/jsonschema/releases)
- [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.6.2...v4.7.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-18 03:01:23 +00:00
Robert Caulk
921f3899f0 revert pickle reading for historic predictions 2022-07-17 16:06:36 +02:00
Robert Caulk
41eeb99177 load pickle file for writing 2022-07-17 10:05:21 +02:00
Matthias
46be1b8778 Version bump ccxt to 1.90.88 2022-07-17 07:21:42 +02:00
Matthias
05a5ae4fcf Update plotting to use entry/exit terminology 2022-07-16 22:28:46 +02:00
Robert Caulk
9d184586f1 fix bug in historic prediction saving 2022-07-16 21:16:59 +02:00
Matthias
9347677c60 Uppdate pricecontours test to not recreate backtesting every loop
in hopes to fix random failure
2022-07-16 19:33:26 +02:00
Matthias
3bb4f2c7c2 Merge pull request #6780 from samgermain/dry-taker-or-maker
Dry run taker or maker fees
2022-07-16 18:15:02 +02:00
Matthias
f6bfd89cef Merge branch 'develop' into feat/freqai 2022-07-16 18:14:34 +02:00
Matthias
423af371c0 Simplify calculation by calling "get_fee" only once 2022-07-16 17:59:05 +02:00
Matthias
4172f92bfc simplify dry-run taker/maker selection 2022-07-16 17:25:13 +02:00
Matthias
8b2535a8da Update Typing for fees 2022-07-16 15:42:17 +02:00
Matthias
8d2e22f009 Merge branch 'develop' into pr/samgermain/6780 2022-07-16 15:35:00 +02:00
Matthias
004bf31142 Merge pull request #7093 from freqtrade/fix/gate_futures_stoposs
gateio futures - several fixes
2022-07-16 15:18:32 +02:00
Matthias
3eb2131d0b Merge pull request #7092 from freqtrade/fix/hyperopt_inherit
hyperopt inherit fix
2022-07-16 15:17:14 +02:00
Matthias
bf07d8fe87 Update test to properly patch/mock exchange 2022-07-16 13:57:12 +02:00
Matthias
357000c478 Extract exchange validation to separate method 2022-07-16 13:45:26 +02:00
Matthias
d03dfb3934 Oder cost is real cost (including leverage) 2022-07-16 13:14:21 +02:00
Matthias
ed64e4299b Stoploss orders should also be eligible to update closed fees 2022-07-16 13:14:21 +02:00
Matthias
415780a4fe gateio order cost is not in contracts
closes #7081
2022-07-16 13:14:21 +02:00
Matthias
7b8a5585dd Fetch 2ndary stoploss order once the order triggered. 2022-07-16 13:14:21 +02:00
Matthias
7c4dd4c48c Support fee cost as string
closes #7056
2022-07-16 13:14:21 +02:00
Matthias
40e2da10f3 Add hypeorpt cloudpickle magic
closes #7078
2022-07-16 11:49:33 +02:00
Matthias
e53e530874 Add test showing broken inheritance hyperopt 2022-07-16 11:49:33 +02:00
Matthias
2e642593e5 Update formatting of hyperopt_conf fixture 2022-07-16 11:47:32 +02:00
Matthias
29efe75a6f Update hyperoptable strategy to use V3 interface 2022-07-16 11:47:32 +02:00
Matthias
1c7f60103d Don't use master for publish CI action 2022-07-15 20:26:24 +02:00
Robert Caulk
4ef2ed2f1b Merge pull request #7085 from wagnercosta/feat/freqai
freqai: fix issue when bot restarts with same identifier, does not load predi…
2022-07-15 20:00:53 +02:00
Matthias
fada432f49 Pin markdown docs dependency 2022-07-15 19:48:12 +02:00
Matthias
b657a4df23 Improve hyperopt docs
part of #7088
2022-07-15 19:02:23 +02:00
Wagner Costa Santos
ca2029a46b fix issue when bot restarts with same identifier, does not load prediction history 2022-07-14 18:55:24 -03:00
Matthias
cdc58058d7 Add candletype to notebook example
closes #7084, closes #7073
2022-07-14 19:40:26 +02:00
robcaulk
4141d165ff add BaseTensorFlowModel class 2022-07-12 19:10:09 +02:00
robcaulk
ef409dd345 Add ground work for TensorFlow models, add protections from common mistakes 2022-07-12 18:09:17 +02:00
Robert Caulk
fea63fba12 Fix saving/loading historic predictions 2022-07-12 10:12:50 +02:00
Robert Caulk
8ce6b18318 start collecting indefinite history of predictions. Allow user to generate statistics on these predictions. Direct FreqAI to save these to disk and reload them if available. 2022-07-11 22:01:48 +02:00
Matthias
0669d93f56 Merge pull request #7068 from freqtrade/ccxt_ordertype_validations
Ccxt ordertype validations
2022-07-11 19:41:05 +02:00
Matthias
5c164efdb6 Also check for createLimitOrder as optionals 2022-07-11 16:09:12 +02:00
Matthias
b9ba94d644 Bump ccxt to 1.90.47 2022-07-11 16:07:58 +02:00
Matthias
bf992fd9df Add test for newly added functionality 2022-07-11 14:09:44 +02:00
Matthias
f9d3775d4c Move "candle" logic for message to telegram
this avoids calling this method unless necessary
2022-07-11 14:09:39 +02:00
Matthias
9a3a2f9013 Simplify adding candle to message 2022-07-11 13:55:32 +02:00
Matthias
8e8f026ea7 Telegram candle message should be configurable 2022-07-11 12:14:19 +02:00
Matthias
ed03ef47ef Merge branch 'develop' into pr/SurferAdmin/6916 2022-07-11 11:49:22 +02:00
Matthias
ec3179156c Revert unwanted changes. 2022-07-11 11:48:24 +02:00
Matthias
3fc92b1b21 Create BaseRegression model - designed to reduce code duplication across currently available models. 2022-07-11 11:33:59 +02:00
Matthias
64f89af69e Add Explicit test for "has" checks 2022-07-11 10:43:21 +02:00
Matthias
6ac1aa15f5 Reenable ccxt order checks 2022-07-11 10:36:19 +02:00
Matthias
f8e35d8760 Add TODO to disabled test 2022-07-11 10:30:05 +02:00
Matthias
523d8a84a8 skip "supports market order" for now until CCXT fixes their assignemnt bugs. 2022-07-11 10:22:51 +02:00
Matthias
7d6b3d0e02 Update hyperopt param docs to be clear that non-conclusive parameters will be ignored 2022-07-11 08:17:16 +02:00
Matthias
0600c4d70e Merge pull request #7064 from freqtrade/dependabot/pip/develop/urllib3-1.26.10
Bump urllib3 from 1.26.9 to 1.26.10
2022-07-11 08:16:58 +02:00
Matthias
2bba071b6a Merge pull request #7063 from freqtrade/dependabot/pip/develop/numpy-1.23.1
Bump numpy from 1.23.0 to 1.23.1
2022-07-11 08:16:39 +02:00
Matthias
a4901ae9a7 Merge pull request #7059 from freqtrade/dependabot/pip/develop/pre-commit-2.20.0
Bump pre-commit from 2.19.0 to 2.20.0
2022-07-11 08:16:01 +02:00
Matthias
04ec44edc3 Merge pull request #7065 from freqtrade/dependabot/pip/develop/python-rapidjson-1.8
Bump python-rapidjson from 1.6 to 1.8
2022-07-11 08:15:44 +02:00
Matthias
50d368f3ec Merge pull request #7060 from freqtrade/dependabot/pip/develop/cryptography-37.0.4
Bump cryptography from 37.0.2 to 37.0.4
2022-07-11 08:15:22 +02:00
dependabot[bot]
0bb8c8feba Bump python-rapidjson from 1.6 to 1.8
Bumps [python-rapidjson](https://github.com/python-rapidjson/python-rapidjson) from 1.6 to 1.8.
- [Release notes](https://github.com/python-rapidjson/python-rapidjson/releases)
- [Changelog](https://github.com/python-rapidjson/python-rapidjson/blob/master/CHANGES.rst)
- [Commits](https://github.com/python-rapidjson/python-rapidjson/compare/v1.6...v1.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-11 05:23:01 +00:00
Matthias
9b3032390c Merge pull request #7066 from freqtrade/dependabot/pip/develop/orjson-3.7.7
Bump orjson from 3.7.6 to 3.7.7
2022-07-11 07:22:01 +02:00
dependabot[bot]
c06b524b4e Bump urllib3 from 1.26.9 to 1.26.10
Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.9 to 1.26.10.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/1.26.10/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/1.26.9...1.26.10)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-11 05:16:14 +00:00
dependabot[bot]
7c6c2c4d6e Bump cryptography from 37.0.2 to 37.0.4
Bumps [cryptography](https://github.com/pyca/cryptography) from 37.0.2 to 37.0.4.
- [Release notes](https://github.com/pyca/cryptography/releases)
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/37.0.2...37.0.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-11 05:15:38 +00:00
dependabot[bot]
7b998378ce Bump numpy from 1.23.0 to 1.23.1
Bumps [numpy](https://github.com/numpy/numpy) from 1.23.0 to 1.23.1.
- [Release notes](https://github.com/numpy/numpy/releases)
- [Changelog](https://github.com/numpy/numpy/blob/main/doc/RELEASE_WALKTHROUGH.rst)
- [Commits](https://github.com/numpy/numpy/compare/v1.23.0...v1.23.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-11 05:15:37 +00:00
Matthias
2bc78fd045 Merge pull request #7062 from freqtrade/dependabot/pip/develop/jsonschema-4.6.2
Bump jsonschema from 4.6.1 to 4.6.2
2022-07-11 07:15:07 +02:00
dependabot[bot]
fa158ba8de Bump pre-commit from 2.19.0 to 2.20.0
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.19.0 to 2.20.0.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v2.19.0...v2.20.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-11 05:14:41 +00:00
Matthias
9d453ffa08 Merge pull request #7061 from freqtrade/dependabot/pip/develop/ccxt-1.90.41
Bump ccxt from 1.90.40 to 1.90.41
2022-07-11 07:14:39 +02:00
Matthias
6aac4f9990 Merge pull request #7058 from freqtrade/dependabot/pip/develop/mkdocs-material-8.3.9
Bump mkdocs-material from 8.3.8 to 8.3.9
2022-07-11 07:13:52 +02:00
Matthias
d5e45d9c43 Merge pull request #7057 from freqtrade/dependabot/pip/develop/pytest-mock-3.8.2
Bump pytest-mock from 3.8.1 to 3.8.2
2022-07-11 07:13:29 +02:00
dependabot[bot]
719fa6f8e1 Bump orjson from 3.7.6 to 3.7.7
Bumps [orjson](https://github.com/ijl/orjson) from 3.7.6 to 3.7.7.
- [Release notes](https://github.com/ijl/orjson/releases)
- [Changelog](https://github.com/ijl/orjson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ijl/orjson/compare/3.7.6...3.7.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-11 03:02:39 +00:00
dependabot[bot]
c98786a4f6 Bump jsonschema from 4.6.1 to 4.6.2
Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.6.1 to 4.6.2.
- [Release notes](https://github.com/python-jsonschema/jsonschema/releases)
- [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.6.1...v4.6.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-11 03:02:17 +00:00
dependabot[bot]
b1d34dba94 Bump ccxt from 1.90.40 to 1.90.41
Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.90.40 to 1.90.41.
- [Release notes](https://github.com/ccxt/ccxt/releases)
- [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg)
- [Commits](https://github.com/ccxt/ccxt/compare/1.90.40...1.90.41)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-11 03:02:12 +00:00
dependabot[bot]
5070a04a82 Bump mkdocs-material from 8.3.8 to 8.3.9
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 8.3.8 to 8.3.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/8.3.8...8.3.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>
2022-07-11 03:01:50 +00:00
dependabot[bot]
9086176f73 Bump pytest-mock from 3.8.1 to 3.8.2
Bumps [pytest-mock](https://github.com/pytest-dev/pytest-mock) from 3.8.1 to 3.8.2.
- [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.8.1...v3.8.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-11 03:01:47 +00:00
Matthias
494e0529d2 Update conftest for leverage tiers 2022-07-10 19:31:14 +02:00
Robert Caulk
607455919e Change config parameter names to improve clarity and consistency throughout the code (!!breaking change, please check discord support channel for migration instructions or review templates/FreqaiExampleStrategy.py config_examples/config_freqai_futures.example.json file changes!!) 2022-07-10 12:35:44 +02:00
Matthias
819cc9c0e4 Fully align LightGBM with Catboost 2022-07-10 11:06:18 +02:00
Matthias
58b18770e3 Fix LightGBM missing argument in predict method 2022-07-10 11:05:35 +02:00
Matthias
9313a2d294 Update leverage tiers to latest version 2022-07-10 10:11:39 +02:00
Matthias
59b0fd1166 Merge pull request #7051 from freqtrade/gateio_fee_fix
Gateio fee fix
2022-07-10 09:45:24 +02:00
Matthias
ea5f41aa6d Version bump ccxt 2022-07-10 09:06:19 +02:00
Matthias
2e1061af64 Fix faulty LightGBM model 2022-07-09 08:21:42 +00:00
Matthias
aab59a8caf Bump ccxt to required version 2022-07-09 09:00:12 +02:00
Matthias
c98e7ea055 Revert allowing empty currency for futures 2022-07-09 08:57:15 +02:00
Matthias
b7167ec880 Fix wrong fee calclulation for gateio futures 2022-07-09 08:51:59 +02:00
Matthias
5b733a723d use "fees" for trades responses 2022-07-09 08:51:28 +02:00
Matthias
81f7d77d74 Allow fee currency to be empty for futures 2022-07-09 08:51:28 +02:00
Matthias
2499276fca Refactor calculate_fee_rate to take separate parameters instead of an "Order"
we passed in a trade object anyway
2022-07-09 08:51:28 +02:00
Matthias
e52f82b565 Add leverage to custom_stake_amount callback
closes #7047
2022-07-08 19:44:20 +02:00
Matthias
b39508f64d remove loadMarkets from "required" section,
it's now implied that all ccxt exchanges provide this method.
2022-07-07 19:44:54 +02:00
robcaulk
d9acdc9767 remove excess, increase no model warning clarity 2022-07-06 18:20:21 +02:00
Matthias
2dc46ca0b8 Add cost to partial test buy order 2022-07-06 07:12:13 +02:00
Matthias
dbc3376fe9 Add alias for gate to gateio 2022-07-06 07:12:13 +02:00
Matthias
da9dac64f2 Merge pull request #7045 from freqtrade/remove_abortion
replace the word "abortion" with "denied" in log messages
2022-07-05 20:41:13 +02:00
robcaulk
514f7d491c change rejected to denied 2022-07-05 12:58:43 +02:00
robcaulk
647f9b5460 replace the word abortion with rejected in log messages 2022-07-05 12:49:09 +02:00
robcaulk
4cac67fd66 Catch infrequent issue associated with grabbing first candle 2022-07-05 12:43:33 +02:00
Matthias
6f0721ae2b Update dry-order-fix to use sqlalchemy internals 2022-07-04 17:17:39 +02:00
Matthias
fe8083c7f8 Improve test for dry-run orderclosing 2022-07-04 17:17:01 +02:00
Matthias
6da3fa08e4 Update migrations to also support Postgres
closes #7038
2022-07-04 11:14:59 +02:00
Matthias
edc9a42a4c Merge pull request #7036 from freqtrade/dependabot/pip/develop/uvicorn-0.18.2
Bump uvicorn from 0.18.1 to 0.18.2
2022-07-04 09:11:37 +02:00
Matthias
14fb499a71 Merge pull request #7033 from freqtrade/dependabot/pip/develop/jsonschema-4.6.1
Bump jsonschema from 4.6.0 to 4.6.1
2022-07-04 09:11:19 +02:00
dependabot[bot]
5820fc3b44 Bump jsonschema from 4.6.0 to 4.6.1
Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.6.0 to 4.6.1.
- [Release notes](https://github.com/python-jsonschema/jsonschema/releases)
- [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.6.0...v4.6.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-04 05:55:44 +00:00
Matthias
fe0a64154d Merge pull request #7037 from freqtrade/dependabot/pip/develop/ccxt-1.89.96
Bump ccxt from 1.89.14 to 1.89.96
2022-07-04 07:54:52 +02:00
Matthias
d993216ec2 Merge pull request #7035 from freqtrade/dependabot/pip/develop/requests-2.28.1
Bump requests from 2.28.0 to 2.28.1
2022-07-04 07:54:36 +02:00
Matthias
f589e13cf2 Merge pull request #7031 from freqtrade/dependabot/pip/develop/prompt-toolkit-3.0.30
Bump prompt-toolkit from 3.0.29 to 3.0.30
2022-07-04 07:10:06 +02:00
dependabot[bot]
0a8a0c66b4 Bump requests from 2.28.0 to 2.28.1
Bumps [requests](https://github.com/psf/requests) from 2.28.0 to 2.28.1.
- [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.0...v2.28.1)

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-04 05:09:28 +00:00
Matthias
a7fa84f681 Merge pull request #7030 from freqtrade/dependabot/pip/develop/orjson-3.7.6
Bump orjson from 3.7.3 to 3.7.6
2022-07-04 07:09:09 +02:00
Matthias
05e8abb934 Merge pull request #7032 from freqtrade/dependabot/pip/develop/python-telegram-bot-13.13
Bump python-telegram-bot from 13.12 to 13.13
2022-07-04 07:08:22 +02:00
dependabot[bot]
9a8d03b1f5 Bump uvicorn from 0.18.1 to 0.18.2
Bumps [uvicorn](https://github.com/encode/uvicorn) from 0.18.1 to 0.18.2.
- [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.18.1...0.18.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-04 03:03:02 +00:00
dependabot[bot]
0555d7783c Bump python-telegram-bot from 13.12 to 13.13
Bumps [python-telegram-bot](https://github.com/python-telegram-bot/python-telegram-bot) from 13.12 to 13.13.
- [Release notes](https://github.com/python-telegram-bot/python-telegram-bot/releases)
- [Changelog](https://github.com/python-telegram-bot/python-telegram-bot/blob/v13.13/CHANGES.rst)
- [Commits](https://github.com/python-telegram-bot/python-telegram-bot/compare/v13.12...v13.13)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-04 03:02:40 +00:00
dependabot[bot]
b16bb23cc8 Bump prompt-toolkit from 3.0.29 to 3.0.30
Bumps [prompt-toolkit](https://github.com/prompt-toolkit/python-prompt-toolkit) from 3.0.29 to 3.0.30.
- [Release notes](https://github.com/prompt-toolkit/python-prompt-toolkit/releases)
- [Changelog](https://github.com/prompt-toolkit/python-prompt-toolkit/blob/master/CHANGELOG)
- [Commits](https://github.com/prompt-toolkit/python-prompt-toolkit/compare/3.0.29...3.0.30)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-04 03:02:34 +00:00
dependabot[bot]
92d189a84f Bump orjson from 3.7.3 to 3.7.6
Bumps [orjson](https://github.com/ijl/orjson) from 3.7.3 to 3.7.6.
- [Release notes](https://github.com/ijl/orjson/releases)
- [Changelog](https://github.com/ijl/orjson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ijl/orjson/compare/3.7.3...3.7.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-04 03:02:30 +00:00
Matthias
eda9464d30 Fix docs test 2022-07-03 19:54:29 +02:00
robcaulk
bd3a6ba2fe update backtesting to handle new output framework 2022-07-03 17:34:44 +02:00
robcaulk
8ac8d53c32 All LGBMRegressor model parameters are now set in config 2022-07-03 16:30:01 +02:00
robcaulk
a6077ac7f4 Merge feat/freqai into develop to get new features 2022-07-03 16:17:13 +02:00
Matthias
07aa372e2a Ensure bot_loop_start is called in hyperopt, too
closes #7001
2022-07-03 14:10:59 +02:00
Matthias
c5e6520fee Reorder methods in freqtradebot 2022-07-03 13:35:26 +02:00
robcaulk
4ff0ef7359 fix bug returning multiple targets for training 2022-07-03 12:15:59 +02:00
Matthias
f2fdc21374 Only use exit_tag if exit_type i exit_signal
closes #7027
2022-07-03 11:07:05 +02:00
Matthias
906c7b92fe Add enhance testcase to show problematic exit_reason behavior 2022-07-03 11:05:15 +02:00
robcaulk
ffb39a5029 black formatting on freqai files 2022-07-03 10:59:38 +02:00
Matthias
df8c9fc4e1 Merge pull request #7005 from freqtrade/dependabot/pip/develop/uvicorn-0.18.1
Bump uvicorn from 0.17.6 to 0.18.1
2022-07-03 07:52:09 +02:00
robcaulk
106131ff0f Rehaul organization of return values 2022-07-02 18:09:38 +02:00
robcaulk
93e1410ed9 first step toward cleaning output and enabling multimodel training per pair 2022-07-01 14:00:30 +02:00
robcaulk
6c7d02cb18 expose nu in the SVM outlier detection via svm_nu in config 2022-06-28 15:12:25 +02:00
Matthias
3c1380fbc6 Merge pull request #7009 from freqtrade/dependabot/pip/develop/types-python-dateutil-2.8.18
Bump types-python-dateutil from 2.8.17 to 2.8.18
2022-06-28 08:02:33 +02:00
Matthias
86f4077024 update dateutil precommit 2022-06-28 07:37:54 +02:00
dependabot[bot]
f2bc35e058 Bump types-python-dateutil from 2.8.17 to 2.8.18
Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.8.17 to 2.8.18.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

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

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

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

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-27 09:59:07 +00:00
Matthias
11a8151653 Merge pull request #7012 from freqtrade/dependabot/pip/develop/types-cachetools-5.2.1
Bump types-cachetools from 5.0.2 to 5.2.1
2022-06-27 11:54:43 +02:00
Matthias
e3abaaa1b7 Merge pull request #7019 from freqtrade/dependabot/pip/develop/pandas-1.4.3
Bump pandas from 1.4.2 to 1.4.3
2022-06-27 11:54:06 +02:00
robcaulk
7dfbd432d1 fix config saving bug, assign priorities to pairs in scanning, sleep the scanning loop to reduce CPU usage 2022-06-27 11:35:33 +02:00
dependabot[bot]
82ef97af7e Bump pandas from 1.4.2 to 1.4.3
Bumps [pandas](https://github.com/pandas-dev/pandas) from 1.4.2 to 1.4.3.
- [Release notes](https://github.com/pandas-dev/pandas/releases)
- [Changelog](https://github.com/pandas-dev/pandas/blob/main/RELEASE.md)
- [Commits](https://github.com/pandas-dev/pandas/compare/v1.4.2...v1.4.3)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-27 03:02:07 +00:00
robcaulk
68bafa9517 archive config to the model folder, filter out features before returning dataframe to strategy (to alleviate frequi issues)` 2022-06-26 23:03:48 +02:00
robcaulk
051b99791d reduce unnecessary verbosity, fix error on first training sweep, add LightGBMPredictionModel 2022-06-26 19:04:23 +02:00
Matthias
b5d0bc997d Clarify stoploss behavior when not defining offset
closes #6828
2022-06-24 17:25:33 +02:00
Matthias
ca88ea50c5 Merge pull request #6859 from mkavinkumar1/get
Removed None in dict.get()
2022-06-23 21:45:13 +02:00
Matthias
2b07d34611 Revert several undesired changes 2022-06-23 20:47:51 +02:00
Matthias
8bf0bf10c5 Merge branch 'develop' into pr/SmartManoj/6859 2022-06-23 20:43:35 +02:00
Matthias
ddc355feb6 Bump numpy from 1.22.4 to 1.23.0 2022-06-23 08:07:22 +00:00
Matthias
90feccf33c slightly update custom dockerfile with add. comment
closes #6994
2022-06-23 07:17:24 +02:00
Surfer
06571e99aa Merge branch 'freqtrade:develop' into develop 2022-06-22 09:38:23 -04:00
Matthias
53e5483daa Store StopPrice for dry-run orders
closes #6996
2022-06-22 06:31:51 +02:00
Surfer
cc4e5b26f0 Merge branch 'freqtrade:develop' into develop 2022-06-21 14:16:03 -04:00
Surfer Admin
e2a94d75b4 Merge branch 'develop' of https://github.com/Surfableio/freqtrade into develop 2022-06-21 14:06:56 -04:00
Surfer Admin
405ea74f16 stopPrice 2022-06-21 14:06:41 -04:00
Matthias
3a0f31fe89 Merge pull request #6914 from freqtrade/leverage_tiers_async
Leverage tiers async
2022-06-21 10:18:40 +02:00
Robert Caulk
852706cd6b Fix default behavior for expiration_hours 2022-06-21 08:12:51 +02:00
Matthias
eebd624baf Merge pull request #6988 from freqtrade/dependabot/pip/develop/mkdocs-material-8.3.6
Bump mkdocs-material from 8.3.4 to 8.3.6
2022-06-20 09:44:14 +02:00
dependabot[bot]
15fac746a8 Bump mkdocs-material from 8.3.4 to 8.3.6
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 8.3.4 to 8.3.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/8.3.4...8.3.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>
2022-06-20 06:59:58 +00:00
Matthias
7756c11454 Merge pull request #6991 from freqtrade/dependabot/pip/develop/ccxt-1.88.15
Bump ccxt from 1.87.12 to 1.88.15
2022-06-20 08:59:16 +02:00
Matthias
5e8bfb576b Merge pull request #6989 from freqtrade/dependabot/pip/develop/types-cachetools-5.0.2
Bump types-cachetools from 5.0.1 to 5.0.2
2022-06-20 08:07:06 +02:00
Matthias
3189b284c0 Fix tests condition 2022-06-20 08:04:34 +02:00
Matthias
165755fb33 Merge pull request #6990 from freqtrade/dependabot/pip/develop/colorama-0.4.5
Bump colorama from 0.4.4 to 0.4.5
2022-06-20 08:02:25 +02:00
Matthias
1cd2b0504a Run regular tests for 3.9 under other ubuntu systems 2022-06-20 07:15:15 +02:00
dependabot[bot]
e1e3a903f9 Bump ccxt from 1.87.12 to 1.88.15
Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.87.12 to 1.88.15.
- [Release notes](https://github.com/ccxt/ccxt/releases)
- [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg)
- [Commits](https://github.com/ccxt/ccxt/compare/1.87.12...1.88.15)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-20 05:07:35 +00:00
dependabot[bot]
996372b8f6 Bump colorama from 0.4.4 to 0.4.5
Bumps [colorama](https://github.com/tartley/colorama) from 0.4.4 to 0.4.5.
- [Release notes](https://github.com/tartley/colorama/releases)
- [Changelog](https://github.com/tartley/colorama/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/tartley/colorama/compare/0.4.4...0.4.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-20 05:06:39 +00:00
Matthias
50c19ece53 Fix ccxt test gateio flukyness 2022-06-20 07:05:51 +02:00
Matthias
f9668ede4a Fix CI Syntax error 2022-06-20 07:02:12 +02:00
Matthias
0804fc7a3a CI should run ccxt tests only once 2022-06-20 07:01:35 +02:00
Matthias
55fb7656df Update pre-commit cachetools 2022-06-20 06:58:41 +02:00
dependabot[bot]
8406010260 Bump types-cachetools from 5.0.1 to 5.0.2
Bumps [types-cachetools](https://github.com/python/typeshed) from 5.0.1 to 5.0.2.
- [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>
2022-06-20 03:01:26 +00:00
robcaulk
b35c64b6c0 fix bug in backtest, typo in example strat 2022-06-19 16:41:09 +02:00
Matthias
0d967f93ba Improve performance of some RPC calls
These don't need orders to be loaded. As a side-effect, this will
also reduce the strain on the database.
2022-06-19 16:13:04 +02:00
Matthias
0809f9aef6 Add offset to trade response 2022-06-18 19:27:05 +02:00
Matthias
bb61250bfe Merge pull request #6987 from freqtrade/profit_metrics
Profit metrics
2022-06-18 17:20:20 +02:00
Matthias
0168343b76 Add trading-volume to api schema 2022-06-18 16:53:25 +02:00
Matthias
474e6705e6 Add Profit factor to backtesting 2022-06-18 16:35:40 +02:00
Matthias
53bfa7931d Add rudimentary test for prior bug
Test fails without the fix in 8c46d19071
2022-06-18 16:32:22 +02:00
Matthias
8c46d19071 Fix backtesting bug
balance was never released on cancelled trades
2022-06-18 16:27:54 +02:00
robcaulk
3599d18ff6 fix bug in follow_mode, thanks @blood4rc 2022-06-18 12:05:28 +02:00
Matthias
b7e4dea6c5 Document new Profit metrics 2022-06-18 11:43:50 +02:00
Matthias
40c9abc7e1 Add trading volume to /profit output 2022-06-18 11:40:32 +02:00
Matthias
6a15d36d14 Add Drawdown and profit_factor to /profit
#6816
2022-06-18 11:14:28 +02:00
Matthias
d77ce468ea Add "dry" hint to buy/sell messages
part of #6962
2022-06-18 09:40:53 +02:00
Matthias
03815cb81b Use fstrings in telegram messaging 2022-06-18 09:23:16 +02:00
Matthias
d62273294d Update /help for /fx to align with actual command name
closes #6985
2022-06-18 09:10:33 +02:00
Matthias
017fd03180 Fix but with late entries in backtesting 2022-06-18 09:05:22 +02:00
Matthias
616bf315cb gateio: futures market orders require IOC to be set. 2022-06-17 23:02:39 +02:00
Matthias
fda8248d41 Gateio allow market orders on futures markets 2022-06-17 22:43:24 +02:00
robcaulk
6da7a98857 add docstrings to new functions, remove superceded code 2022-06-17 16:16:23 +02:00
robcaulk
5e914d5756 improve model youth by constantly scanning pairs in dry/live and always training new models. Fix bug in DI return values 2022-06-17 16:06:51 +02:00
robcaulk
f631ae911b add model expiration feature, fix bug in DI return values 2022-06-17 14:55:40 +02:00
Matthias
6bdf9c2a94 Simplify trade profit calculations further 2022-06-17 11:17:05 +00:00
Matthias
91f9818ae3 Simplify trade calculations 2022-06-17 09:53:29 +00:00
Matthias
d7770c507b Remove implicit use of certain rates in profit calculations 2022-06-17 07:00:42 +00:00
Matthias
76cae8e8e3 Update tests to always provide rate to profit calculations 2022-06-17 06:55:31 +00:00
Matthias
575b4ead1a Update Test with funding_fee 0 2022-06-17 06:29:17 +00:00
Matthias
14a859c190 Improve some documentation around futures / leverage 2022-06-16 19:50:13 +02:00
Matthias
61040c9f8e Fix freqAI dockerfile not running freqai code ... 2022-06-16 19:35:16 +02:00
robcaulk
0b0688a91e ensure scanning purges models 2022-06-16 16:12:38 +02:00
Matthias
121edc3e42 Add freqAI docker file 2022-06-16 12:36:15 +00:00
Surfer
36f7315481 Merge branch 'freqtrade:develop' into develop 2022-06-16 08:19:57 -04:00
robcaulk
c5de0c49e4 first functional scanning commit 2022-06-16 00:24:18 +02:00
robcaulk
4d472a0ea1 merging datarehaul into scanning branch 2022-06-16 00:22:49 +02:00
Matthias
8f32fa5cb3 Avoid exception on exchange recycling if __init__ fails 2022-06-15 20:13:07 +02:00
Matthias
f9e2e87346 Improve some formatting and typehints 2022-06-15 20:03:36 +02:00
Matthias
ec40e79362 Merge pull request #6874 from froggleston/buy_reasons
Buy reasons
2022-06-15 19:06:00 +02:00
Matthias
e2e6c790be Minor doc update 2022-06-15 16:50:25 +02:00
froggleston
4a5ed5a273 Fix tests 2022-06-15 11:48:57 +01:00
froggleston
14110bd5ca Merge branch 'buy_reasons' of github.com:froggleston/freqtrade into buy_reasons 2022-06-15 11:25:24 +01:00
froggleston
c391ca08de Change backtesting-analysis options to space separated lists 2022-06-15 11:25:06 +01:00
Matthias
29d8aeb9b3 Don't fail on invalid parameter 2022-06-15 07:13:47 +02:00
Matthias
3c62df6b86 Ensure the same timestamp is used for backtest and signal export 2022-06-15 06:53:52 +02:00
froggleston
6bb342f23a Add export-filename support 2022-06-14 16:54:27 +01:00
Matthias
01a68e1060 Remove unnecessary check and condition 2022-06-13 20:48:49 +02:00
Matthias
1ffee96bad Fix protection parameters not loading from parameter file
closes #6978
2022-06-13 19:59:05 +02:00
Matthias
d5fd1f9c38 Improve order filled handling 2022-06-13 13:24:48 +00:00
Matthias
848a5d85c6 Add small stability fix to test 2022-06-13 13:24:48 +00:00
Matthias
d7901132b8 Merge pull request #6973 from freqtrade/dependabot/pip/develop/plotly-5.8.2
Bump plotly from 5.8.0 to 5.8.2
2022-06-13 10:52:15 +02:00
Matthias
dca639cf26 Merge pull request #6970 from freqtrade/dependabot/pip/develop/pymdown-extensions-9.5
Bump pymdown-extensions from 9.4 to 9.5
2022-06-13 10:03:11 +02:00
Matthias
11603e70c9 Merge pull request #6972 from freqtrade/dependabot/pip/develop/orjson-3.7.2
Bump orjson from 3.7.1 to 3.7.2
2022-06-13 10:02:55 +02:00
dependabot[bot]
35adeb6412 Bump plotly from 5.8.0 to 5.8.2
Bumps [plotly](https://github.com/plotly/plotly.py) from 5.8.0 to 5.8.2.
- [Release notes](https://github.com/plotly/plotly.py/releases)
- [Changelog](https://github.com/plotly/plotly.py/blob/master/CHANGELOG.md)
- [Commits](https://github.com/plotly/plotly.py/compare/v5.8.0...v5.8.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-13 07:33:30 +00:00
dependabot[bot]
850f5d3842 Bump orjson from 3.7.1 to 3.7.2
Bumps [orjson](https://github.com/ijl/orjson) from 3.7.1 to 3.7.2.
- [Release notes](https://github.com/ijl/orjson/releases)
- [Changelog](https://github.com/ijl/orjson/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ijl/orjson/compare/3.7.1...3.7.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-13 07:32:39 +00:00
Matthias
9923462907 Merge pull request #6971 from freqtrade/dependabot/pip/develop/requests-2.28.0
Bump requests from 2.27.1 to 2.28.0
2022-06-13 09:32:03 +02:00
Matthias
46a214e41a Merge pull request #6969 from freqtrade/dependabot/pip/develop/mypy-0.961
Bump mypy from 0.960 to 0.961
2022-06-13 09:31:51 +02:00
dependabot[bot]
fdca583c67 Bump pymdown-extensions from 9.4 to 9.5
Bumps [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions) from 9.4 to 9.5.
- [Release notes](https://github.com/facelessuser/pymdown-extensions/releases)
- [Commits](https://github.com/facelessuser/pymdown-extensions/compare/9.4...9.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-13 07:07:39 +00:00
Matthias
29c38e0623 Merge pull request #6968 from freqtrade/dependabot/pip/develop/mkdocs-material-8.3.4
Bump mkdocs-material from 8.3.2 to 8.3.4
2022-06-13 09:07:02 +02:00
Matthias
a56ee4ee94 Merge pull request #6976 from freqtrade/dependabot/pip/develop/ccxt-1.87.12
Bump ccxt from 1.85.57 to 1.87.12
2022-06-13 09:06:46 +02:00
dependabot[bot]
cb2f89bca6 Bump requests from 2.27.1 to 2.28.0
Bumps [requests](https://github.com/psf/requests) from 2.27.1 to 2.28.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.27.1...v2.28.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-13 06:26:23 +00:00
dependabot[bot]
43b8b0a083 Bump mypy from 0.960 to 0.961
Bumps [mypy](https://github.com/python/mypy) from 0.960 to 0.961.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.960...v0.961)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-13 06:25:53 +00:00
dependabot[bot]
71f314d4c4 Bump ccxt from 1.85.57 to 1.87.12
Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.85.57 to 1.87.12.
- [Release notes](https://github.com/ccxt/ccxt/releases)
- [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg)
- [Commits](https://github.com/ccxt/ccxt/compare/1.85.57...1.87.12)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-13 06:25:35 +00:00
dependabot[bot]
ee0b9e3a5c Bump mkdocs-material from 8.3.2 to 8.3.4
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 8.3.2 to 8.3.4.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/8.3.2...8.3.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-13 06:25:18 +00:00
Matthias
5e4b3882e6 Merge pull request #6974 from freqtrade/dependabot/pip/develop/types-filelock-3.2.7
Bump types-filelock from 3.2.6 to 3.2.7
2022-06-13 08:25:10 +02:00
Matthias
4030a5df8e Merge pull request #6975 from freqtrade/dependabot/github_actions/develop/actions/setup-python-4
Bump actions/setup-python from 3 to 4
2022-06-13 08:24:20 +02:00
Matthias
e67d29cd2f Update more trades to use create_mock_trades 2022-06-13 07:17:13 +02:00
dependabot[bot]
70966c8a8f Bump actions/setup-python from 3 to 4
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 3 to 4.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-13 05:08:12 +00:00
Matthias
8fd245c28b Update pre-commit filelocktypes 2022-06-13 06:58:06 +02:00
Matthias
43c871f2f4 Use time-machine to stabilize time-sensitive tests 2022-06-13 06:49:31 +02:00
Matthias
390e600f55 Update statistics output 2022-06-13 06:46:34 +02:00
dependabot[bot]
40c7caac16 Bump types-filelock from 3.2.6 to 3.2.7
Bumps [types-filelock](https://github.com/python/typeshed) from 3.2.6 to 3.2.7.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-13 03:01:53 +00:00
Matthias
7619fd08d6 Update telegram tests to use mock_trades 2022-06-12 19:41:28 +02:00
Matthias
dff83ef620 Update telegram profit test to USDT 2022-06-12 17:30:01 +02:00
Matthias
56652c2b39 Improve test resiliance 2022-06-12 17:09:47 +02:00
Matthias
c981ad4608 Fix missing space 2022-06-12 08:31:02 +02:00
Matthias
75a248cf42 Fstring freqAI sample strategy, remove duplicate features 2022-06-11 19:56:37 +02:00
Matthias
2e1ed132f7 Merge pull request #6964 from freqtrade/rpc_rel_daily
Telegram / api daily relative profit
2022-06-11 19:31:32 +02:00
Matthias
c9761f4736 FreqUI should be installed by default when running setup.sh 2022-06-11 18:02:03 +02:00
Matthias
9c65fad73f Merge Pull request #6919 into develop 2022-06-11 17:49:32 +02:00
Matthias
4b70e03daa Add some rudimentary tsts for discord webhook integration 2022-06-11 17:49:23 +02:00
Matthias
fdfa94bcc3 make discord notifications fully configurable. 2022-06-11 17:43:46 +02:00
Matthias
f816c15e1e Update discord message format 2022-06-11 16:48:28 +02:00
Matthias
3a06337601 Update API to provide new values. 2022-06-11 11:28:45 +02:00
Matthias
9ba11f7bcc Update docs and tests for new daily command 2022-06-11 11:26:49 +02:00
Matthias
76827b31a9 Add relative profit to daily/weekly commands 2022-06-11 11:18:21 +02:00
Matthias
0a801c0223 Simplify daily RPC test 2022-06-11 08:58:36 +02:00
Matthias
1a5c3c587d Simplify weekly/monthly tests, convert to usdt 2022-06-11 08:53:37 +02:00
Matthias
ab6a306e07 Update daily test to USDT 2022-06-11 08:31:59 +02:00
Matthias
2c7c5f9a6e Update mock_usdt trade method 2022-06-10 20:47:52 +02:00
robcaulk
eb47c74096 merge datarehaul into main freqai branch 2022-06-10 20:26:19 +02:00
Matthias
76f87377ba Reduce decimals on FIAT daily column 2022-06-10 20:18:53 +02:00
Matthias
e8f8cd9d36 Merge pull request #6960 from italodamato/opt-ask-force-new-points
remove `random_state` condition when sampling random points
2022-06-10 19:45:36 +02:00
Italo
7142394121 remove random_state condition
otherwise the random sample always draws the same set of points
2022-06-10 09:46:45 +01:00
Matthias
ad3c01736e time aggregate to only query for data necessary
improves the query by not creating a full trade object.
2022-06-10 07:26:53 +02:00
Matthias
2218313f5c Merge pull request #6957 from freqtrade/rpc_consolidate_daily
Rpc consolidate daily
2022-06-10 06:39:59 +02:00
Matthias
2e67e2f911 Merge pull request #6958 from italodamato/opt-ask-force-new-points
don't overwrite is_random
2022-06-10 06:37:03 +02:00
Italo
dce9fdd0e4 don't overwrite is_random
this should fix issue #6746
2022-06-09 20:06:23 +01:00
Matthias
8fb743b91d improve variable wording 2022-06-09 20:13:26 +02:00
Matthias
dd32127014 Merge pull request #6944 from gaugau3000/develop
give extra info on rate origin for confirm_trade_*
2022-06-09 20:10:29 +02:00
Matthias
3c2ba99fc4 Improve sql cheatsheet docs 2022-06-09 19:57:56 +02:00
Matthias
a9c7ad8a0f Add warning about sqlite disabled foreign keys 2022-06-09 19:51:21 +02:00
Matthias
1ddd5f1901 Update docstring throughout the bot. 2022-06-09 19:41:08 +02:00
Matthias
88f8cbe172 Update tests to reflect new naming 2022-06-09 19:38:18 +02:00
Matthias
b211a5156f Add test for strategy_wrapper lazy loading 2022-06-09 19:36:15 +02:00
Matthias
a547001601 Reduce Telegram "unit" stats 2022-06-09 07:06:32 +02:00
Matthias
d4dd026310 Consolidate monthly stats to common method 2022-06-09 07:06:32 +02:00
Matthias
3cb15a2a54 Combine weekly and daily profit methods 2022-06-09 07:06:32 +02:00
Matthias
c550cd8b0d Simplify query in freqtradebot 2022-06-09 07:04:46 +02:00
Matthias
6a7ffd5483 Merge pull request #6952 from freqtrade/dependabot/docker/python-3.10.5-slim-bullseye
Bump python from 3.10.4-slim-bullseye to 3.10.5-slim-bullseye
2022-06-09 06:27:59 +02:00
dependabot[bot]
d265b8adb6 Bump python from 3.10.4-slim-bullseye to 3.10.5-slim-bullseye
Bumps python from 3.10.4-slim-bullseye to 3.10.5-slim-bullseye.

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-09 03:01:48 +00:00
Matthias
7eacb847b0 Fix backtesting bug when order is not replaced 2022-06-08 20:21:45 +02:00
gautier pialat
ac40ae89b9 give extra info on rate origin for confirm_trade_*
Documentation :
Take into consideration the market buy/sell rates use case for the confirm_trade_entry and confirm_trade_exit callback function
2022-06-08 00:20:33 +02:00
Matthias
381d64833d version-bump ccxt 2022-06-07 21:05:31 +02:00
robcaulk
d9b79d94e4 increase candle update flexibility to allow long sequential trainings that may last more than one candle 2022-06-07 20:57:10 +02:00
robcaulk
66800c7a45 ensure newest candles are always appended 2022-06-07 20:24:23 +02:00
robcaulk
f8f25e36ef update example config/strat 2022-06-07 19:54:45 +02:00
robcaulk
15d049cffe detect if upper tf candles are new or not, append if so. Correct the epoch for candle update check 2022-06-07 19:49:20 +02:00
Matthias
ca281c5722 Merge pull request #6943 from freqtrade/cancel_outdated_orders
Cancel orders which can no longer be found after several days
2022-06-07 18:05:15 +02:00
Matthias
9534d6cca1 Cancel orders which can no longer be found after several days 2022-06-07 07:03:40 +02:00
robcaulk
cab8f517b4 add lock to datadrawer 2022-06-07 01:07:30 +02:00
robcaulk
4b26b6aaec add lock to any historic data access 2022-06-07 00:54:18 +02:00
Robert Caulk
3c2e314ee5 Fix bugs 2022-06-06 16:26:07 -06:00
Robert Caulk
e6c5e737a2 Fix other bugs 2022-06-06 16:24:32 -06:00
Robert Caulk
bf19055e53 Update function spelling 2022-06-06 15:56:12 -06:00
Robert Caulk
2451ed8c88 Quick bug fix 2022-06-06 15:11:54 -06:00
Matthias
5007024f63 Merge pull request #6940 from freqtrade/bt_orders
Open orders should also be shown in the UI
2022-06-06 13:44:21 +02:00
Matthias
de79192432 Merge pull request #6941 from freqtrade/ci/concurrency
Update CI to use github actions builtin concurrency
2022-06-06 13:36:55 +02:00
Matthias
057be50941 Remove old concurrency method 2022-06-06 11:11:47 +02:00
Matthias
4eb6e80b4f Merge pull request #6936 from freqtrade/dependabot/pip/develop/jsonschema-4.6.0
Bump jsonschema from 4.5.1 to 4.6.0
2022-06-06 11:03:40 +02:00
Matthias
c00a7b65af Merge pull request #6937 from freqtrade/dependabot/pip/develop/types-requests-2.27.30
Bump types-requests from 2.27.29 to 2.27.30
2022-06-06 11:00:40 +02:00
Matthias
0b806af487 Add orders column to btresult 2022-06-06 10:59:10 +02:00
Matthias
82c5a6b29d Update CI to use concurrency 2022-06-06 10:57:33 +02:00
Matthias
ea9b68badd Add updating freqtrade to updating desc 2022-06-06 10:54:26 +02:00
Matthias
99f6c75c40 Bump types-requests precommit 2022-06-06 10:22:19 +02:00
Matthias
e2948857bf Merge pull request #6938 from freqtrade/dependabot/pip/develop/sqlalchemy-1.4.37
Bump sqlalchemy from 1.4.36 to 1.4.37
2022-06-06 10:21:38 +02:00
Matthias
767de555a6 Merge pull request #6934 from freqtrade/dependabot/pip/develop/filelock-3.7.1
Bump filelock from 3.7.0 to 3.7.1
2022-06-06 10:20:50 +02:00
Matthias
73043f2ccc Merge pull request #6933 from freqtrade/dependabot/pip/develop/orjson-3.7.1
Bump orjson from 3.6.8 to 3.7.1
2022-06-06 10:20:35 +02:00
Matthias
55cda53325 Merge pull request #6935 from freqtrade/dependabot/pip/develop/mkdocs-material-8.3.2
Bump mkdocs-material from 8.2.16 to 8.3.2
2022-06-06 10:20:08 +02:00
Matthias
a96dce0f8f Merge pull request #6939 from freqtrade/dependabot/pip/develop/ccxt-1.84.97
Bump ccxt from 1.84.39 to 1.84.97
2022-06-06 10:19:48 +02:00
dependabot[bot]
05922e9ebc Bump ccxt from 1.84.39 to 1.84.97
Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.84.39 to 1.84.97.
- [Release notes](https://github.com/ccxt/ccxt/releases)
- [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg)
- [Commits](https://github.com/ccxt/ccxt/compare/1.84.39...1.84.97)

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-06 03:02:07 +00:00
dependabot[bot]
963dc0221c Bump types-requests from 2.27.29 to 2.27.30
Bumps [types-requests](https://github.com/python/typeshed) from 2.27.29 to 2.27.30.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-06 03:01:59 +00:00
dependabot[bot]
35316ec068 Bump jsonschema from 4.5.1 to 4.6.0
Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.5.1 to 4.6.0.
- [Release notes](https://github.com/python-jsonschema/jsonschema/releases)
- [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.5.1...v4.6.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-06 03:01:55 +00:00
dependabot[bot]
6547f3aadb Bump mkdocs-material from 8.2.16 to 8.3.2
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 8.2.16 to 8.3.2.
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/8.2.16...8.3.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-06 03:01:52 +00:00
dependabot[bot]
04cb49b7e4 Bump filelock from 3.7.0 to 3.7.1
Bumps [filelock](https://github.com/tox-dev/py-filelock) from 3.7.0 to 3.7.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.7.0...3.7.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-06 03:01:48 +00:00
dependabot[bot]
786bc36163 Bump orjson from 3.6.8 to 3.7.1
Bumps [orjson](https://github.com/ijl/orjson) from 3.6.8 to 3.7.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.6.8...3.7.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-06 03:01:44 +00:00
Matthias
79107fd062 Add minimal order object serialization 2022-06-05 22:12:27 +02:00
Matthias
8369d5bedd Include open orders in json responses 2022-06-05 22:12:27 +02:00
Matthias
c0ff554d5b Cleanup old, left open dry-run orders 2022-06-05 22:12:27 +02:00
Matthias
f709222943 Properly close out orders in backtesting 2022-06-05 22:12:27 +02:00
Matthias
c499bb051f Allow empty unfilledtimeout for webserver mode 2022-06-05 19:41:17 +02:00
Matthias
a790bad1e4 Add entry_tag to leverage callback
closes #6929
2022-06-05 10:24:54 +02:00
Matthias
27bea580d4 Fix rest-client script's force_enter
closes #6927
2022-06-05 09:40:04 +02:00
robcaulk
d6b8801f41 fix follower bug 2022-06-05 04:40:58 +02:00
robcaulk
e8c0dcf9f3 add debug message to timerange 2022-06-03 17:14:07 +02:00
robcaulk
f2762e3b4b fix bug in return_values() 2022-06-03 16:58:51 +02:00
robcaulk
16b4a5b71f rehaul of backend data management - increasing performance by holding history in memory, reducing load on the ratelimit by only pinging exchange once per candle. Improve code readability. 2022-06-03 15:19:46 +02:00
robcaulk
15a971346d catch infinity values when filtering 2022-06-02 17:13:20 +02:00
Robert Caulk
7d41542f93 process_only_new_candles in examplestrat should be True, thanks @Bloodhunter4rc 2022-06-02 07:24:08 -06:00
robcaulk
fea39254d9 fix custom_exit (thanks @paranoidandy) 2022-06-02 14:58:45 +02:00
robcaulk
b37c31cc21 fix ta-lib issue with simultaneous method access 2022-06-02 14:37:40 +02:00
robcaulk
4ac6ef2972 make defining period intervals more user friendly and flexible 2022-06-02 13:45:29 +02:00
robcaulk
ace951bf7e another queue bug fix for fresh starts 2022-06-02 13:28:06 +02:00
Anuj Shah
eb4adeab4d fix flake8 issues 2022-06-02 11:19:29 +05:30
Anuj Shah
45c47bda60 refactor into discord rpc module 2022-06-01 21:14:48 +05:30
Anuj Shah
afd8e85835 feat: add support for discord notification 2022-06-01 15:54:32 +05:30
robcaulk
833d25bda0 Save data after queue reorg 2022-06-01 08:05:38 +02:00
robcaulk
0b0dd8dd80 Force high priority pair to be trained before anything else. 2022-06-01 07:55:05 +02:00
Surfer Admin
7fe8b7661d Display the signal candle analyzed in telegram. 2022-05-31 15:46:43 -04:00
Matthias
34a44b9dd2 Fix backtesting bug when canceling orders
closes #6911
2022-05-31 20:32:41 +02:00
Matthias
66edbcd3d5 Fix slight backtesting bug in edge-case scenarios 2022-05-31 20:08:34 +02:00
robcaulk
7523ed825e automatically detect maximum required data based on user fed indicators (to avoid NaNs in dataset for rolling indicators), add new config parameter for backtesting to let users increase their startup_candles to accommodate high timeframe indicators, add docs to explain all. Add new feature for automatic indicator duplication according to user defined intervals (exhibited in example strat and configs now). 2022-05-31 18:42:27 +02:00
Matthias
3549176370 Update missleading docstring
closes #6913
2022-05-31 17:52:45 +02:00
Matthias
88845f6d88 Fix cancel order deleting trade
if one order was successfully filled, the trade cannot be deleted.

closes #6907
2022-05-31 17:49:51 +02:00
Matthias
eee337c764 Merge pull request #6906 from freqtrade/params_to_instance
Params to instance
2022-05-31 16:18:48 +02:00
robcaulk
9b3b08a2bb let follower purge old model files 2022-05-31 15:37:38 +02:00
robcaulk
bac4ced382 Ensure follower predictions are persistent and uniquely stored 2022-05-31 14:35:04 +02:00
Matthias
ea537b32c7 Update tests for leverage_tier_loading 2022-05-31 11:40:14 +00:00
robcaulk
70adf55643 Automatically detect and change follower data_path to accommodate remote systems 2022-05-31 12:35:09 +02:00
robcaulk
0306f5ca13 Add autopurge feature so that FreqAI cleans up after itself when it no longer needs old models on disk 2022-05-31 11:58:21 +02:00
Matthias
cce8d1aa4d Update get_market_leverage_tiers to be async 2022-05-31 08:48:34 +00:00
Matthias
be6e0813db Remove --strategy from analysis test 2022-05-31 06:53:03 +02:00
robcaulk
45f4f0f603 ensure follower sends back null arrays in case leader hasnt created a model file yet 2022-05-31 01:48:48 +02:00
robcaulk
29d2f59f12 fix PCA bug 2022-05-31 00:40:45 +02:00
robcaulk
606f18e5c1 Add follow_mode feature so that secondary bots can be launched with the same identifier and load models trained by the leader 2022-05-30 21:35:48 +02:00
Matthias
c285ad0e2b Remove --strategy parameters, update docs 2022-05-30 20:26:24 +02:00
Matthias
d950b0acbe Update documentation about dynamic parameters 2022-05-30 18:18:01 +02:00
robcaulk
5b4c649d43 detect variable sized dataframes coming from strat, adjust our stored/returned data accordingly 2022-05-30 13:55:46 +02:00
robcaulk
e229902381 fix bug in previous commit 2022-05-30 12:48:22 +02:00
robcaulk
a20651efd8 Increase performance by only predicting on most recent candle instead of full strat provided dataframe. Collect predictions and store them so that we can feed true predictions back to strategy (so that frequi isnt updating historic predictions based on newly trained models). 2022-05-30 11:37:05 +02:00
Matthias
d8df9fdccf Merge pull request #6900 from freqtrade/dependabot/pip/develop/types-requests-2.27.29
Bump types-requests from 2.27.27 to 2.27.29
2022-05-30 08:36:39 +02:00
Matthias
8e2c7e1298 extract detect_parameters to separate function 2022-05-30 07:26:26 +02:00
Matthias
f323cbc769 Bump types-requests precommit 2022-05-30 07:23:05 +02:00
Matthias
b73fd0ac69 Merge pull request #6899 from freqtrade/dependabot/pip/develop/mypy-0.960
Bump mypy from 0.950 to 0.960
2022-05-30 07:22:39 +02:00
Matthias
5bf021be2e Enhance hyperoptable strategy to test instance parameters 2022-05-30 07:08:37 +02:00
Matthias
eaa656f859 Hyperoptable parameters can be instance attributes 2022-05-30 07:07:47 +02:00
dependabot[bot]
2b2967f34e Bump types-requests from 2.27.27 to 2.27.29
Bumps [types-requests](https://github.com/python/typeshed) from 2.27.27 to 2.27.29.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-30 04:54:54 +00:00
Matthias
7962092092 Merge pull request #6897 from freqtrade/dependabot/pip/develop/types-python-dateutil-2.8.17
Bump types-python-dateutil from 2.8.16 to 2.8.17
2022-05-30 06:54:21 +02:00
Matthias
386d3e0353 Rename stop/roi loading method 2022-05-30 06:52:44 +02:00
Matthias
ad8ff10a05 Minor doc changes 2022-05-30 06:32:46 +02:00
Matthias
41052b4e1e Bump types dateutil precommit 2022-05-30 06:28:03 +02:00
Matthias
8837e1937b Merge pull request #6896 from freqtrade/dependabot/pip/develop/python-telegram-bot-13.12
Bump python-telegram-bot from 13.11 to 13.12
2022-05-30 06:27:25 +02:00
Matthias
d83b204f4b Merge pull request #6901 from freqtrade/dependabot/pip/develop/ccxt-1.84.39
Bump ccxt from 1.83.62 to 1.84.39
2022-05-30 06:25:39 +02:00
Matthias
5d801ff287 Merge pull request #6898 from freqtrade/dependabot/pip/develop/mkdocs-material-8.2.16
Bump mkdocs-material from 8.2.15 to 8.2.16
2022-05-30 06:22:16 +02:00
dependabot[bot]
23fa00e29a Bump ccxt from 1.83.62 to 1.84.39
Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.83.62 to 1.84.39.
- [Release notes](https://github.com/ccxt/ccxt/releases)
- [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg)
- [Commits](https://github.com/ccxt/ccxt/compare/1.83.62...1.84.39)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-30 03:02:26 +00:00
dependabot[bot]
a937f36997 Bump mypy from 0.950 to 0.960
Bumps [mypy](https://github.com/python/mypy) from 0.950 to 0.960.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.950...v0.960)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-30 03:02:13 +00:00
dependabot[bot]
9366c1d36f Bump mkdocs-material from 8.2.15 to 8.2.16
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 8.2.15 to 8.2.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/8.2.15...8.2.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>
2022-05-30 03:02:03 +00:00
dependabot[bot]
e7c78529e9 Bump types-python-dateutil from 2.8.16 to 2.8.17
Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.8.16 to 2.8.17.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-30 03:01:58 +00:00
dependabot[bot]
b52fd0b4df Bump python-telegram-bot from 13.11 to 13.12
Bumps [python-telegram-bot](https://github.com/python-telegram-bot/python-telegram-bot) from 13.11 to 13.12.
- [Release notes](https://github.com/python-telegram-bot/python-telegram-bot/releases)
- [Changelog](https://github.com/python-telegram-bot/python-telegram-bot/blob/v13.12/CHANGES.rst)
- [Commits](https://github.com/python-telegram-bot/python-telegram-bot/compare/v13.11...v13.12)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-30 03:01:56 +00:00
robcaulk
2f1a2c1cd7 allow users to store data in custom formats, update spot config to reflect better target horizon to training period ratio 2022-05-30 02:12:31 +02:00
robcaulk
d59eac3321 revert a79032b 2022-05-29 21:33:38 +02:00
Matthias
f65df4901e Update doc clarity 2022-05-29 20:53:09 +02:00
robcaulk
a79032bf75 fixing bug in training queue 2022-05-29 20:19:32 +02:00
Matthias
056047f635 Fix --help 2022-05-29 20:07:02 +02:00
robcaulk
3f72263278 allow pairs deeper in the queue to get trained if the higher priority pairs dont need training 2022-05-29 20:02:43 +02:00
robcaulk
cc6cae47ec allow pairs deeper in the queue to get trained if the higher priority pairs dont need training 2022-05-29 19:49:43 +02:00
robcaulk
4eb4753e20 allow subdaily retraining for backtesting 2022-05-29 17:44:35 +02:00
froggleston
9a068c0b14 Add test for each analysis group, remove default table output if not indicator-list 2022-05-29 16:25:31 +01:00
froggleston
24b02127ec Update docs 2022-05-29 15:42:34 +01:00
Matthias
e6affcc23e Move parameter file loading to hyper-mixin 2022-05-29 16:39:52 +02:00
Matthias
1ee08d22d2 Delay parameter init
closes #6894
2022-05-29 16:39:52 +02:00
robcaulk
0aa7162055 ensure the prediction is reset in the pair_dict after any trade exit, not just custom_exit 2022-05-29 16:36:46 +02:00
robcaulk
fe36b08fce fix key error in example strat 2022-05-29 16:26:34 +02:00
robcaulk
ce365eb9e3 improve example strat so that it has dynamic buy and sell logic according to original prediction 2022-05-29 14:45:46 +02:00
froggleston
df1c36e5aa Change command name, use load_backtest_stats for strategy resolving 2022-05-29 11:54:27 +01:00
froggleston
c59209a01a Merge branch 'buy_reasons' of github.com:froggleston/freqtrade into buy_reasons 2022-05-29 11:20:32 +01:00
froggleston
e7c5818d16 First pass changes for cleaning up 2022-05-29 11:20:11 +01:00
Matthias
a875a7dc40 Use unified stopPrice for binance 2022-05-29 11:01:01 +02:00
Matthias
f64f2b1ad8 Fix /stats Formatting issue in multi-message settings 2022-05-29 10:34:22 +02:00
robcaulk
4eb29c8810 Dont reset pair priority if it doesnt successfully train 2022-05-28 18:34:26 +02:00
robcaulk
83dd453723 catch errors occuring on background thread, and make sure to keep the ball rolling. Improve pair retraining queue. 2022-05-28 18:26:19 +02:00
robcaulk
e54614fa2f remove remnants of single threaded version, ensure pair queue priority is checked before retraining 2022-05-28 14:55:07 +02:00
robcaulk
2a4d1e2d64 fix bug in setting new timerange for retraining 2022-05-28 12:23:26 +02:00
robcaulk
7870a86e9a fix live retraining bug 2022-05-28 11:38:57 +02:00
robcaulk
0bf915054d handle key check correctly 2022-05-28 11:22:32 +02:00
robcaulk
c5a16e91fb throw user error if user tries to load models but feeds the wrong features (while using PCA) 2022-05-28 11:11:41 +02:00
Matthias
3e7bf6a9ef Remove imports in test_strategy2 2022-05-27 19:31:34 +02:00
Matthias
b04fe5d4ee Simplify test v2 strategy 2022-05-27 19:30:14 +02:00
robcaulk
b8f9c3557b dirty dirty, dont look here (hacking a flag to avoid reloading leverage_tiers in dry/live) 2022-05-27 13:56:34 +02:00
robcaulk
891fb87712 give load_cached_data_for_updating the right flags to avoid redownloading data in dry/live 2022-05-27 13:38:22 +02:00
robcaulk
65fdebab75 let load_pairs_histories load futures candles in live 2022-05-27 13:01:33 +02:00
robcaulk
c080571b7a help futures go dry/live with auto download feature 2022-05-27 12:23:32 +02:00
Matthias
24cf044646 Fix bybit spot mode 2022-05-27 08:18:04 +00:00
robcaulk
8a501831d6 fix the error logic on previous commit 2022-05-27 01:15:55 +02:00
robcaulk
23c30dbc10 add error for user trying to backtest with backtest_period<1 2022-05-27 00:43:52 +02:00
robcaulk
6193205012 fix bug for target_mean/std array merging in backtesting 2022-05-26 21:07:50 +02:00
Matthias
43b7955fc2 Fully rely on pathlib 2022-05-26 19:37:55 +02:00
Matthias
682daa4e94 Reset logging mixin to avoid random test failure 2022-05-26 18:05:40 +02:00
froggleston
145faf9817 Use tmpdir for testing 2022-05-26 11:06:38 +01:00
Matthias
da970cca82 Merge pull request #6888 from stash86/patch-1
fix typo
2022-05-26 06:32:44 +02:00
Stefano Ariestasia
e1c6cf5f91 fix typo 2022-05-26 10:12:50 +09:00
Matthias
537d10c627 Improve some typing 2022-05-25 20:43:43 +02:00
Matthias
3e66275c98 Refactor bot_start to separate function
to be reused further ...
2022-05-25 20:01:21 +02:00
Matthias
023f817179 Improve wording for supported futures exchanges 2022-05-25 19:37:32 +02:00
robcaulk
ff531c416f reduce complexity inside start_download_data() in an effort to appease flake8 2022-05-25 15:31:50 +02:00
robcaulk
d79983c791 try to pass flake8 2022-05-25 14:55:19 +02:00
robcaulk
7593339c14 small cleanup 2022-05-25 14:42:46 +02:00
robcaulk
b79d4e8876 Allow user to go live and start from pretrained models (after a completed backtest) by simply reusing the identifier config parameter while dry/live. 2022-05-25 14:40:32 +02:00
robcaulk
7486d9d9e2 proper validation of freqai config parameters 2022-05-25 12:37:25 +02:00
Matthias
b2968df5dc Fix some type problems 2022-05-25 10:13:37 +00:00
robcaulk
7ff3258607 remove assertions, log error if user has not assigned freqai in config, fix stratify bug 2022-05-25 11:43:45 +02:00
robcaulk
35bed842cb cleanup, add clarity to comments and docstrings 2022-05-25 11:31:03 +02:00
froggleston
21e6c14e1e Final test changes 2022-05-25 10:08:03 +01:00
froggleston
f5c2930889 Presume that pytest will call the cleanup call 2022-05-25 09:58:38 +01:00
froggleston
2873ca6d38 Add cleanup, adjust _print_table for indicators, add rsi to test output 2022-05-25 09:57:12 +01:00
Matthias
9e4c68a5b4 Merge pull request #6887 from freqtrade/ci_strategyTemplates
Run CI against strategy templates
2022-05-25 09:13:18 +02:00
Matthias
43f726ba8f Run CI against different templates 2022-05-25 06:34:05 +00:00
froggleston
edd474e663 Another test fix attempt 2022-05-24 21:21:20 +01:00
froggleston
22b9805e47 Fix all tests 2022-05-24 21:04:23 +01:00
froggleston
3adda84b96 Update docs, add test 2022-05-24 20:27:15 +01:00
Matthias
d6773bc32c Merge pull request #6886 from freqtrade/fix/typing
Fix/typing
2022-05-24 19:41:59 +02:00
Matthias
a8ee77cd5e Simplify backtesting typechecking 2022-05-24 19:13:35 +02:00
robcaulk
58b5abbaa6 improve multithreaded training queue system 2022-05-24 15:28:38 +02:00
robcaulk
31ae2b3060 alleviate FutureWarning in sklearn about ensuring svm model features are passed with identical order 2022-05-24 14:46:16 +02:00
froggleston
8c03ebb78f Fix group 0 table, add pathlib.Path use 2022-05-24 12:48:13 +01:00
robcaulk
255d35976e add priority metadata to pairs to avoid a sync of train time + train period 2022-05-24 12:58:53 +02:00
froggleston
80c6190c05 Fix analyze_commands setup 2022-05-24 11:47:26 +01:00
froggleston
ae1ede58da Fix import order 2022-05-24 11:47:26 +01:00
froggleston
a1a09a802b Add analyze_commands 2022-05-24 11:47:25 +01:00
froggleston
9488e8992d First commit for integrating buy_reasons into FT 2022-05-24 11:47:25 +01:00
robcaulk
059c285425 paying closer attention to managing live retraining on separate thread without affecting prediction of other coins on master thread 2022-05-24 12:01:01 +02:00
Matthias
7f3853bbcd Merge pull request #6883 from freqtrade/makeProcessCandlesTrue
Change default value of process_only_new_candles to True since False …
2022-05-24 07:03:14 +02:00
Matthias
904f094b80 Don't reassign method, but implement it properly 2022-05-24 06:59:54 +02:00
Matthias
23e089061b Merge pull request #6870 from freqtrade/should_exit_list
Should exit list
2022-05-24 06:57:50 +02:00
Matthias
0a713faca8 Fix some type errors 2022-05-24 06:54:16 +02:00
Matthias
f1a72e448a Align interfaces and strategy templates 2022-05-24 06:54:16 +02:00
Matthias
3f68c3b68e Update some types 2022-05-24 06:54:16 +02:00
Matthias
502404c0cc Use pyproject.toml instead of setup.cfg 2022-05-24 06:54:16 +02:00
Matthias
7f4161ff78 Add typehints to strategy wrapper 2022-05-24 06:54:16 +02:00
Matthias
07ec3b27fe Add typing information to retrier decorator 2022-05-24 06:54:16 +02:00
robcaulk
b0d2d13eb1 improve data persistence/mapping for live/dry. This accommodates quick reloads after crash and handles multi-pair cleanly 2022-05-23 21:05:05 +02:00
Matthias
42ae8ba6fb Refactor hyperopt parameters to separate file 2022-05-23 20:18:09 +02:00
robcaulk
e1c068ca66 add config asserts, use .get method with default values for optional functionality, move data_cleaning_* to freqai_interface (away from user custom pred model) since it is controlled by config params. 2022-05-23 12:07:09 +02:00
robcaulk
5c4014ee62 Change default value of process_only_new_candles to True since False is an uncommon usecase for expert strategy devs 2022-05-23 10:24:58 +02:00
robcaulk
dede128648 set process_only_new_candles to true in example strat 2022-05-23 10:15:59 +02:00
robcaulk
ee3cdd0ffe more cleanup 2022-05-23 09:55:58 +02:00
Matthias
063fc5174d Merge pull request #6877 from freqtrade/dependabot/pip/develop/types-filelock-3.2.6
Bump types-filelock from 3.2.5 to 3.2.6
2022-05-23 09:20:50 +02:00
Matthias
34b1231df3 Bump filelock-precommit 2022-05-23 08:32:46 +02:00
dependabot[bot]
b88dfe4297 Bump types-filelock from 3.2.5 to 3.2.6
Bumps [types-filelock](https://github.com/python/typeshed) from 3.2.5 to 3.2.6.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 06:32:06 +00:00
Matthias
bb1e1a9680 Merge pull request #6880 from freqtrade/dependabot/pip/develop/scikit-learn-1.1.1
Bump scikit-learn from 1.1.0 to 1.1.1
2022-05-23 08:31:55 +02:00
Matthias
2b79398dba Merge pull request #6879 from freqtrade/dependabot/pip/develop/types-python-dateutil-2.8.16
Bump types-python-dateutil from 2.8.15 to 2.8.16
2022-05-23 08:31:03 +02:00
Matthias
f6e2c2c0da Merge pull request #6875 from freqtrade/dependabot/pip/develop/ccxt-1.83.62
Bump ccxt from 1.83.12 to 1.83.62
2022-05-23 08:30:42 +02:00
Matthias
cc3ec279c2 Bump dateutil types precommit 2022-05-23 06:57:49 +02:00
Matthias
734803aa44 Merge pull request #6882 from freqtrade/dependabot/pip/develop/types-requests-2.27.27
Bump types-requests from 2.27.25 to 2.27.27
2022-05-23 06:57:08 +02:00
dependabot[bot]
596aeec652 Bump scikit-learn from 1.1.0 to 1.1.1
Bumps [scikit-learn](https://github.com/scikit-learn/scikit-learn) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/scikit-learn/scikit-learn/releases)
- [Commits](https://github.com/scikit-learn/scikit-learn/compare/1.1.0...1.1.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 04:33:43 +00:00
Matthias
eb5fe9e3ae Merge pull request #6857 from froggleston/develop
Add support for fudging unavailable funding rates, allowing backtesti…
2022-05-23 06:31:51 +02:00
Matthias
66497c28e8 Bump pre-commit requests types 2022-05-23 06:28:11 +02:00
Matthias
c28cdc3d86 Merge pull request #6878 from freqtrade/dependabot/pip/develop/scipy-1.8.1
Bump scipy from 1.8.0 to 1.8.1
2022-05-23 06:26:55 +02:00
Matthias
8973554595 Merge pull request #6876 from freqtrade/dependabot/pip/develop/psutil-5.9.1
Bump psutil from 5.9.0 to 5.9.1
2022-05-23 06:25:37 +02:00
Matthias
26d5b22974 Merge pull request #6881 from freqtrade/dependabot/pip/develop/numpy-1.22.4
Bump numpy from 1.22.3 to 1.22.4
2022-05-23 06:25:13 +02:00
dependabot[bot]
7f5650699e Bump types-requests from 2.27.25 to 2.27.27
Bumps [types-requests](https://github.com/python/typeshed) from 2.27.25 to 2.27.27.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 03:01:48 +00:00
dependabot[bot]
34657639f8 Bump numpy from 1.22.3 to 1.22.4
Bumps [numpy](https://github.com/numpy/numpy) from 1.22.3 to 1.22.4.
- [Release notes](https://github.com/numpy/numpy/releases)
- [Changelog](https://github.com/numpy/numpy/blob/main/doc/HOWTO_RELEASE.rst.txt)
- [Commits](https://github.com/numpy/numpy/compare/v1.22.3...v1.22.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 03:01:46 +00:00
dependabot[bot]
ff9dcfe789 Bump types-python-dateutil from 2.8.15 to 2.8.16
Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.8.15 to 2.8.16.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 03:01:32 +00:00
dependabot[bot]
40f63ae51c Bump scipy from 1.8.0 to 1.8.1
Bumps [scipy](https://github.com/scipy/scipy) from 1.8.0 to 1.8.1.
- [Release notes](https://github.com/scipy/scipy/releases)
- [Commits](https://github.com/scipy/scipy/compare/v1.8.0...v1.8.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 03:01:30 +00:00
dependabot[bot]
f819fafa1c Bump psutil from 5.9.0 to 5.9.1
Bumps [psutil](https://github.com/giampaolo/psutil) from 5.9.0 to 5.9.1.
- [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.0...release-5.9.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 03:01:20 +00:00
dependabot[bot]
27019339b5 Bump ccxt from 1.83.12 to 1.83.62
Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.83.12 to 1.83.62.
- [Release notes](https://github.com/ccxt/ccxt/releases)
- [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg)
- [Commits](https://github.com/ccxt/ccxt/compare/1.83.12...1.83.62)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 03:01:15 +00:00
robcaulk
3587bd82e1 cleanup superceded code 2022-05-23 00:10:36 +02:00
robcaulk
af0cc21af9 Enable hourly/minute retraining in live/dry. Suppress catboost folder output. Update config + constants + docs to reflect updates. 2022-05-23 00:06:26 +02:00
Matthias
e3beaae8be update hyperopt typing 2022-05-22 19:32:32 +02:00
Matthias
0b5544ef9e Stoploss fill should fill as "filled" notification
Closes #6873
2022-05-22 19:18:12 +02:00
robcaulk
42d95af829 Aggregated commit. Adding support vector machine for outlier detection, improve user interface to dry/live, better standardization, fix various other bugs 2022-05-22 17:51:49 +02:00
Matthias
938a66511a Update Documentation for new confirm_trade_exit behavior 2022-05-22 11:28:11 +02:00
Matthias
3692fcd3d5 Improve exit signal sequence 2022-05-22 11:01:18 +02:00
Matthias
ce3bfd59f5 Add explicit should_sell test 2022-05-22 10:31:29 +02:00
Matthias
b7388557a9 Update interface tests 2022-05-22 10:20:01 +02:00
Matthias
bdb904e714 Should_exit should return all sell signals 2022-05-22 10:17:49 +02:00
Matthias
1315d02437 Fix startup sending "longed" messages for open stoplosses 2022-05-22 09:01:46 +02:00
Matthias
26d394ca74 Add liquidation Price to api response 2022-05-22 08:54:27 +02:00
Matthias
ea8fda0dee Slightly improve test 2022-05-22 08:36:28 +02:00
Matthias
1ff1e3b43d Merge pull request #6869 from freqtrade/update_levtiers
Update leveraged tiers
2022-05-22 08:35:02 +02:00
Matthias
f006978caf Be more explicit in default value 2022-05-21 17:35:49 +02:00
Matthias
681ef13174 Relax dry-run leverage test-case to simplify future updates 2022-05-21 16:23:29 +02:00
Matthias
97abcf4b32 Add documentation for leverage_tiers update 2022-05-21 16:10:00 +02:00
Matthias
963cc17c18 Update leveraged tiers 2022-05-21 16:05:00 +02:00
Matthias
0d388b561b Add test for "combine_funding_and_mark", fix bug 2022-05-21 09:03:30 +02:00
Matthias
2df42a3035 Move "funding fillup" logic to exchange class 2022-05-21 08:50:39 +02:00
Matthias
6bd5535d6c Use exchange method to combine funding and mark candles 2022-05-21 08:31:34 +02:00
Matthias
0e158b66b0 Update docs link 2022-05-21 08:26:44 +02:00
froggleston
c499a92f57 Remove surplus mark columns, and make fillna on funding rate only 2022-05-20 11:48:53 +01:00
Matthias
0138114fc2 Merge pull request #6866 from freqtrade/dry_order_db
Dry orders from db
2022-05-20 12:10:09 +02:00
Matthias
c3e3188c6a Rename variable 2022-05-20 11:30:25 +02:00
Matthias
843bf0631e Remove Sponsored Promotions 2022-05-20 07:14:49 +02:00
Matthias
b3acfb3c6f Bump ccxt to 1.83.12
closes #6849
2022-05-20 06:55:51 +02:00
Matthias
2cf17e04be Init persistence for tests that use dry-run orders 2022-05-20 06:26:16 +02:00
robcaulk
c5ecf94177 move live retraining to separate thread. 2022-05-19 21:15:58 +02:00
Matthias
46ea135b6b Update dry-run considerations 2022-05-19 20:10:11 +02:00
Matthias
219363fffb Check for both ask and bid in SpreadFilter
closes #6865
2022-05-19 19:53:23 +02:00
Matthias
56a73575a1 Add explicit test for order_to_ccxt 2022-05-19 19:29:39 +02:00
robcaulk
1fae6c9ef7 keep model accessible in memory to avoid loading objects from disk during live/dry 2022-05-19 19:27:38 +02:00
robcaulk
67eb94c69d download-data will now check if freqai is active in config, and if so will also download data for corr_pairlist 2022-05-19 17:55:00 +02:00
robcaulk
89eacf2f47 Retrain model if FreqAI found a pretrained model but user strategy is not passing the expected features (user has changed the features in the strategy but has passed a the same config[freqai][identifier]). Logger warning output to user. 2022-05-19 17:15:50 +02:00
Matthias
5e18e51ce0 Fix some tests 2022-05-19 07:03:53 +02:00
Matthias
a3d9384bc0 Remove clean-dry-run code 2022-05-19 06:56:34 +02:00
Matthias
0a95ef6ab2 Don't reset open orders in dry-run on restart 2022-05-19 06:42:38 +02:00
froggleston
363098d32d Fix reversed makr/funding_rate columns 2022-05-18 12:56:43 +01:00
froggleston
736f9f4972 Fix docs and add outer join support for merging funding rates across full timerange 2022-05-18 12:47:37 +01:00
Matthias
d5486f17d8 Update Test to use StrategyV3 2022-05-18 10:57:19 +02:00
மனோஜ்குமார் பழனிச்சாமி
2b61aa282a Removed None in dict.get()
https://stackoverflow.com/a/12631641

Extra Changes: freqtrade\freqtradebot.py:70
freqtrade\plugins\pairlistmanager.py:31
2022-05-18 03:41:10 +05:30
froggleston
c41d4c4f45 Fix leverage docs 2022-05-17 22:37:48 +01:00
froggleston
37e4ede65c Fix flake issues 2022-05-17 22:32:17 +01:00
froggleston
bb758da940 Add support for fudging unavailable funding rates, allowing backtesting of timeranges where futures candles are available, but rates are not 2022-05-17 22:05:33 +01:00
robcaulk
c708dd3186 doc update thanks matthias 2022-05-17 20:46:23 +02:00
Matthias
c81b960791 Fix some typos 2022-05-17 19:58:36 +02:00
robcaulk
db66b82f6f accept open-ended timeranges from user 2022-05-17 19:50:06 +02:00
Matthias
7b9439f2e4 Merge pull request #6854 from eSeR1805/feat_bt_cancel_entry_reporting
BT: Reporting canceled/replaced entry orders
2022-05-17 19:26:44 +02:00
robcaulk
d1d451c27e auto populate features based on a prepended % in the strategy (remove feature assignment from config). Update doc/constants/example strategy to reflect change 2022-05-17 18:15:03 +02:00
robcaulk
8664e8f9a3 create a prediction_models folder where basic prediction models can live (similar to optimize/hyperopt-loss. Update resolver/docs/and gitignore to accommodate change 2022-05-17 17:13:38 +02:00
eSeR1805
34684ec86a Merge branch 'freqtrade:develop' into feat_bt_cancel_entry_reporting 2022-05-17 14:09:57 +03:00
eSeR1805
c6bf6779f8 Update docs BT sample report and details. 2022-05-17 14:09:01 +03:00
eSeR1805
bb7ffd8fbe Update testcases relying on BT results. 2022-05-17 14:08:35 +03:00
eSeR1805
0585b378b3 BT: Report canceled/replaced orders also. 2022-05-17 14:07:42 +03:00
eSeR1805
6e8f24f6a7 BT: track canceled/replaced orders also. 2022-05-17 14:07:02 +03:00
Matthias
8d46e16c46 Merge pull request #6848 from freqtrade/datahandler_case
Datahandler case insensitive
2022-05-17 09:34:11 +02:00
Matthias
1cd8ebc8c8 Merge pull request #6847 from freqtrade/use_Precise
Use precise
2022-05-17 09:33:39 +02:00
Matthias
6fd003c655 Merge pull request #6851 from eSeR1805/feat_bt_cancel_entry_reporting
BT: Reporting canceled trade entries
2022-05-17 07:05:26 +02:00
Matthias
b022680962 Merge pull request #6822 from SmartManoj/patch-10
fixed variable naming style
2022-05-17 06:34:39 +02:00
மனோஜ்குமார் பழனிச்சாமி
7cd0f8a7b1 Merge branch 'develop' into patch-10 2022-05-17 08:07:13 +05:30
eSeR1805
905b24bd4d Update BT report detailing. 2022-05-17 02:04:45 +03:00
eSeR1805
a2a8e4fdc7 Update doc BT sample report. 2022-05-17 02:01:27 +03:00
eSeR1805
99aea454b5 Update testcases to match reporting. 2022-05-17 01:42:48 +03:00
eSeR1805
f2e2e57237 Report trade entries canceled by user. 2022-05-17 01:41:31 +03:00
eSeR1805
fb7c0792c0 Track trade entries canceled by user. 2022-05-17 01:41:01 +03:00
Matthias
76637d3939 Simplify timeframe-transition 2022-05-16 20:10:52 +02:00
Matthias
2e65a1793d Add fallback to load 1M files as well as 1Mo files 2022-05-16 19:48:27 +02:00
Matthias
a1048fb619 Store monthly candles as "Mo" 2022-05-16 19:39:43 +02:00
Matthias
9607d04279 Improve ccxt imports 2022-05-16 19:22:07 +02:00
Matthias
d09b462930 Add rudimentary tests for Precise "builtin operator" workings 2022-05-16 19:21:38 +02:00
Matthias
c8e0fc926d Update to do Builtin Precise math 2022-05-16 19:21:38 +02:00
Matthias
a793cf8f05 Use ccxt's "precise" to do precise math 2022-05-16 19:21:38 +02:00
Matthias
528509f809 Extract get_price_side from get_rate 2022-05-16 19:20:13 +02:00
Matthias
860a15ff40 Merge pull request #6839 from freqtrade/dependabot/pip/develop/plotly-5.8.0
Bump plotly from 5.7.0 to 5.8.0
2022-05-16 19:18:43 +02:00
Matthias
1913565507 Merge pull request #6834 from stash86/patch-1
Missing \n on /help response
2022-05-16 10:39:46 +02:00
Matthias
c54919e4ce Merge pull request #6841 from freqtrade/dependabot/pip/develop/scikit-learn-1.1.0
Bump scikit-learn from 1.0.2 to 1.1.0
2022-05-16 10:02:58 +02:00
Matthias
d6c452a93e Merge pull request #6836 from freqtrade/dependabot/pip/develop/pyjwt-2.4.0
Bump pyjwt from 2.3.0 to 2.4.0
2022-05-16 10:01:59 +02:00
dependabot[bot]
f5183df0f1 Bump scikit-learn from 1.0.2 to 1.1.0
Bumps [scikit-learn](https://github.com/scikit-learn/scikit-learn) from 1.0.2 to 1.1.0.
- [Release notes](https://github.com/scikit-learn/scikit-learn/releases)
- [Commits](https://github.com/scikit-learn/scikit-learn/compare/1.0.2...1.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-16 04:37:41 +00:00
dependabot[bot]
bd65236e17 Bump pyjwt from 2.3.0 to 2.4.0
Bumps [pyjwt](https://github.com/jpadilla/pyjwt) from 2.3.0 to 2.4.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.3.0...2.4.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-16 04:37:25 +00:00
Matthias
36d95a3a30 Merge pull request #6843 from freqtrade/dependabot/pip/develop/mkdocs-material-8.2.15
Bump mkdocs-material from 8.2.14 to 8.2.15
2022-05-16 06:36:52 +02:00
Matthias
f8e9dc0650 Merge pull request #6840 from freqtrade/dependabot/pip/develop/flake8-tidy-imports-4.8.0
Bump flake8-tidy-imports from 4.7.0 to 4.8.0
2022-05-16 06:36:28 +02:00
Matthias
66621d6723 Merge pull request #6838 from freqtrade/dependabot/pip/develop/fastapi-0.78.0
Bump fastapi from 0.76.0 to 0.78.0
2022-05-16 06:36:09 +02:00
Matthias
f015985062 Merge pull request #6837 from freqtrade/dependabot/pip/develop/time-machine-2.7.0
Bump time-machine from 2.6.0 to 2.7.0
2022-05-16 06:34:41 +02:00
Matthias
f1474cea7a Merge pull request #6842 from freqtrade/dependabot/pip/develop/ccxt-1.82.61
Bump ccxt from 1.81.81 to 1.82.61
2022-05-16 06:33:30 +02:00
Matthias
5c5b9534c1 Merge pull request #6844 from freqtrade/dependabot/pip/develop/filelock-3.7.0
Bump filelock from 3.6.0 to 3.7.0
2022-05-16 06:33:15 +02:00
dependabot[bot]
dd1b84f938 Bump filelock from 3.6.0 to 3.7.0
Bumps [filelock](https://github.com/tox-dev/py-filelock) from 3.6.0 to 3.7.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.6.0...3.7.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-16 03:02:00 +00:00
dependabot[bot]
a8b4066f85 Bump mkdocs-material from 8.2.14 to 8.2.15
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 8.2.14 to 8.2.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/8.2.14...8.2.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>
2022-05-16 03:01:57 +00:00
dependabot[bot]
9e44d69774 Bump ccxt from 1.81.81 to 1.82.61
Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.81.81 to 1.82.61.
- [Release notes](https://github.com/ccxt/ccxt/releases)
- [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg)
- [Commits](https://github.com/ccxt/ccxt/compare/1.81.81...1.82.61)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-16 03:01:53 +00:00
dependabot[bot]
9fc21686ed Bump flake8-tidy-imports from 4.7.0 to 4.8.0
Bumps [flake8-tidy-imports](https://github.com/adamchainz/flake8-tidy-imports) from 4.7.0 to 4.8.0.
- [Release notes](https://github.com/adamchainz/flake8-tidy-imports/releases)
- [Changelog](https://github.com/adamchainz/flake8-tidy-imports/blob/main/HISTORY.rst)
- [Commits](https://github.com/adamchainz/flake8-tidy-imports/compare/4.7.0...4.8.0)

---
updated-dependencies:
- dependency-name: flake8-tidy-imports
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-16 03:01:40 +00:00
dependabot[bot]
748055892c Bump plotly from 5.7.0 to 5.8.0
Bumps [plotly](https://github.com/plotly/plotly.py) from 5.7.0 to 5.8.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.7.0...v5.8.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-16 03:01:33 +00:00
dependabot[bot]
47c116a423 Bump fastapi from 0.76.0 to 0.78.0
Bumps [fastapi](https://github.com/tiangolo/fastapi) from 0.76.0 to 0.78.0.
- [Release notes](https://github.com/tiangolo/fastapi/releases)
- [Commits](https://github.com/tiangolo/fastapi/compare/0.76.0...0.78.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-16 03:01:28 +00:00
dependabot[bot]
4fc6857d87 Bump time-machine from 2.6.0 to 2.7.0
Bumps [time-machine](https://github.com/adamchainz/time-machine) from 2.6.0 to 2.7.0.
- [Release notes](https://github.com/adamchainz/time-machine/releases)
- [Changelog](https://github.com/adamchainz/time-machine/blob/main/HISTORY.rst)
- [Commits](https://github.com/adamchainz/time-machine/compare/2.6.0...2.7.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>
2022-05-16 03:01:25 +00:00
Stefano Ariestasia
2cb8eecf18 add space 2022-05-16 07:43:36 +09:00
Stefano Ariestasia
e21f6a7787 missing newline 2022-05-16 07:28:40 +09:00
Stefano Ariestasia
36e514e825 Merge branch 'freqtrade:develop' into patch-1 2022-05-16 07:27:11 +09:00
Matthias
8198bfd997 Merge pull request #6833 from freqtrade/python_310_main_versoin
Python 310 main version
2022-05-15 20:01:19 +02:00
Matthias
008ee14889 Improve ci to run on ubuntu 22.04 2022-05-15 19:29:42 +02:00
Matthias
3d36d35e30 Merge pull request #6825 from freqtrade/okx_history
Okx history
2022-05-15 19:27:45 +02:00
Matthias
86af3fe0e7 Update image versions from 3.9 to 3.10 2022-05-15 19:22:12 +02:00
robcaulk
80dcd88abf allow user to run config from anywhere on their system 2022-05-15 17:42:15 +02:00
robcaulk
9e94d28860 add timerange to backtest commnad 2022-05-15 17:42:15 +02:00
robcaulk
e5759d950b fix typo 2022-05-15 17:42:15 +02:00
robcaulk
f4296173e9 use bash visual in doc 2022-05-15 17:42:15 +02:00
robcaulk
717df891b1 use bash visual in doc 2022-05-15 17:42:15 +02:00
robcaulk
a8022c104a give beta testers more information in the doc 2022-05-15 17:42:15 +02:00
robcaulk
a7029e35b5 ensure informative pairs includes any combination of whitelist - corr_pairlist 2022-05-15 17:42:15 +02:00
robcaulk
9b3e5faebe create more flexible whitelist, avoid duplicating whitelist features into corr_pairlist, update docs 2022-05-15 17:42:15 +02:00
robcaulk
22bd5556ed add self-retraining functionality for live/dry 2022-05-15 17:42:15 +02:00
robcaulk
178c2014b0 appease mypy 2022-05-15 17:42:15 +02:00
robcaulk
a4f5811a5b fix flake8 issue in arguments.py 2022-05-15 17:42:15 +02:00
robcaulk
aae233bd6c try passing the check tests 2022-05-15 17:42:15 +02:00
robcaulk
f653ace24b another attempt at fixing datalength bug 2022-05-15 17:42:15 +02:00
robcaulk
b08c0888bb add USERPATH_FREQAIMODELS, remove return values from @abstract methods 2022-05-15 17:42:15 +02:00
robcaulk
b03c7b514d optional style for interfacing freqai with backtesting 2022-05-15 17:42:15 +02:00
robcaulk
e9a7b68bc1 revert constants.py and add changes 2022-05-15 17:42:15 +02:00
Matthias
a0b25938f4 Fix exit_reason assignment in backtesting 2022-05-15 17:41:59 +02:00
Matthias
a8f064a8cb Fix exit_reason assignment in live mode 2022-05-15 17:41:59 +02:00
robcaulk
3020218096 fix bug on backtest timerange 2022-05-15 17:41:34 +02:00
robcaulk
00ff0c9b91 ensure user defined timerange truncates final backtest so that we arent mismatching data lengths upon return to strategy. Rename DataHandler class to FreqaiDataKitchen 2022-05-15 17:41:34 +02:00
robcaulk
66715c5ba4 update doc 2022-05-15 17:41:34 +02:00
robcaulk
def71a0afe auto build full_timerange and self manage training_timerange 2022-05-15 17:41:34 +02:00
robcaulk
764f9449b4 fix logger, debug some flake8 appeasements 2022-05-15 17:41:34 +02:00
robcaulk
29c2d1d189 use logger in favor of print 2022-05-15 17:38:58 +02:00
robcaulk
99f7e44c30 flake8 passing, use pathlib in lieu of os.path to accommodate windows/mac OS 2022-05-15 17:38:58 +02:00
robcaulk
2600ba4e74 remove unused remnants 2022-05-15 17:38:58 +02:00
robcaulk
630d201546 remove trained_stake 2022-05-15 17:38:58 +02:00
robcaulk
b40f8f88ac cleaning and bug fixing 2022-05-15 17:38:58 +02:00
robcaulk
fc837c4daa add freqao backend machinery, user interface, documentation 2022-05-15 17:38:58 +02:00
Matthias
706994340f Fix bad docstring 2022-05-15 17:06:40 +02:00
Matthias
ebab02fce3 Merge pull request #6827 from eSeR1805/fix_readjust_entry_bt_sl
Fix: Refresh SL on entry order replacement
2022-05-15 16:41:18 +02:00
eSeR1805
cf001db396 Merge pull request #1 from xmatthias/bt_stop_attempt
Update stoploss handling for entry-order adjustment
2022-05-15 16:56:40 +03:00
Matthias
18fd3bb333 Update stoploss handling for entry-order adjustment 2022-05-15 15:45:39 +02:00
Matthias
9143e9ecb1 Add some safety measures for new startup_candles verification 2022-05-15 15:12:29 +02:00
Matthias
d60d0f64d2 Revert ohlcv_candle_limit logic for okx 2022-05-14 19:35:06 +02:00
Matthias
116b58e97c add "date_minus_candles" method 2022-05-14 19:30:42 +02:00
Matthias
a947a1316b Add test to ensure stoploss is set properly in live 2022-05-14 17:42:01 +02:00
Matthias
3b14439240 Slightly improve performance of order adjusts
Avoind  2nd call to `get_rate()`.

closes #6821
2022-05-14 16:16:32 +02:00
eSeR1805
c27e0a0a1b Allow SL refresh only if no filled entry orders. 2022-05-14 16:56:56 +03:00
eSeR1805
ec54b47b6e Flake fix. 2022-05-14 16:39:27 +03:00
eSeR1805
1c20fb7638 Refresh open_rate and stoploss on order replacement. 2022-05-14 16:37:04 +03:00
Matthias
5767d652bf Add explicit test and document behavior 2022-05-14 14:18:51 +02:00
Matthias
2a1368d508 Offsetfilter: add number_assets parameter
closes #6824
2022-05-14 14:16:13 +02:00
Matthias
bb1b283d95 Update some ohlcv_candle_limit calls 2022-05-14 13:44:10 +02:00
Matthias
111b04c9e6 Okx - conditional candle-length 2022-05-14 09:51:44 +02:00
Matthias
64668b11da add ohlcv_has_history - disabling kraken downloads 2022-05-14 09:10:38 +02:00
Matthias
8e9384e8e6 Merge pull request #6823 from mkavinkumar1/clean-bt
cleaned up backtesting
2022-05-13 21:00:06 +02:00
Matthias
80ebd8f875 Merge pull request #6820 from SmartManoj/patch-9
Corrected docstring
2022-05-13 19:29:47 +02:00
மனோஜ்குமார் பழனிச்சாமி
64670726a6 flake8 fix 2022-05-13 21:52:26 +05:30
மனோஜ்குமார் பழனிச்சாமி
9d13c87292 cleaned up backtesting
Solves the [bug](https://github.com/freqtrade/freqtrade/runs/6425715015?check_suite_focus=true)
2022-05-13 21:46:25 +05:30
மனோஜ்குமார் பழனிச்சாமி
71a80cab3a fixed variable naming style 2022-05-13 21:19:40 +05:30
மனோஜ்குமார் பழனிச்சாமி
8a3c2c6cad Corrected docstring
Discussed in Discord
2022-05-13 19:32:52 +05:30
Matthias
c299601ece Add warning about OKX futures backtesting data 2022-05-13 07:03:18 +02:00
Matthias
5444f4ee6f Merge pull request #6793 from mkavinkumar1/log
logged balance details
2022-05-12 19:11:28 +02:00
Matthias
891900c186 Merge pull request #6812 from freqtrade/db_migrate
Db migrate
2022-05-11 19:54:31 +02:00
Matthias
1fc041d0d6 Fix formatting issue 2022-05-11 19:39:56 +02:00
Matthias
ae463fcdf2 Merge pull request #6792 from mkavinkumar1/rpc
consistent exchange name
2022-05-11 19:23:36 +02:00
Matthias
7c1838427f Merge pull request #6814 from DJCrashdummy/patch-1
minor polish for explanation of `backtesting --breakdown`
2022-05-11 09:09:32 +02:00
DJCrashdummy
b2b503f043 minor polish for explanation of --breakdown
- corrected the command to fit the explanation
- added a little explanation how to read the weekly & monthly breakdown
2022-05-11 06:26:49 +00:00
DJCrashdummy
8a6a6ec911 corrected minor "typo" in formatting 2022-05-11 06:30:58 +02:00
Matthias
f374c9da70 PR cleanup 2022-05-11 06:30:40 +02:00
Matthias
044afdf7af Add better test scenario 2022-05-10 20:27:24 +02:00
Matthias
31cce741ac Add sequence migration 2022-05-10 07:13:51 +02:00
Matthias
269630e755 Add preliminary documentation for database conversion 2022-05-10 07:13:42 +02:00
Matthias
c19be34e71 Add rudimentary test for db migration 2022-05-09 20:58:40 +02:00
Matthias
0958c06b84 Implement database migration to other system 2022-05-09 20:58:40 +02:00
Matthias
c3b0f6b64b Add feature shell for database conversion 2022-05-09 20:58:40 +02:00
Matthias
0f499469fc Merge pull request #6796 from freqtrade/model_reorg
Model reorg
2022-05-09 20:15:45 +02:00
Matthias
e66e1317dc Merge pull request #6803 from freqtrade/dependabot/pip/develop/types-tabulate-0.8.9
Bump types-tabulate from 0.8.8 to 0.8.9
2022-05-09 08:00:20 +02:00
Matthias
54450bcb8c Merge pull request #6804 from freqtrade/dependabot/pip/develop/ccxt-1.81.81
Bump ccxt from 1.81.43 to 1.81.81
2022-05-09 07:13:18 +02:00
Matthias
35ec657ef1 Bump types-tabulate==0.8.9 precommit 2022-05-09 06:55:01 +02:00
dependabot[bot]
a5beacbdd0 Bump types-tabulate from 0.8.8 to 0.8.9
Bumps [types-tabulate](https://github.com/python/typeshed) from 0.8.8 to 0.8.9.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-09 04:53:29 +00:00
Matthias
bfcb8c9b82 Merge pull request #6806 from freqtrade/dependabot/pip/develop/types-python-dateutil-2.8.15
Bump types-python-dateutil from 2.8.14 to 2.8.15
2022-05-09 06:52:59 +02:00
Matthias
a69b8d2fb6 Merge pull request #6800 from freqtrade/dependabot/pip/develop/pre-commit-2.19.0
Bump pre-commit from 2.18.1 to 2.19.0
2022-05-09 06:52:43 +02:00
dependabot[bot]
2dd655eda0 Bump pre-commit from 2.18.1 to 2.19.0
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.18.1 to 2.19.0.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v2.18.1...v2.19.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-09 04:52:32 +00:00
Matthias
ad81cd280f Merge pull request #6805 from freqtrade/dependabot/pip/develop/flake8-tidy-imports-4.7.0
Bump flake8-tidy-imports from 4.6.0 to 4.7.0
2022-05-09 06:51:40 +02:00
Matthias
162a517411 Merge pull request #6802 from freqtrade/dependabot/pip/develop/fastapi-0.76.0
Bump fastapi from 0.75.2 to 0.76.0
2022-05-09 06:51:21 +02:00
Matthias
5f0c79cc47 Merge pull request #6801 from freqtrade/dependabot/pip/develop/jsonschema-4.5.1
Bump jsonschema from 4.4.0 to 4.5.1
2022-05-09 06:37:29 +02:00
Matthias
4e5a8ce87e Merge pull request #6799 from freqtrade/dependabot/pip/develop/mkdocs-material-8.2.14
Bump mkdocs-material from 8.2.12 to 8.2.14
2022-05-09 06:37:06 +02:00
dependabot[bot]
5080245a73 Bump ccxt from 1.81.43 to 1.81.81
Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.81.43 to 1.81.81.
- [Release notes](https://github.com/ccxt/ccxt/releases)
- [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg)
- [Commits](https://github.com/ccxt/ccxt/compare/1.81.43...1.81.81)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-09 04:32:48 +00:00
Matthias
0756027e33 BUmp types-python-dateutil precommit 2022-05-09 06:32:28 +02:00
Matthias
5f7b19cb56 Merge pull request #6798 from freqtrade/dependabot/pip/develop/cryptography-37.0.2
Bump cryptography from 37.0.1 to 37.0.2
2022-05-09 06:31:44 +02:00
dependabot[bot]
69b79cd799 Bump types-python-dateutil from 2.8.14 to 2.8.15
Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.8.14 to 2.8.15.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-09 03:11:16 +00:00
dependabot[bot]
1ae74c1197 Bump flake8-tidy-imports from 4.6.0 to 4.7.0
Bumps [flake8-tidy-imports](https://github.com/adamchainz/flake8-tidy-imports) from 4.6.0 to 4.7.0.
- [Release notes](https://github.com/adamchainz/flake8-tidy-imports/releases)
- [Changelog](https://github.com/adamchainz/flake8-tidy-imports/blob/main/HISTORY.rst)
- [Commits](https://github.com/adamchainz/flake8-tidy-imports/compare/4.6.0...4.7.0)

---
updated-dependencies:
- dependency-name: flake8-tidy-imports
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-09 03:11:12 +00:00
dependabot[bot]
77a22a6b1c Bump fastapi from 0.75.2 to 0.76.0
Bumps [fastapi](https://github.com/tiangolo/fastapi) from 0.75.2 to 0.76.0.
- [Release notes](https://github.com/tiangolo/fastapi/releases)
- [Commits](https://github.com/tiangolo/fastapi/compare/0.75.2...0.76.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-09 03:10:38 +00:00
dependabot[bot]
74b309cf50 Bump jsonschema from 4.4.0 to 4.5.1
Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.4.0 to 4.5.1.
- [Release notes](https://github.com/python-jsonschema/jsonschema/releases)
- [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.4.0...v4.5.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-09 03:10:27 +00:00
dependabot[bot]
30cc8e92a1 Bump mkdocs-material from 8.2.12 to 8.2.14
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 8.2.12 to 8.2.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/8.2.12...8.2.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>
2022-05-09 03:10:15 +00:00
dependabot[bot]
df48399a90 Bump cryptography from 37.0.1 to 37.0.2
Bumps [cryptography](https://github.com/pyca/cryptography) from 37.0.1 to 37.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/37.0.1...37.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>
2022-05-09 03:10:07 +00:00
Matthias
511afbcd9d Merge pull request #6797 from lukeingalls/patch-1
then -> than
2022-05-08 21:50:41 +02:00
Luke Ingalls
f71b2624ab then -> than 2022-05-08 10:07:22 -07:00
Matthias
30d6eeffd0 Fix migration bug 2022-05-08 17:49:13 +02:00
Matthias
b58e811b14 Move trade/order Models to their own class 2022-05-08 17:45:20 +02:00
Matthias
af1a5e0449 Extract base and Pairlock from models file 2022-05-08 17:38:06 +02:00
Matthias
3221726d85 Update migration to use boolean value
closes #6794
2022-05-08 17:29:42 +02:00
Matthias
ab91758c7e Merge pull request #6790 from eSeR1805/profit_reporting
Report profit only on filled entries.
2022-05-08 17:25:42 +02:00
Matthias
4a7515e66a Add test for 0.0 case 2022-05-08 16:04:06 +02:00
Matthias
1436bc1a70 Update list-strategies command
closes #6795
2022-05-08 15:30:44 +02:00
மனோஜ்குமார் பழனிச்சாமி
f43ae0ea43 logged balance details 2022-05-08 13:53:07 +05:30
மனோஜ்குமார் பழனிச்சாமி
d79b90a98f consistent exchange name 2022-05-08 12:46:58 +05:30
Matthias
45b328af2e explicitly call cleanup when cleaning backtest 2022-05-08 08:11:39 +02:00
eSeR1805
bfc7898654 Report profit only on filled entries. 2022-05-07 21:56:22 +03:00
Matthias
c9498d0117 Merge pull request #6692 from eSeR1805/feat_readjust_entry
Feature: Readjust Entry Order
2022-05-07 20:11:20 +02:00
Matthias
277e07589e update/fix some comments and docs 2022-05-07 17:47:37 +02:00
eSeR1805
eca8d16c61 Minor fix and enhancement for TC51. 2022-05-07 17:31:56 +03:00
Matthias
f5f599c7f0 Add LowProfitPairs only_per_side option 2022-05-07 15:25:15 +02:00
Matthias
26648e54cc Merge pull request #6789 from freqtrade/okx_positionmode
Okx positionmode
2022-05-07 14:30:44 +02:00
Matthias
dc0c1bf87d Only fetch accounts when authenticated. 2022-05-07 13:17:27 +02:00
Matthias
149704e748 Fix wrong type 2022-05-07 11:39:47 +02:00
Matthias
6fdcf3a10a Support both position modes on OKX 2022-05-07 10:58:41 +02:00
Matthias
2da284b921 Properly type side for create_order 2022-05-07 10:02:54 +02:00
Matthias
68a97a898d Disable scheduled notification in CI 2022-05-07 08:04:43 +02:00
Matthias
108903f7f0 Add DCA order adjust test 2022-05-06 19:50:10 +02:00
Matthias
70bac41d89 Add more backtest test scenarios 2022-05-06 19:50:10 +02:00
eSeR1805
182a6f475d Minor typos. 2022-05-06 10:13:29 +03:00
Matthias
5b3eaa3003 Ensure advanced strategy template is runnable 2022-05-06 06:42:08 +02:00
Matthias
d11c44940e Slightly reword docs
remove some Note-boxes - people tend to skip these.
2022-05-06 06:42:01 +02:00
Matthias
2d9be6dace move open_rate updating to close_bt_order 2022-05-05 19:50:16 +02:00
eSeR1805
29f1edbde7 Cleanup. Remove stray new line. 2022-05-05 12:24:32 +03:00
eSeR1805
495708df76 Merge branch 'develop' into feat_readjust_entry 2022-05-05 12:20:09 +03:00
eSeR1805
2bed0eab0c BT: Update trade open_rate on first filled order. 2022-05-05 12:19:05 +03:00
eSeR1805
25c74e26d1 Models:Trade: Revert trade open_rate update. 2022-05-05 12:18:19 +03:00
Matthias
1a37c6ff42 Bump ccxt to 1.81.43
fixes bug in okx live liquidation pricing
2022-05-05 07:05:00 +02:00
eSeR1805
ae01afdd0f Models:Trade: Fix open_rate updates. 2022-05-04 22:05:53 +03:00
eSeR1805
496bf84e3a Merge branch 'develop' into feat_readjust_entry 2022-05-04 21:43:41 +03:00
eSeR1805
dbecc097df Models:Trade: Update trade open_rate based on lastest order. 2022-05-04 21:34:45 +03:00
Sam Germain
10cbb5e67c test_exchange::test_taker_or_maker fixes 2022-05-04 00:10:09 -06:00
Sam Germain
86ad5dd02a test_exchange::test_taker_or_maker fixes 2022-05-04 00:08:41 -06:00
Sam Germain
dac9931b4a test_create_dry_run_order_fees 2022-05-03 23:56:49 -06:00
Sam Germain
5d9aee6b7e test_taker_or_maker 2022-05-03 23:56:49 -06:00
Sam Germain
e8803477df exchange/exchange add param taker_or_maker to add_dry_order_fee 2022-05-03 23:56:40 -06:00
Matthias
b73f770955 Merge pull request #6778 from markdregan/patch-1
Add bot_loop_start() call in plotting.py
2022-05-04 07:24:32 +02:00
Matthias
b2f33944ec Add preliminary backtesting test 2022-05-04 07:13:02 +02:00
Matthias
5c82cce06c Fix new test failures 2022-05-04 06:40:12 +02:00
Mark Regan
ce035a5947 Add bot_loop_start() call in plotting.py
plotting.py was missing a call to strategy.bot_loop_start() resulting in strategies using this callback to not work.

Made changes and confirmed plotting now works for strategies using bot_loop_start() callback.

LMK if anything else needed for PR.
2022-05-03 23:34:12 +01:00
Matthias
2705096ce6 Merge pull request #6777 from freqtrade/fix/contractsizefee
Fix fee handling for futures trades
2022-05-03 20:34:37 +02:00
Matthias
091cb4fb8d Reduce no stake amount verbosity
closes #6768
2022-05-03 19:42:17 +02:00
Matthias
eb996a152a Fix fee handling for futures trades 2022-05-03 19:06:17 +02:00
Matthias
65ab6d2468 Merge pull request #6771 from talentoscope/patch-1
Update setup.sh
2022-05-03 08:12:29 +02:00
talentoscope
8e1cdb9103 Update setup.sh
Added curl to dependencies for Debian systems
2022-05-02 23:20:13 +01:00
Matthias
88c8fe5570 Merge pull request #6715 from nicolaspapp/feat/relative-drawdown
Add relative drawdown
2022-05-02 21:09:14 +02:00
Matthias
7a57629918 Keep Backtest-metrics aligned 2022-05-02 20:08:38 +02:00
Matthias
3f64c6307f Maintain compatibility with old backtest results 2022-05-02 20:01:44 +02:00
Matthias
1e2523af61 Fix some assumptions on the data
available_capital is not guaranteed to be available, while dry-run-wallet is.
2022-05-02 19:44:14 +02:00
eSeR1805
52d510c331 Merge branch 'develop' into feat_readjust_entry 2022-05-02 18:30:05 +03:00
eSeR1805
4c74601073 Freqtradebot: Cleanup stray debug messages. 2022-05-02 18:22:41 +03:00
eSeR1805
59397cdd19 Freqtradebot: Fix full cancel logging location. 2022-05-02 18:09:28 +03:00
eSeR1805
b83cd95a02 Tests: add basic testcases for entry adjustment. 2022-05-02 18:07:48 +03:00
Matthias
c1b10bbb91 Merge pull request #6763 from freqtrade/dependabot/pip/develop/mypy-0.950
Bump mypy from 0.942 to 0.950
2022-05-02 09:13:08 +02:00
Matthias
46993ce3ae Merge pull request #6761 from freqtrade/dependabot/pip/develop/types-tabulate-0.8.8
Bump types-tabulate from 0.8.7 to 0.8.8
2022-05-02 09:12:52 +02:00
Matthias
2a6efab8a2 Don't use deprecated abstractclassmethod decorator 2022-05-02 06:24:52 +00:00
Matthias
38dffe1ed6 types-tabulate - pre-commit update 2022-05-02 08:11:05 +02:00
dependabot[bot]
24ce90ba9b Bump types-tabulate from 0.8.7 to 0.8.8
Bumps [types-tabulate](https://github.com/python/typeshed) from 0.8.7 to 0.8.8.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-02 06:00:02 +00:00
Matthias
541ee436c5 Merge pull request #6759 from freqtrade/dependabot/pip/develop/sqlalchemy-1.4.36
Bump sqlalchemy from 1.4.35 to 1.4.36
2022-05-02 07:59:30 +02:00
Matthias
725706beab Merge pull request #6765 from freqtrade/dependabot/pip/develop/types-requests-2.27.25
Bump types-requests from 2.27.20 to 2.27.25
2022-05-02 07:59:14 +02:00
Matthias
24cb40fe98 Merge pull request #6758 from freqtrade/dependabot/pip/develop/types-python-dateutil-2.8.14
Bump types-python-dateutil from 2.8.12 to 2.8.14
2022-05-02 07:24:32 +02:00
Matthias
e3c298e892 Merge pull request #6766 from freqtrade/dependabot/pip/develop/jinja2-3.1.2
Bump jinja2 from 3.1.1 to 3.1.2
2022-05-02 07:11:19 +02:00
dependabot[bot]
67dd9be95a Bump sqlalchemy from 1.4.35 to 1.4.36
Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 1.4.35 to 1.4.36.
- [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases)
- [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst)
- [Commits](https://github.com/sqlalchemy/sqlalchemy/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-02 05:00:17 +00:00
Matthias
bd07d356bd Merge pull request #6762 from freqtrade/dependabot/pip/develop/cryptography-37.0.1
Bump cryptography from 36.0.2 to 37.0.1
2022-05-02 06:59:27 +02:00
Matthias
71ae92274d Bump pre-commit dependency 2022-05-02 06:45:42 +02:00
Matthias
49c1b310c2 Bump pre-commit types 2022-05-02 06:44:30 +02:00
dependabot[bot]
ba28fa6c3c Bump cryptography from 36.0.2 to 37.0.1
Bumps [cryptography](https://github.com/pyca/cryptography) from 36.0.2 to 37.0.1.
- [Release notes](https://github.com/pyca/cryptography/releases)
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/36.0.2...37.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-02 04:31:35 +00:00
dependabot[bot]
9de0652b2c Bump jinja2 from 3.1.1 to 3.1.2
Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.1 to 3.1.2.
- [Release notes](https://github.com/pallets/jinja/releases)
- [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/jinja/compare/3.1.1...3.1.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-02 04:31:34 +00:00
Matthias
13dc0a0b4d Merge pull request #6764 from freqtrade/dependabot/pip/develop/ccxt-1.81.16
Bump ccxt from 1.80.61 to 1.81.16
2022-05-02 06:30:11 +02:00
Matthias
3f25fb2139 Merge pull request #6760 from freqtrade/dependabot/pip/develop/mkdocs-material-8.2.12
Bump mkdocs-material from 8.2.10 to 8.2.12
2022-05-02 06:29:37 +02:00
dependabot[bot]
093bea4230 Bump types-requests from 2.27.20 to 2.27.25
Bumps [types-requests](https://github.com/python/typeshed) from 2.27.20 to 2.27.25.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-02 03:01:34 +00:00
dependabot[bot]
73aafb886b Bump ccxt from 1.80.61 to 1.81.16
Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.80.61 to 1.81.16.
- [Release notes](https://github.com/ccxt/ccxt/releases)
- [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg)
- [Commits](https://github.com/ccxt/ccxt/compare/1.80.61...1.81.16)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-02 03:01:33 +00:00
dependabot[bot]
4990534bf4 Bump mypy from 0.942 to 0.950
Bumps [mypy](https://github.com/python/mypy) from 0.942 to 0.950.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.942...v0.950)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-02 03:01:22 +00:00
dependabot[bot]
3d730661ee Bump mkdocs-material from 8.2.10 to 8.2.12
Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 8.2.10 to 8.2.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/8.2.10...8.2.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>
2022-05-02 03:01:11 +00:00
dependabot[bot]
a0e27d82aa Bump types-python-dateutil from 2.8.12 to 2.8.14
Bumps [types-python-dateutil](https://github.com/python/typeshed) from 2.8.12 to 2.8.14.
- [Release notes](https://github.com/python/typeshed/releases)
- [Commits](https://github.com/python/typeshed/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-02 03:01:00 +00:00
eSeR1805
04c51d2d1a Merge branch 'develop' into feat_readjust_entry 2022-05-01 21:42:15 +03:00
Nicolas Papp
7160f9085a Update summary examples 2022-05-01 12:32:12 -03:00
Nicolas Papp
f9244aad92 Fix on max drawdown formula to match tests 2022-05-01 12:25:53 -03:00
eSeR1805
4e43194dfe BT: Refactor open order management. 2022-05-01 18:06:20 +03:00
Matthias
582e30bca6 Merge pull request #6716 from freqtrade/pairlocks_direction
Pairlocks direction
2022-05-01 17:04:20 +02:00
Matthias
910addd02b Merge pull request #6753 from freqtrade/download_prepend
Download prepend
2022-05-01 15:15:16 +02:00
Matthias
995c48b642 Merge branch 'develop' into pairlocks_direction 2022-05-01 14:59:04 +02:00
Matthias
2cedbe5704 Fix documentation mishap 2022-05-01 14:50:36 +02:00
eSeR1805
9d205132d0 Revert unintended comment change. 2022-05-01 12:10:11 +03:00
eSeR1805
8c19953cdd Quick exit when order should be maintained. 2022-05-01 12:08:19 +03:00
Matthias
53a2f55cf0 Merge branch 'develop' into pr/nicolaspapp/6715 2022-05-01 10:03:10 +02:00
Matthias
8b5d454b50 Fix subtle bug in trades download 2022-04-30 17:44:57 +02:00
Matthias
e49b3ef051 Improve message formatting 2022-04-30 17:35:11 +02:00
Matthias
f6a7e6b785 Add prepend option to download-data 2022-04-30 17:32:50 +02:00
Matthias
11d447cd5a Add support for download-data "until" 2022-04-30 15:42:41 +02:00
Matthias
4262f84744 Merge branch 'develop' into pr/nicolaspapp/6715 2022-04-30 14:22:18 +02:00
eSeR1805
3be2afdd88 Merge branch 'develop' into feat_readjust_entry 2022-04-30 13:39:23 +03:00
eSeR1805
ad0c5d9440 Refactor entry adjustment for backtesting. 2022-04-30 13:38:17 +03:00
eSeR1805
f9977c26e7 Full cancel only for non DCA trades. 2022-04-30 12:55:03 +03:00
eSeR1805
09089b160e Merge branch 'develop' into feat_readjust_entry 2022-04-29 13:02:38 +03:00
eSeR1805
17650d7e60 Maintain existing order. Update functionality and documentation 2022-04-29 00:10:17 +03:00
eSeR1805
eb23170c43 Merge branch 'develop' into feat_readjust_entry 2022-04-28 23:06:52 +03:00
Nicolas Papp
bc5048e4f3 Update to backtesting.md 2022-04-25 23:50:47 -03:00
Matthias
4444259078 Fix hyperopt-loss interface to enforce kwargs 2022-04-25 11:33:18 +02:00
Matthias
5ff2261b74 Improve test to explicitly test for dates 2022-04-25 07:32:32 +02:00
Matthias
9bc6bbe472 Improve test for max_drawdown calculations 2022-04-25 07:23:16 +02:00
Nicolas Papp
e8aec967dd Update on note 2022-04-24 17:42:52 -03:00
Nicolas Papp
086cc6be93 Correction on tests 2022-04-24 17:37:09 -03:00
Matthias
4de0fdbfca Minor edits found during review 2022-04-24 14:43:30 +02:00
Matthias
6623192108 improve doc wording 2022-04-24 14:39:13 +02:00
Matthias
737bdfe844 Use "side" parameter when calling Pairlocks 2022-04-24 14:33:24 +02:00
Matthias
144e4da96e Update stoploss guard tests 2022-04-24 14:33:24 +02:00
Matthias
b0a8bf3025 Show lock side 2022-04-24 14:33:24 +02:00
Matthias
4942d73693 update pairlock tests 2022-04-24 14:33:24 +02:00
Matthias
845f960a4e realign pairlock naming to side 2022-04-24 14:33:24 +02:00
Matthias
fc201bb4ff implement pairlock side further 2022-04-24 14:33:24 +02:00
Matthias
420836b1b2 Update test naming 2022-04-24 14:33:24 +02:00
Matthias
7c79d937e0 Properly type "side" parameter 2022-04-24 14:33:24 +02:00
Matthias
b7cada1edd Convert ProtectionReturn to dataclass 2022-04-24 14:33:24 +02:00
Matthias
9e199165b4 Update protection-interface to support per-side locks 2022-04-24 14:33:24 +02:00
Matthias
6ff3b178b0 Add direction column to pairlocks 2022-04-24 14:33:24 +02:00
Nicolas Papp
0f943c482b PEP8 code compliance 2022-04-23 13:15:14 -03:00
eSeR1805
76558f284f Fix user cancellation functionality. 2022-04-19 13:33:37 +03:00
eSeR1805
cea4f663d5 Merge branch 'develop' into feat_readjust_entry 2022-04-18 21:22:19 +03:00
eSeR1805
d24ee9032a Update usage in backtest. No functional update. 2022-04-18 21:21:38 +03:00
eSeR1805
d9f838a65f Update template usage to reflect changes. 2022-04-18 21:20:50 +03:00
eSeR1805
3166739ec9 Update strategy callback params and description. 2022-04-18 21:17:39 +03:00
eSeR1805
95e009b9cb Update adjustment functionality and add cancelation option 2022-04-18 21:16:45 +03:00
eSeR1805
2cac1b7dcc Add new (user cancellation) reason. 2022-04-18 21:14:35 +03:00
eSeR1805
541147c801 Update documentation to match feature changes. 2022-04-18 21:13:50 +03:00
eSeR1805
17da4ca099 Use order_date_utc 2022-04-17 12:11:30 +03:00
eSeR1805
698c25f133 Fix issues reported by flake. 2022-04-16 15:44:07 +03:00
eSeR1805
d65b64a46f Merge branch 'develop' into feat_readjust_entry 2022-04-16 15:20:50 +03:00
eSeR1805
237d116d8c Update existing tests to use the new func name. 2022-04-16 15:08:54 +03:00
eSeR1805
452f44206a Add new callback to advanced template. 2022-04-16 15:08:09 +03:00
eSeR1805
bf5799ef9e Add new functionality to backtesting. 2022-04-16 15:07:18 +03:00
eSeR1805
f8a7fdd5ed Add new callback to strategy interface. 2022-04-16 15:04:22 +03:00
eSeR1805
317c1e0746 Add option to handle_cancel_enter to prevent closing trade. 2022-04-16 15:03:44 +03:00
eSeR1805
76c545ba0d Reorganize, rename, redescribe and add new functionality 2022-04-16 15:03:09 +03:00
eSeR1805
e5d4f7766e Add new cancel reason for when replacing orders. 2022-04-16 14:44:41 +03:00
eSeR1805
16b6b08227 Update docs to include info on new functionality. 2022-04-16 14:42:41 +03:00
Nicolas Papp
c8e4687833 Plots and hyperopt 2022-04-11 16:41:48 -03:00
Nicolas Papp
178240aa6c Merge branch 'develop' of https://github.com/nicolaspapp/freqtrade into feat/relative-drawdown 2022-04-11 14:42:10 -03:00
Nicolas Papp
47a6ef4f00 Max relative drawdown 2022-04-10 12:53:47 -03:00
Stefano Ariestasia
da0688b6aa Revert "Add exchange id for binance Futures"
This reverts commit 3c8387ab61.
2022-04-02 03:20:21 +09:00
Stefano Ariestasia
3c8387ab61 Add exchange id for binance Futures 2022-04-01 20:48:13 +09:00
227 changed files with 31848 additions and 19623 deletions

View File

@@ -13,20 +13,24 @@ on:
schedule:
- cron: '0 5 * * 4'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build_linux:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ ubuntu-18.04, ubuntu-20.04 ]
os: [ ubuntu-18.04, ubuntu-20.04, ubuntu-22.04 ]
python-version: ["3.8", "3.9", "3.10"]
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v3
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
@@ -62,15 +66,15 @@ jobs:
- name: Tests
run: |
pytest --random-order --cov=freqtrade --cov-config=.coveragerc
if: matrix.python-version != '3.9'
if: matrix.python-version != '3.9' || matrix.os != 'ubuntu-22.04'
- name: Tests incl. ccxt compatibility tests
run: |
pytest --random-order --cov=freqtrade --cov-config=.coveragerc --longrun
if: matrix.python-version == '3.9'
if: matrix.python-version == '3.9' && matrix.os == 'ubuntu-22.04'
- name: Coveralls
if: (runner.os == 'Linux' && matrix.python-version == '3.8')
if: (runner.os == 'Linux' && matrix.python-version == '3.9')
env:
# Coveralls token. Not used as secret due to github not providing secrets to forked repositories
COVERALLS_REPO_TOKEN: 6D1m0xupS3FgutfuGao8keFf9Hc0FpIXu
@@ -78,11 +82,13 @@ jobs:
# Allow failure for coveralls
coveralls || true
- name: Backtesting
- name: Backtesting (multi)
run: |
cp config_examples/config_bittrex.example.json config.json
freqtrade create-userdir --userdir user_data
freqtrade backtesting --datadir tests/testdata --strategy SampleStrategy
freqtrade new-strategy -s AwesomeStrategy
freqtrade new-strategy -s AwesomeStrategyMin --template minimal
freqtrade backtesting --datadir tests/testdata --strategy-list AwesomeStrategy AwesomeStrategyMin -i 5m
- name: Hyperopt
run: |
@@ -121,7 +127,7 @@ jobs:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v3
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
@@ -157,29 +163,15 @@ jobs:
pip install -e .
- name: Tests
if: (runner.os != 'Linux' || matrix.python-version != '3.8')
run: |
pytest --random-order
- name: Tests (with cov)
if: (runner.os == 'Linux' && matrix.python-version == '3.8')
run: |
pytest --random-order --cov=freqtrade --cov-config=.coveragerc
- name: Coveralls
if: (runner.os == 'Linux' && matrix.python-version == '3.8')
env:
# Coveralls token. Not used as secret due to github not providing secrets to forked repositories
COVERALLS_REPO_TOKEN: 6D1m0xupS3FgutfuGao8keFf9Hc0FpIXu
run: |
# Allow failure for coveralls
coveralls -v || true
- name: Backtesting
run: |
cp config_examples/config_bittrex.example.json config.json
freqtrade create-userdir --userdir user_data
freqtrade backtesting --datadir tests/testdata --strategy SampleStrategy
freqtrade new-strategy -s AwesomeStrategyAdv --template advanced
freqtrade backtesting --datadir tests/testdata --strategy AwesomeStrategyAdv
- name: Hyperopt
run: |
@@ -219,7 +211,7 @@ jobs:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v3
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
@@ -271,9 +263,9 @@ jobs:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v3
uses: actions/setup-python@v4
with:
python-version: 3.9
python-version: "3.10"
- name: pre-commit dependencies
run: |
@@ -290,9 +282,9 @@ jobs:
./tests/test_docs.sh
- name: Set up Python
uses: actions/setup-python@v3
uses: actions/setup-python@v4
with:
python-version: 3.9
python-version: "3.10"
- name: Documentation build
run: |
@@ -308,18 +300,6 @@ jobs:
details: Freqtrade doc test failed!
webhookUrl: ${{ secrets.DISCORD_WEBHOOK }}
cleanup-prior-runs:
permissions:
actions: write # for rokroskar/workflow-run-cleanup-action to obtain workflow name & cancel it
contents: read # for rokroskar/workflow-run-cleanup-action to obtain branch
runs-on: ubuntu-20.04
steps:
- name: Cleanup previous runs on this branch
uses: rokroskar/workflow-run-cleanup-action@v0.3.3
if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/stable' && github.repository == 'freqtrade/freqtrade'"
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
# Notify only once - when CI completes (and after deploy) in case it's successfull
notify-complete:
needs: [ build_linux, build_macos, build_windows, docs_check, mypy_version_check ]
@@ -356,9 +336,9 @@ jobs:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v3
uses: actions/setup-python@v4
with:
python-version: 3.8
python-version: "3.9"
- name: Extract branch name
shell: bash
@@ -371,7 +351,7 @@ jobs:
python setup.py sdist bdist_wheel
- name: Publish to PyPI (Test)
uses: pypa/gh-action-pypi-publish@master
uses: pypa/gh-action-pypi-publish@v1.5.1
if: (github.event_name == 'release')
with:
user: __token__
@@ -379,7 +359,7 @@ jobs:
repository_url: https://test.pypi.org/legacy/
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@master
uses: pypa/gh-action-pypi-publish@v1.5.1
if: (github.event_name == 'release')
with:
user: __token__
@@ -419,7 +399,7 @@ jobs:
- name: Discord notification
uses: rjstone/discord-webhook-notify@v1
if: always() && ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false)
if: always() && ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false) && (github.event_name != 'schedule')
with:
severity: info
details: Deploy Succeeded!

8
.gitignore vendored
View File

@@ -7,10 +7,15 @@ logfile.txt
user_data/*
!user_data/strategy/sample_strategy.py
!user_data/notebooks
!user_data/models
!user_data/freqaimodels
user_data/freqaimodels/*
user_data/models/*
user_data/notebooks/*
freqtrade-plot.html
freqtrade-profit-plot.html
freqtrade/rpc/api_server/ui/*
build_helpers/ta-lib/*
# Macos related
.DS_Store
@@ -80,6 +85,8 @@ instance/
# Sphinx documentation
docs/_build/
# Mkdocs documentation
site/
# PyBuilder
target/
@@ -105,3 +112,4 @@ target/
!config_examples/config_ftx.example.json
!config_examples/config_full.example.json
!config_examples/config_kraken.example.json
!config_examples/config_freqai.example.json

View File

@@ -13,11 +13,11 @@ repos:
- id: mypy
exclude: build_helpers
additional_dependencies:
- types-cachetools==5.0.1
- types-filelock==3.2.5
- types-requests==2.27.20
- types-tabulate==0.8.7
- types-python-dateutil==2.8.12
- types-cachetools==5.2.1
- types-filelock==3.2.7
- types-requests==2.28.8
- types-tabulate==0.8.11
- types-python-dateutil==2.8.19
# stages: [push]
- repo: https://github.com/pycqa/isort

View File

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

View File

@@ -9,10 +9,6 @@ Freqtrade is a free and open source crypto trading bot written in Python. It is
![freqtrade](https://raw.githubusercontent.com/freqtrade/freqtrade/develop/docs/assets/freqtrade-screenshot.png)
## Sponsored promotion
[![tokenbot-promo](https://raw.githubusercontent.com/freqtrade/freqtrade/develop/docs/assets/TokenBot-Freqtrade-banner.png)](https://tokenbot.com/?utm_source=github&utm_medium=freqtrade&utm_campaign=algodevs)
## Disclaimer
This software is for educational purposes only. Do not risk money which
@@ -39,7 +35,7 @@ Please read the [exchange specific notes](docs/exchanges.md) to learn about even
- [X] [OKX](https://okx.com/) (Former OKEX)
- [ ] [potentially many others](https://github.com/ccxt/ccxt/). _(We cannot guarantee they will work)_
### Experimentally, freqtrade also supports futures on the following exchanges
### Supported Futures Exchanges (experimental)
- [X] [Binance](https://www.binance.com/)
- [X] [Gate.io](https://www.gate.io/ref/6266643)
@@ -67,6 +63,7 @@ Please find the complete documentation on the [freqtrade website](https://www.fr
- [x] **Dry-run**: Run the bot without paying money.
- [x] **Backtesting**: Run a simulation of your buy/sell strategy.
- [x] **Strategy Optimization by machine learning**: Use machine learning to optimize your buy/sell strategy parameters with real exchange data.
- [X] **Adaptive prediction modeling**: Build a smart strategy with FreqAI that self-trains to the market via adaptive machine learning methods. [Learn more](https://www.freqtrade.io/en/stable/freqai/)
- [x] **Edge position sizing** Calculate your win rate, risk reward ratio, the best stoploss and adjust your position size before taking a position for each specific market. [Learn more](https://www.freqtrade.io/en/stable/edge/).
- [x] **Whitelist crypto-currencies**: Select which crypto-currency you want to trade or use dynamic whitelists.
- [x] **Blacklist crypto-currencies**: Select which crypto-currency you want to avoid.
@@ -197,7 +194,7 @@ Issues labeled [good first issue](https://github.com/freqtrade/freqtrade/labels/
The clock must be accurate, synchronized to a NTP server very frequently to avoid problems with communication to the exchanges.
### Min hardware required
### Minimum hardware required
To run this bot we recommend you a cloud instance with a minimum of:

View File

@@ -4,7 +4,7 @@ else
INSTALL_LOC=${1}
fi
echo "Installing to ${INSTALL_LOC}"
if [ ! -f "${INSTALL_LOC}/lib/libta_lib.a" ]; then
if [ -n "$2" ] || [ ! -f "${INSTALL_LOC}/lib/libta_lib.a" ]; then
tar zxvf ta-lib-0.4.0-src.tar.gz
cd ta-lib \
&& sed -i.bak "s|0.00000001|0.000000000000000001 |g" src/ta_func/ta_utility.h \
@@ -17,11 +17,17 @@ if [ ! -f "${INSTALL_LOC}/lib/libta_lib.a" ]; then
cd .. && rm -rf ./ta-lib/
exit 1
fi
if [ -z "$2" ]; then
which sudo && sudo make install || make install
if [ -x "$(command -v apt-get)" ]; then
echo "Updating library path using ldconfig"
sudo ldconfig
fi
else
# Don't install with sudo
make install
fi
cd .. && rm -rf ./ta-lib/
else
echo "TA-lib already installed, skipping installation"

View File

@@ -6,10 +6,12 @@ export DOCKER_BUILDKIT=1
# Replace / with _ to create a valid tag
TAG=$(echo "${BRANCH_NAME}" | sed -e "s/\//_/g")
TAG_PLOT=${TAG}_plot
TAG_FREQAI=${TAG}_freqai
TAG_PI="${TAG}_pi"
TAG_ARM=${TAG}_arm
TAG_PLOT_ARM=${TAG_PLOT}_arm
TAG_FREQAI_ARM=${TAG_FREQAI}_arm
CACHE_IMAGE=freqtradeorg/freqtrade_cache
echo "Running for ${TAG}"
@@ -38,8 +40,10 @@ fi
docker tag freqtrade:$TAG_ARM ${CACHE_IMAGE}:$TAG_ARM
docker build --cache-from freqtrade:${TAG_ARM} --build-arg sourceimage=${CACHE_IMAGE} --build-arg sourcetag=${TAG_ARM} -t freqtrade:${TAG_PLOT_ARM} -f docker/Dockerfile.plot .
docker build --cache-from freqtrade:${TAG_ARM} --build-arg sourceimage=${CACHE_IMAGE} --build-arg sourcetag=${TAG_ARM} -t freqtrade:${TAG_FREQAI_ARM} -f docker/Dockerfile.freqai .
docker tag freqtrade:$TAG_PLOT_ARM ${CACHE_IMAGE}:$TAG_PLOT_ARM
docker tag freqtrade:$TAG_FREQAI_ARM ${CACHE_IMAGE}:$TAG_FREQAI_ARM
# Run backtest
docker run --rm -v $(pwd)/config_examples/config_bittrex.example.json:/freqtrade/config.json:ro -v $(pwd)/tests:/tests freqtrade:${TAG_ARM} backtesting --datadir /tests/testdata --strategy-path /tests/strategy/strats/ --strategy StrategyTestV3
@@ -53,6 +57,7 @@ docker images
# docker push ${IMAGE_NAME}
docker push ${CACHE_IMAGE}:$TAG_PLOT_ARM
docker push ${CACHE_IMAGE}:$TAG_FREQAI_ARM
docker push ${CACHE_IMAGE}:$TAG_ARM
# Create multi-arch image
@@ -66,6 +71,9 @@ docker manifest push -p ${IMAGE_NAME}:${TAG}
docker manifest create ${IMAGE_NAME}:${TAG_PLOT} ${CACHE_IMAGE}:${TAG_PLOT_ARM} ${CACHE_IMAGE}:${TAG_PLOT}
docker manifest push -p ${IMAGE_NAME}:${TAG_PLOT}
docker manifest create ${IMAGE_NAME}:${TAG_FREQAI} ${CACHE_IMAGE}:${TAG_FREQAI_ARM} ${CACHE_IMAGE}:${TAG_FREQAI}
docker manifest push -p ${IMAGE_NAME}:${TAG_FREQAI}
# Tag as latest for develop builds
if [ "${TAG}" = "develop" ]; then
docker manifest create ${IMAGE_NAME}:latest ${CACHE_IMAGE}:${TAG_ARM} ${IMAGE_NAME}:${TAG_PI} ${CACHE_IMAGE}:${TAG}

View File

@@ -5,6 +5,7 @@
# Replace / with _ to create a valid tag
TAG=$(echo "${BRANCH_NAME}" | sed -e "s/\//_/g")
TAG_PLOT=${TAG}_plot
TAG_FREQAI=${TAG}_freqai
TAG_PI="${TAG}_pi"
PI_PLATFORM="linux/arm/v7"
@@ -49,8 +50,10 @@ fi
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 tag freqtrade:$TAG_PLOT ${CACHE_IMAGE}:$TAG_PLOT
docker tag freqtrade:$TAG_FREQAI ${CACHE_IMAGE}:$TAG_FREQAI
# Run backtest
docker run --rm -v $(pwd)/config_examples/config_bittrex.example.json:/freqtrade/config.json:ro -v $(pwd)/tests:/tests freqtrade:${TAG} backtesting --datadir /tests/testdata --strategy-path /tests/strategy/strats/ --strategy StrategyTestV3
@@ -64,6 +67,7 @@ docker images
docker push ${CACHE_IMAGE}
docker push ${CACHE_IMAGE}:$TAG_PLOT
docker push ${CACHE_IMAGE}:$TAG_FREQAI
docker push ${CACHE_IMAGE}:$TAG

View File

@@ -0,0 +1,96 @@
{
"trading_mode": "futures",
"margin_mode": "isolated",
"max_open_trades": 5,
"stake_currency": "USDT",
"stake_amount": 200,
"tradable_balance_ratio": 1,
"fiat_display_currency": "USD",
"dry_run": true,
"timeframe": "3m",
"dry_run_wallet": 1000,
"cancel_open_orders_on_exit": true,
"unfilledtimeout": {
"entry": 10,
"exit": 30
},
"exchange": {
"name": "binance",
"key": "",
"secret": "",
"ccxt_config": {
"enableRateLimit": true
},
"ccxt_async_config": {
"enableRateLimit": true,
"rateLimit": 200
},
"pair_whitelist": [
"1INCH/USDT",
"ALGO/USDT"
],
"pair_blacklist": []
},
"entry_pricing": {
"price_side": "same",
"use_order_book": true,
"order_book_top": 1,
"price_last_balance": 0.0,
"check_depth_of_market": {
"enabled": false,
"bids_to_ask_delta": 1
}
},
"exit_pricing": {
"price_side": "other",
"use_order_book": true,
"order_book_top": 1
},
"pairlists": [
{
"method": "StaticPairList"
}
],
"freqai": {
"enabled": true,
"startup_candles": 10000,
"purge_old_models": true,
"train_period_days": 15,
"backtest_period_days": 7,
"live_retrain_hours": 0,
"identifier": "uniqe-id",
"feature_parameters": {
"include_timeframes": [
"3m",
"15m",
"1h"
],
"include_corr_pairlist": [
"BTC/USDT",
"ETH/USDT"
],
"label_period_candles": 20,
"include_shifted_candles": 2,
"DI_threshold": 0.9,
"weight_factor": 0.9,
"principal_component_analysis": false,
"use_SVM_to_remove_outliers": true,
"stratify_training_data": 0,
"indicator_max_period_candles": 20,
"indicator_periods_candles": [10, 20]
},
"data_split_parameters": {
"test_size": 0.33,
"random_state": 1
},
"model_training_parameters": {
"n_estimators": 1000
}
},
"bot_name": "",
"force_entry_enable": true,
"initial_state": "running",
"internals": {
"process_throttle_secs": 5
}
}

View File

@@ -5,6 +5,7 @@
"tradable_balance_ratio": 0.99,
"fiat_display_currency": "USD",
"amount_reserve_percent": 0.05,
"available_capital": 1000,
"amend_last_stake_amount": false,
"last_stake_amount_min_ratio": 0.5,
"dry_run": true,
@@ -92,6 +93,7 @@
"secret": "your_exchange_secret",
"password": "",
"log_responses": false,
// "unknown_fee_rate": 1,
"ccxt_config": {},
"ccxt_async_config": {},
"pair_whitelist": [
@@ -155,7 +157,8 @@
"entry_cancel": "on",
"exit_cancel": "on",
"protection_trigger": "off",
"protection_trigger_global": "on"
"protection_trigger_global": "on",
"show_candle": "off"
},
"reload": true,
"balance_dust_level": 0.01

View File

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

View File

@@ -7,4 +7,5 @@ FROM freqtradeorg/freqtrade:develop
# The below dependency - pyti - serves as an example. Please use whatever you need!
RUN pip install --user pyti
# Switch back to user (only if you required root above)
# USER ftuser

9
docker/Dockerfile.freqai Normal file
View File

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

View File

@@ -22,50 +22,79 @@ DataFrame of the candles that resulted in buy signals. Depending on how many buy
makes, this file may get quite large, so periodically check your `user_data/backtest_results`
folder to delete old exports.
To analyze the buy tags, we need to use the `buy_reasons.py` script from
[froggleston's repo](https://github.com/froggleston/freqtrade-buyreasons). Follow the instructions
in their README to copy the script into your `freqtrade/scripts/` folder.
Before running your next backtest, make sure you either delete your old backtest results or run
backtesting with the `--cache none` option to make sure no cached results are used.
If all goes well, you should now see a `backtest-result-{timestamp}_signals.pkl` file in the
`user_data/backtest_results` folder.
Now run the `buy_reasons.py` script, supplying a few options:
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`):
``` bash
python3 scripts/buy_reasons.py -c <config.json> -s <strategy_name> -t <timerange> -g0,1,2,3,4
freqtrade backtesting-analysis -c <config.json> --analysis-groups 0 1 2 3 4
```
The `-g` option is used to specify the various tabular outputs, ranging from the simplest (0)
to the most detailed per pair, per buy and per sell tag (4). More options are available by
running with the `-h` option.
This command will read from the last backtesting results. The `--analysis-groups` option is
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):
* 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
* 4: profit summaries grouped by pair, enter_ and exit_tag (this can get quite large)
More options are available by running with the `-h` option.
### Using export-filename
Normally, `backtesting-analysis` uses the latest backtest results, but if you wanted to go
back to a previous backtest output, you need to supply the `--export-filename` option.
You can supply the same parameter to `backtest-analysis` with the name of the final backtest
output file. This allows you to keep historical versions of backtest results and re-analyse
them at a later date:
``` bash
freqtrade backtesting -c <config.json> --timeframe <tf> --strategy <strategy_name> --timerange=<timerange> --export=signals --export-filename=/tmp/mystrat_backtest.json
```
You should see some output similar to below in the logs with the name of the timestamped
filename that was exported:
```
2022-06-14 16:28:32,698 - freqtrade.misc - INFO - dumping json to "/tmp/mystrat_backtest-2022-06-14_16-28-32.json"
```
You can then use that filename in `backtesting-analysis`:
```
freqtrade backtesting-analysis -c <config.json> --export-filename=/tmp/mystrat_backtest-2022-06-14_16-28-32.json
```
### Tuning the buy tags and sell tags to display
To show only certain buy and sell tags in the displayed output, use the following two options:
```
--enter_reason_list : Comma separated list of enter signals to analyse. Default: "all"
--exit_reason_list : Comma separated list of exit signals to analyse. Default: "stop_loss,trailing_stop_loss"
--enter-reason-list : Space-separated list of enter signals to analyse. Default: "all"
--exit-reason-list : Space-separated list of exit signals to analyse. Default: "all"
```
For example:
```bash
python3 scripts/buy_reasons.py -c <config.json> -s <strategy_name> -t <timerange> -g0,1,2,3,4 --enter_reason_list "enter_tag_a,enter_tag_b" --exit_reason_list "roi,custom_exit_tag_a,stop_loss"
freqtrade backtesting-analysis -c <config.json> --analysis-groups 0 2 --enter-reason-list enter_tag_a enter_tag_b --exit-reason-list roi custom_exit_tag_a stop_loss
```
### Outputting signal candle indicators
The real power of the buy_reasons.py script comes from the ability to print out the indicator
The real power of `freqtrade backtesting-analysis` comes from the ability to print out the indicator
values present on signal candles to allow fine-grained investigation and tuning of buy signal
indicators. To print out a column for a given set of indicators, use the `--indicator-list`
option:
```bash
python3 scripts/buy_reasons.py -c <config.json> -s <strategy_name> -t <timerange> -g0,1,2,3,4 --enter_reason_list "enter_tag_a,enter_tag_b" --exit_reason_list "roi,custom_exit_tag_a,stop_loss" --indicator_list "rsi,rsi_1h,bb_lowerband,ema_9,macd,macdsignal"
freqtrade backtesting-analysis -c <config.json> --analysis-groups 0 2 --enter-reason-list enter_tag_a enter_tag_b --exit-reason-list roi custom_exit_tag_a stop_loss --indicator-list rsi rsi_1h bb_lowerband ema_9 macd macdsignal
```
The indicators have to be present in your strategy's main DataFrame (either for your main

View File

@@ -98,6 +98,23 @@ class MyAwesomeStrategy(IStrategy):
!!! Note
All overrides are optional and can be mixed/matched as necessary.
### 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.
``` python
class MyAwesomeStrategy(IStrategy):
def bot_start(self, **kwargs) -> None:
self.buy_adx = IntParameter(20, 30, default=30, optimize=True)
# ...
```
!!! Warning
Parameters created this way will not show up in the `list-strategies` parameter count.
### Overriding Base estimator
You can define your own estimator for Hyperopt by implementing `generate_estimator()` in the Hyperopt subclass.

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
docs/assets/freqai_algo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 995 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

View File

@@ -287,9 +287,9 @@ A backtesting result will look like that:
| ADA/BTC | 1 | 0.89 | 0.89 | 0.00004434 | 0.44 | 6:00:00 | 1 0 0 100 |
| LTC/BTC | 1 | 0.68 | 0.68 | 0.00003421 | 0.34 | 2:00:00 | 1 0 0 100 |
| TOTAL | 2 | 0.78 | 1.57 | 0.00007855 | 0.78 | 4:00:00 | 2 0 0 100 |
================ SUMMARY METRICS ===============
================== SUMMARY METRICS ==================
| Metric | Value |
|------------------------+---------------------|
|-----------------------------+---------------------|
| Backtesting from | 2019-01-01 00:00:00 |
| Backtesting to | 2019-05-01 00:00:00 |
| Max open trades | 3 |
@@ -300,10 +300,16 @@ A backtesting result will look like that:
| Absolute profit | 0.00762792 BTC |
| Total profit % | 76.2% |
| CAGR % | 460.87% |
| Trades per day | 3.575 |
| Profit factor | 1.11 |
| Avg. stake amount | 0.001 BTC |
| Total trade volume | 0.429 BTC |
| | |
| Long / Short | 352 / 77 |
| Total profit Long % | 1250.58% |
| Total profit Short % | -15.02% |
| Absolute profit Long | 0.00838792 BTC |
| Absolute profit Short | -0.00076 BTC |
| | |
| Best Pair | LSK/BTC 26.26% |
| Worst Pair | ZEC/BTC -10.18% |
| Best Trade | LSK/BTC 4.25% |
@@ -315,17 +321,21 @@ A backtesting result will look like that:
| Avg. Duration Loser | 6:55:00 |
| Rejected Entry signals | 3089 |
| Entry/Exit Timeouts | 0 / 0 |
| Canceled Trade Entries | 34 |
| Canceled Entry Orders | 123 |
| Replaced Entry Orders | 89 |
| | |
| Min balance | 0.00945123 BTC |
| Max balance | 0.01846651 BTC |
| Drawdown (Account) | 13.33% |
| Max % of account underwater | 25.19% |
| Absolute Drawdown (Account) | 13.33% |
| Drawdown | 0.0015 BTC |
| Drawdown high | 0.0013 BTC |
| Drawdown low | -0.0002 BTC |
| Drawdown Start | 2019-02-15 14:10:00 |
| Drawdown End | 2019-04-11 18:15:00 |
| Market change | -5.88% |
===============================================
=====================================================
```
### Backtesting report table
@@ -377,9 +387,9 @@ The last element of the backtest report is the summary metrics table.
It contains some useful key metrics about performance of your strategy on backtesting data.
```
================ SUMMARY METRICS ===============
================== SUMMARY METRICS ==================
| Metric | Value |
|------------------------+---------------------|
|-----------------------------+---------------------|
| Backtesting from | 2019-01-01 00:00:00 |
| Backtesting to | 2019-05-01 00:00:00 |
| Max open trades | 3 |
@@ -390,6 +400,7 @@ It contains some useful key metrics about performance of your strategy on backte
| Absolute profit | 0.00762792 BTC |
| Total profit % | 76.2% |
| CAGR % | 460.87% |
| Profit factor | 1.11 |
| Avg. stake amount | 0.001 BTC |
| Total trade volume | 0.429 BTC |
| | |
@@ -410,17 +421,21 @@ It contains some useful key metrics about performance of your strategy on backte
| Avg. Duration Loser | 6:55:00 |
| Rejected Entry signals | 3089 |
| Entry/Exit Timeouts | 0 / 0 |
| Canceled Trade Entries | 34 |
| Canceled Entry Orders | 123 |
| Replaced Entry Orders | 89 |
| | |
| Min balance | 0.00945123 BTC |
| Max balance | 0.01846651 BTC |
| Drawdown (Account) | 13.33% |
| Max % of account underwater | 25.19% |
| Absolute Drawdown (Account) | 13.33% |
| Drawdown | 0.0015 BTC |
| Drawdown high | 0.0013 BTC |
| Drawdown low | -0.0002 BTC |
| Drawdown Start | 2019-02-15 14:10:00 |
| Drawdown End | 2019-04-11 18:15:00 |
| Market change | -5.88% |
================================================
=====================================================
```
@@ -431,6 +446,8 @@ It contains some useful key metrics about performance of your strategy on backte
- `Final balance`: Final balance - starting balance + absolute profit.
- `Absolute profit`: Profit made in stake currency.
- `Total profit %`: Total profit. Aligned to the `TOTAL` row's `Tot Profit %` from the first table. Calculated as `(End capital Starting capital) / Starting capital`.
- `CAGR %`: Compound annual growth rate.
- `Profit factor`: profit / loss.
- `Avg. stake amount`: Average stake amount, either `stake_amount` or the average when using dynamic stake amount.
- `Total trade volume`: Volume generated on the exchange to reach the above profit.
- `Best Pair` / `Worst Pair`: Best and worst performing pair, and it's corresponding `Cum Profit %`.
@@ -440,8 +457,13 @@ It contains some useful key metrics about performance of your strategy on backte
- `Avg. Duration Winners` / `Avg. Duration Loser`: Average durations for winning and losing trades.
- `Rejected Entry signals`: Trade entry signals that could not be acted upon due to `max_open_trades` being reached.
- `Entry/Exit Timeouts`: Entry/exit orders which did not fill (only applicable if custom pricing is used).
- `Canceled Trade Entries`: Number of trades that have been canceled by user request via `adjust_entry_price`.
- `Canceled Entry Orders`: Number of entry orders that have been canceled by user request via `adjust_entry_price`.
- `Replaced Entry Orders`: Number of entry orders that have been replaced by user request via `adjust_entry_price`.
- `Min balance` / `Max balance`: Lowest and Highest Wallet balance during the backtest period.
- `Drawdown (Account)`: Maximum Account Drawdown experienced. Calculated as $(Absolute Drawdown) / (DrawdownHigh + startingBalance)$.
- `Max % of account underwater`: Maximum percentage your account has decreased from the top since the simulation started.
Calculated as the maximum of `(Max Balance - Current Balance) / (Max Balance)`.
- `Absolute Drawdown (Account)`: Maximum Account Drawdown experienced. Calculated as `(Absolute Drawdown) / (DrawdownHigh + startingBalance)`.
- `Drawdown`: Maximum, absolute drawdown experienced. Difference between Drawdown High and Subsequent Low point.
- `Drawdown high` / `Drawdown low`: Profit at the beginning and end of the largest drawdown period. A negative low value means initial capital lost.
- `Drawdown Start` / `Drawdown End`: Start and end datetime for this largest drawdown (can also be visualized via the `plot-dataframe` sub-command).
@@ -457,7 +479,7 @@ You can get an overview over daily / weekly or monthly results by using the `--b
To visualize daily and weekly breakdowns, you can use the following:
``` bash
freqtrade backtesting --strategy MyAwesomeStrategy --breakdown day month
freqtrade backtesting --strategy MyAwesomeStrategy --breakdown day week
```
``` output
@@ -473,7 +495,7 @@ freqtrade backtesting --strategy MyAwesomeStrategy --breakdown day month
```
The output will show a table containing the realized absolute Profit (in stake currency) for the given timeperiod, as well as wins, draws and losses that materialized (closed) on this day.
The output will show a table containing the realized absolute Profit (in stake currency) for the given timeperiod, as well as wins, draws and losses that materialized (closed) on this day. Below that there will be a second table for the summarized values of weeks indicated by the date of the closing Sunday. The same would apply to a monthly breakdown indicated by the last day of the month.
### Backtest result caching
@@ -492,6 +514,7 @@ You can then load the trades to perform further analysis as shown in the [data a
Since backtesting lacks some detailed information about what happens within a candle, it needs to take a few assumptions:
- Exchange [trading limits](#trading-limits-in-backtesting) are respected
- Buys happen at open-price
- All orders are filled at the requested price (no slippage, no unfilled orders)
- Exit-signal exits happen at open-price of the consecutive candle
@@ -512,15 +535,33 @@ Since backtesting lacks some detailed information about what happens within a ca
- Exit-reason does not explain if a trade was positive or negative, just what triggered the exit (this can look odd if negative ROI values are used)
- Evaluation sequence (if multiple signals happen on the same candle)
- Exit-signal
- ROI (if not stoploss)
- Stoploss
- ROI
- Trailing stoploss
Taking these assumptions, backtesting tries to mirror real trading as closely as possible. However, backtesting will **never** replace running a strategy in dry-run mode.
Also, keep in mind that past results don't guarantee future success.
In addition to the above assumptions, strategy authors should carefully read the [Common Mistakes](strategy-customization.md#common-mistakes-when-developing-strategies) section, to avoid using data in backtesting which is not available in real market conditions.
### Improved backtest accuracy
### Trading limits in backtesting
Exchanges have certain trading limits, like minimum base currency, or minimum stake (quote) currency.
These limits are usually listed in the exchange documentation as "trading rules" or similar.
Backtesting (as well as live and dry-run) does honor these limits, and will ensure that a stoploss can be placed below this value - so the value will be slightly higher than what the exchange specifies.
Freqtrade has however no information about historic limits.
This can lead to situations where trading-limits are inflated by using a historic price, resulting in minimum amounts > 50$.
For example:
BTC minimum tradable amount is 0.001.
BTC trades at 22.000\$ today (0.001 BTC is related to this) - but the backtesting period includes prices as high as 50.000\$.
Today's minimum would be `0.001 * 22_000` - or 22\$.
However the limit could also be 50$ - based on `0.001 * 50_000` in some historic setting.
## Improved backtest accuracy
One big limitation of backtesting is it's inability to know how prices moved intra-candle (was high before close, or viceversa?).
So assuming you run backtesting with a 1h timeframe, there will be 4 prices for that candle (Open, High, Low, Close).

View File

@@ -20,7 +20,9 @@ All profit calculations of Freqtrade include fees. For Backtesting / Hyperopt /
## Bot execution logic
Starting freqtrade in dry-run or live mode (using `freqtrade trade`) will start the bot and start the bot iteration loop.
By default, loop runs every few seconds (`internals.process_throttle_secs`) and does roughly the following in the following sequence:
This will also run the `bot_start()` callback.
By default, the bot loop runs every few seconds (`internals.process_throttle_secs`) and performs the following actions:
* Fetch open trades from persistence.
* Calculate current list of tradable pairs.
@@ -34,6 +36,7 @@ By default, loop runs every few seconds (`internals.process_throttle_secs`) and
* Check timeouts for open orders.
* Calls `check_entry_timeout()` strategy callback for open entry orders.
* Calls `check_exit_timeout()` strategy callback for open exit orders.
* Calls `adjust_entry_price()` strategy callback for open entry orders.
* Verifies existing positions and eventually places exit orders.
* Considers stoploss, ROI and exit-signal, `custom_exit()` and `custom_stoploss()`.
* Determine exit-price based on `exit_pricing` configuration setting or by using the `custom_exit_price()` callback.
@@ -53,11 +56,13 @@ This loop will be repeated again and again until the bot is stopped.
[backtesting](backtesting.md) or [hyperopt](hyperopt.md) do only part of the above logic, since most of the trading operations are fully simulated.
* Load historic data for configured pairlist.
* Calls `bot_start()` once.
* Calls `bot_loop_start()` once.
* Calculate indicators (calls `populate_indicators()` once per pair).
* Calculate entry / exit signals (calls `populate_entry_trend()` and `populate_exit_trend()` once per pair).
* Loops per candle simulating entry and exit points.
* Check for Order timeouts, either via the `unfilledtimeout` configuration, or via `check_entry_timeout()` / `check_exit_timeout()` strategy callbacks.
* Calls `adjust_entry_price()` strategy callback for open entry orders.
* Check for trade entry signals (`enter_long` / `enter_short` columns).
* Confirm trade entry / exits (calls `confirm_trade_entry()` and `confirm_trade_exit()` if implemented in the strategy).
* Call `custom_entry_price()` (if implemented in the strategy) to determine entry price (Prices are moved to be within the opening candle).

View File

@@ -105,7 +105,7 @@ This is similar to using multiple `--config` parameters, but simpler in usage as
``` json title="Result"
{
"max_open_trades": 10,
"max_open_trades": 3,
"stake_currency": "USDT",
"stake_amount": "unlimited"
}
@@ -116,6 +116,9 @@ This is similar to using multiple `--config` parameters, but simpler in usage as
The table below will list all configuration parameters available.
Freqtrade can also load many options via command line (CLI) arguments (check out the commands `--help` output for details).
### Configuration option prevalence
The prevalence for all Options is as follows:
- CLI arguments override any other option
@@ -123,6 +126,8 @@ The prevalence for all Options is as follows:
- Configuration files are used in sequence (the last file wins) and override Strategy configurations.
- Strategy configurations are only used if they are not set via configuration or command-line arguments. These options are marked with [Strategy Override](#parameters-in-the-strategy) in the below table.
### Parameters table
Mandatory parameters are marked as **Required**, which means that they are required to be set in one of the possible ways.
| Parameter | Description |
@@ -135,12 +140,12 @@ Mandatory parameters are marked as **Required**, which means that they are requi
| `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.
| `timeframe` | The timeframe to use (e.g `1m`, `5m`, `15m`, `30m`, `1h` ...). [Strategy Override](#parameters-in-the-strategy). <br> **Datatype:** String
| `timeframe` | The timeframe to use (e.g `1m`, `5m`, `15m`, `30m`, `1h` ...). Usually missing in configuration, and specified in the strategy. [Strategy Override](#parameters-in-the-strategy). <br> **Datatype:** String
| `fiat_display_currency` | Fiat currency used to show your profits. [More information below](#what-values-can-be-used-for-fiat_display_currency). <br> **Datatype:** String
| `dry_run` | **Required.** Define if the bot must be in Dry Run or production mode. <br>*Defaults to `true`.* <br> **Datatype:** Boolean
| `dry_run_wallet` | Define the starting amount in stake currency for the simulated wallet used by the bot running in Dry Run mode.<br>*Defaults to `1000`.* <br> **Datatype:** Float
| `cancel_open_orders_on_exit` | Cancel open orders when the `/stop` RPC command is issued, `Ctrl+C` is pressed or the bot dies unexpectedly. When set to `true`, this allows you to use `/stop` to cancel unfilled and partially filled orders in the event of a market crash. It does not impact open positions. <br>*Defaults to `false`.* <br> **Datatype:** Boolean
| `process_only_new_candles` | Enable processing of indicators only when new candles arrive. If false each loop populates the indicators, this will mean the same candle is processed many times creating system load but can be useful of your strategy depends on tick data not only candle. [Strategy Override](#parameters-in-the-strategy). <br>*Defaults to `false`.* <br> **Datatype:** Boolean
| `process_only_new_candles` | Enable processing of indicators only when new candles arrive. If false each loop populates the indicators, this will mean the same candle is processed many times creating system load but can be useful of your strategy depends on tick data not only candle. [Strategy Override](#parameters-in-the-strategy). <br>*Defaults to `true`.* <br> **Datatype:** Boolean
| `minimal_roi` | **Required.** Set the threshold as ratio the bot will use to exit a trade. [More information below](#understand-minimal_roi). [Strategy Override](#parameters-in-the-strategy). <br> **Datatype:** Dict
| `stoploss` | **Required.** Value as ratio of the stoploss used by the bot. More details in the [stoploss documentation](stoploss.md). [Strategy Override](#parameters-in-the-strategy). <br> **Datatype:** Float (as ratio)
| `trailing_stop` | Enables trailing stoploss (based on `stoploss` in either configuration or strategy file). More details in the [stoploss documentation](stoploss.md#trailing-stop-loss). [Strategy Override](#parameters-in-the-strategy). <br> **Datatype:** Boolean
@@ -148,13 +153,16 @@ 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
| `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.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_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
@@ -165,6 +173,8 @@ Mandatory parameters are marked as **Required**, which means that they are requi
| `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.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**
| `use_exit_signal` | Use exit signals produced by the strategy in addition to the `minimal_roi`. [Strategy Override](#parameters-in-the-strategy). <br>*Defaults to `true`.* <br> **Datatype:** Boolean
| `exit_profit_only` | Wait until the bot reaches `exit_profit_offset` before taking an exit decision. [Strategy Override](#parameters-in-the-strategy). <br>*Defaults to `false`.* <br> **Datatype:** Boolean
| `exit_profit_offset` | Exit-signal is only active above this value. Only active in combination with `exit_profit_only=True`. [Strategy Override](#parameters-in-the-strategy). <br>*Defaults to `0.0`.* <br> **Datatype:** Float (as ratio)
@@ -172,8 +182,9 @@ Mandatory parameters are marked as **Required**, which means that they are requi
| `ignore_buying_expired_candle_after` | Specifies the number of seconds until a buy signal is no longer used. <br> **Datatype:** Integer
| `order_types` | Configure order-types depending on the action (`"entry"`, `"exit"`, `"stoploss"`, `"stoploss_on_exchange"`). [More information below](#understand-order_types). [Strategy Override](#parameters-in-the-strategy).<br> **Datatype:** Dict
| `order_time_in_force` | Configure time in force for entry and exit orders. [More information below](#understand-order_time_in_force). [Strategy Override](#parameters-in-the-strategy). <br> **Datatype:** Dict
| `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
| `recursive_strategy_search` | Set to `true` to recursively search sub-directories inside `user_data/strategies` for a strategy. <br> **Datatype:** Boolean
| `position_adjustment_enable` | Enables the strategy to use position adjustments (additional buys or sells). [More information here](strategy-callbacks.md#adjust-trade-position). <br> [Strategy Override](#parameters-in-the-strategy). <br>*Defaults to `false`.*<br> **Datatype:** Boolean
| `max_entry_position_adjustment` | Maximum additional order(s) for each open trade on top of the first entry Order. Set it to `-1` for unlimited additional orders. [More information here](strategy-callbacks.md#adjust-trade-position). <br> [Strategy Override](#parameters-in-the-strategy). <br>*Defaults to `-1`.*<br> **Datatype:** Positive Integer or -1
| | **Exchange**
| `exchange.name` | **Required.** Name of the exchange class to use. [List below](#user-content-what-values-for-exchangename). <br> **Datatype:** String
| `exchange.sandbox` | Use the 'sandbox' version of the exchange, where the exchange provides a sandbox for risk-free integration. See [here](sandbox-testing.md) in more details.<br> **Datatype:** Boolean
| `exchange.key` | API key to use for the exchange. Only required when you are in production mode.<br>**Keep it in secret, do not disclose publicly.** <br> **Datatype:** String
@@ -190,14 +201,19 @@ Mandatory parameters are marked as **Required**, which means that they are requi
| `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
| `edge.*` | Please refer to [edge configuration document](edge.md) for detailed explanation.
| `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.
| `pairlists` | Define one or more pairlists to be used. [More information](plugins.md#pairlists-and-pairlist-handlers). <br>*Defaults to `StaticPairList`.* <br> **Datatype:** List of Dicts
| `protections` | Define one or more protections to be used. [More information](plugins.md#protections). <br> **Datatype:** List of Dicts
| | **Telegram**
| `telegram.enabled` | Enable the usage of Telegram. <br> **Datatype:** Boolean
| `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.notification_settings.*` | Detailed notification settings. Refer to the [telegram documentation](telegram-usage.md) for details.<br> **Datatype:** dictionary
| | **Webhook**
| `webhook.enabled` | Enable usage of Webhook notifications <br> **Datatype:** Boolean
| `webhook.url` | URL for the webhook. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
| `webhook.webhookentry` | Payload to send on entry. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
@@ -207,6 +223,7 @@ Mandatory parameters are marked as **Required**, which means that they are requi
| `webhook.webhookexitcancel` | Payload to send on exit order cancel. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
| `webhook.webhookexitfill` | Payload to send on exit order filled. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
| `webhook.webhookstatus` | Payload to send on status calls. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
| | **Rest API / FreqUI**
| `api_server.enabled` | Enable usage of API Server. See the [API Server documentation](rest-api.md) for more details. <br> **Datatype:** Boolean
| `api_server.listen_ip_address` | Bind IP address. See the [API Server documentation](rest-api.md) for more details. <br> **Datatype:** IPv4
| `api_server.listen_port` | Bind Port. See the [API Server documentation](rest-api.md) for more details. <br>**Datatype:** Integer between 1024 and 65535
@@ -214,22 +231,22 @@ Mandatory parameters are marked as **Required**, which means that they are requi
| `api_server.username` | Username for API server. See the [API Server documentation](rest-api.md) for more details. <br>**Keep it in secret, do not disclose publicly.**<br> **Datatype:** String
| `api_server.password` | Password for API server. See the [API Server documentation](rest-api.md) for more details. <br>**Keep it in secret, do not disclose publicly.**<br> **Datatype:** String
| `bot_name` | Name of the bot. Passed via API to a client - can be shown to distinguish / name bots.<br> *Defaults to `freqtrade`*<br> **Datatype:** String
| `db_url` | Declares database URL to use. NOTE: This defaults to `sqlite:///tradesv3.dryrun.sqlite` if `dry_run` is `true`, and to `sqlite:///tradesv3.sqlite` for production instances. <br> **Datatype:** String, SQLAlchemy connect string
| | **Other**
| `initial_state` | Defines the initial application state. If set to stopped, then the bot has to be explicitly started via `/start` RPC command. <br>*Defaults to `stopped`.* <br> **Datatype:** Enum, either `stopped` or `running`
| `force_entry_enable` | Enables the RPC Commands to force a Trade entry. More information below. <br> **Datatype:** Boolean
| `disable_dataframe_checks` | Disable checking the OHLCV dataframe returned from the strategy methods for correctness. Only use when intentionally changing the dataframe and understand what you are doing. [Strategy Override](#parameters-in-the-strategy).<br> *Defaults to `False`*. <br> **Datatype:** Boolean
| `strategy` | **Required** Defines Strategy class to use. Recommended to be set via `--strategy NAME`. <br> **Datatype:** ClassName
| `strategy_path` | Adds an additional strategy lookup path (must be a directory). <br> **Datatype:** String
| `internals.process_throttle_secs` | Set the process throttle, or minimum loop duration for one bot iteration loop. Value in second. <br>*Defaults to `5` seconds.* <br> **Datatype:** Positive Integer
| `internals.heartbeat_interval` | Print heartbeat message every N seconds. Set to 0 to disable heartbeat messages. <br>*Defaults to `60` seconds.* <br> **Datatype:** Positive Integer or 0
| `internals.sd_notify` | Enables use of the sd_notify protocol to tell systemd service manager about changes in the bot state and issue keep-alive pings. See [here](installation.md#7-optional-configure-freqtrade-as-a-systemd-service) for more details. <br> **Datatype:** Boolean
| `logfile` | Specifies logfile name. Uses a rolling strategy for log file rotation for 10 files with the 1MB limit per file. <br> **Datatype:** String
| `strategy` | **Required** Defines Strategy class to use. Recommended to be set via `--strategy NAME`. <br> **Datatype:** ClassName
| `strategy_path` | Adds an additional strategy lookup path (must be a directory). <br> **Datatype:** String
| `recursive_strategy_search` | Set to `true` to recursively search sub-directories inside `user_data/strategies` for a strategy. <br> **Datatype:** Boolean
| `user_data_dir` | Directory containing user data. <br> *Defaults to `./user_data/`*. <br> **Datatype:** String
| `db_url` | Declares database URL to use. NOTE: This defaults to `sqlite:///tradesv3.dryrun.sqlite` if `dry_run` is `true`, and to `sqlite:///tradesv3.sqlite` for production instances. <br> **Datatype:** String, SQLAlchemy connect string
| `logfile` | Specifies logfile name. Uses a rolling strategy for log file rotation for 10 files with the 1MB limit per file. <br> **Datatype:** String
| `add_config_files` | Additional config files. These files will be loaded and merged with the current config file. The files are resolved relative to the initial file.<br> *Defaults to `[]`*. <br> **Datatype:** List of strings
| `dataformat_ohlcv` | Data format to use to store historical candle (OHLCV) data. <br> *Defaults to `json`*. <br> **Datatype:** String
| `dataformat_trades` | Data format to use to store historical trades data. <br> *Defaults to `jsongz`*. <br> **Datatype:** String
| `position_adjustment_enable` | Enables the strategy to use position adjustments (additional buys or sells). [More information here](strategy-callbacks.md#adjust-trade-position). <br> [Strategy Override](#parameters-in-the-strategy). <br>*Defaults to `false`.*<br> **Datatype:** Boolean
| `max_entry_position_adjustment` | Maximum additional order(s) for each open trade on top of the first entry Order. Set it to `-1` for unlimited additional orders. [More information here](strategy-callbacks.md#adjust-trade-position). <br> [Strategy Override](#parameters-in-the-strategy). <br>*Defaults to `-1`.*<br> **Datatype:** Positive Integer or -1
### Parameters in the strategy
@@ -583,7 +600,7 @@ Once you will be happy with your bot performance running in the Dry-run mode, yo
* Market orders fill based on orderbook volume the moment the order is placed.
* Limit orders fill once the price reaches the defined level - or time out based on `unfilledtimeout` settings.
* In combination with `stoploss_on_exchange`, the stop_loss price is assumed to be filled.
* Open orders (not trades, which are stored in the database) are reset on bot restart.
* Open orders (not trades, which are stored in the database) are kept open after bot restarts, with the assumption that they were not filled while being offline.
## Switch to production mode

View File

@@ -30,6 +30,7 @@ usage: freqtrade download-data [-h] [-v] [--logfile FILE] [-V] [-c PATH]
[--data-format-ohlcv {json,jsongz,hdf5}]
[--data-format-trades {json,jsongz,hdf5}]
[--trading-mode {spot,margin,futures}]
[--prepend]
optional arguments:
-h, --help show this help message and exit
@@ -62,6 +63,7 @@ optional arguments:
`jsongz`).
--trading-mode {spot,margin,futures}
Select Trading mode
--prepend Allow data prepending.
Common arguments:
-v, --verbose Verbose mode (-vv for more, -vvv to get all messages).
@@ -157,10 +159,21 @@ freqtrade download-data --exchange binance --pairs .*/USDT
- To change the exchange used to download the historical data from, please use a different configuration file (you'll probably need to adjust rate limits etc.)
- To use `pairs.json` from some other directory, use `--pairs-file some_other_dir/pairs.json`.
- To download historical candle (OHLCV) data for only 10 days, use `--days 10` (defaults to 30 days).
- To download historical candle (OHLCV) data from a fixed starting point, use `--timerange 20200101-` - which will download all data from January 1st, 2020. Eventually set end dates are ignored.
- To download historical candle (OHLCV) data from a fixed starting point, use `--timerange 20200101-` - which will download all data from January 1st, 2020.
- Use `--timeframes` to specify what timeframe download the historical candle (OHLCV) data for. Default is `--timeframes 1m 5m` which will download 1-minute and 5-minute data.
- To use exchange, timeframe and list of pairs as defined in your configuration file, use the `-c/--config` option. With this, the script uses the whitelist defined in the config as the list of currency pairs to download data for and does not require the pairs.json file. You can combine `-c/--config` with most other options.
#### Download additional data before the current timerange
Assuming you downloaded all data from 2022 (`--timerange 20220101-`) - but you'd now like to also backtest with earlier data.
You can do so by using the `--prepend` flag, combined with `--timerange` - specifying an end-date.
``` bash
freqtrade download-data --exchange binance --pairs ETH/USDT XRP/USDT BTC/USDT --prepend --timerange 20210101-20220101
```
!!! Note
Freqtrade will ignore the end-date in this mode if data is available, updating the end-date to the existing data start point.
### Data format

View File

@@ -68,6 +68,36 @@ def test_method_to_test(caplog):
```
### Debug configuration
To debug freqtrade, we recommend VSCode with the following launch configuration (located in `.vscode/launch.json`).
Details will obviously vary between setups - but this should work to get you started.
``` json
{
"name": "freqtrade trade",
"type": "python",
"request": "launch",
"module": "freqtrade",
"console": "integratedTerminal",
"args": [
"trade",
// Optional:
// "--userdir", "user_data",
"--strategy",
"MyAwesomeStrategy",
]
},
```
Command line arguments can be added in the `"args"` array.
This method can also be used to debug a strategy, by setting the breakpoints within the strategy.
A similar setup can also be taken for Pycharm - using `freqtrade` as module name, and setting the command line arguments as "parameters".
!!! Note "Startup directory"
This assumes that you have the repository checked out, and the editor is started at the repository root level (so setup.py is at the top level of your repository).
## ErrorHandling
Freqtrade Exceptions all inherit from `FreqtradeException`.
@@ -200,11 +230,12 @@ For that reason, they must implement the following methods:
* `global_stop()`
* `stop_per_pair()`.
`global_stop()` and `stop_per_pair()` must return a ProtectionReturn tuple, which consists of:
`global_stop()` and `stop_per_pair()` must return a ProtectionReturn object, which consists of:
* lock pair - boolean
* lock until - datetime - until when should the pair be locked (will be rounded up to the next new candle)
* reason - string, used for logging and storage in the database
* lock_side - long, short or '*'.
The `until` portion should be calculated using the provided `calculate_lock_end()` method.
@@ -313,6 +344,32 @@ The output will show the last entry from the Exchange as well as the current UTC
If the day shows the same day, then the last candle can be assumed as incomplete and should be dropped (leave the setting `"ohlcv_partial_candle"` from the exchange-class untouched / True). Otherwise, set `"ohlcv_partial_candle"` to `False` to not drop Candles (shown in the example above).
Another way is to run this command multiple times in a row and observe if the volume is changing (while the date remains the same).
### Update binance cached leverage tiers
Updating leveraged tiers should be done regularly - and requires an authenticated account with futures enabled.
``` python
import ccxt
import json
from pathlib import Path
exchange = ccxt.binance({
'apiKey': '<apikey>',
'secret': '<secret>'
'options': {'defaultType': 'future'}
})
_ = exchange.load_markets()
lev_tiers = exchange.fetch_leverage_tiers()
# Assumes this is running in the root of the repository.
file = Path('freqtrade/exchange/binance_leverage_tiers.json')
json.dump(dict(sorted(lev_tiers.items())), file.open('w'), indent=2)
```
This file should then be contributed upstream, so others can benefit from this, too.
## Updating example notebooks
To keep the jupyter notebooks aligned with the documentation, the following should be ran after updating a example notebook.

View File

@@ -230,6 +230,11 @@ OKX requires a passphrase for each api key, you will therefore need to add this
!!! Warning
OKX only provides 100 candles per api call. Therefore, the strategy will only have a pretty low amount of data available in backtesting mode.
!!! Warning "Futures"
OKX Futures has the concept of "position mode" - which can be Net or long/short (hedge mode).
Freqtrade supports both modes - but changing the mode mid-trading is not supported and will lead to exceptions and failures to place trades.
OKX also only provides MARK candles for the past ~3 months. Backtesting futures prior to that date will therefore lead to slight deviations, as funding-fees cannot be calculated correctly without this data.
## Gate.io
!!! Tip "Stoploss on Exchange"

769
docs/freqai.md Normal file
View File

@@ -0,0 +1,769 @@
![freqai-logo](assets/freqai_doc_logo.svg)
# FreqAI
FreqAI is a module designed to automate a variety of tasks associated with training a predictive model to generate market forecasts given a set of input features.
Among the the features included:
* **Self-adaptive retraining**: retrain models during live deployments to self-adapt to the market in an unsupervised manner.
* **Rapid feature engineering**: create large rich feature sets (10k+ features) based on simple user created strategies.
* **High performance**: adaptive retraining occurs on separate thread (or on GPU if available) from inferencing and bot trade operations. Keep newest models and data in memory for rapid inferencing.
* **Realistic backtesting**: emulate self-adaptive retraining with backtesting module that automates past retraining.
* **Modifiable**: use the generalized and robust architecture for incorporating any machine learning library/method available in Python. Seven examples available.
* **Smart outlier removal**: remove outliers from training and prediction sets using a variety of outlier detection techniques.
* **Crash resilience**: model storage to disk to make reloading from a crash fast and easy (and purge obsolete files for sustained dry/live runs).
* **Automated data normalization**: normalize the data in a smart and statistically safe way.
* **Automatic data download**: compute the data download timerange and update historic data (in live deployments).
* **Clean incoming data** safe NaN handling before training and prediction.
* **Dimensionality reduction**: reduce the size of the training data via Principal Component Analysis.
* **Deploy bot fleets**: set one bot to train models while a fleet of other bots inference into the models and handle trades.
## Quick start
The easiest way to quickly test FreqAI is to run it in dry run with the following command
```bash
freqtrade trade --config config_examples/config_freqai.example.json --strategy FreqaiExampleStrategy --freqaimodel LightGBMRegressor --strategy-path freqtrade/templates
```
where the user will see the boot-up process of auto-data downloading, followed by simultaneous training and trading.
The example strategy, example prediction model, and example config can all be found in
`freqtrade/templates/FreqaiExampleStrategy.py`, `freqtrade/freqai/prediction_models/LightGBMRegressor.py`,
`config_examples/config_freqai.example.json`, respectively.
## General approach
The user provides FreqAI with a set of custom *base* indicators (created inside the strategy the same way
a typical Freqtrade strategy is created) as well as target values which look into the future.
FreqAI trains a model to predict the target value based on the input of custom indicators for each pair in the whitelist. These models are consistently retrained to adapt to market conditions. FreqAI offers the ability to both backtest strategies (emulating reality with periodic retraining) and deploy dry/live. In dry/live conditions, FreqAI can be set to constant retraining in a background thread in an effort to keep models as young as possible.
An overview of the algorithm is shown here to help users understand the data processing pipeline and the model usage.
![freqai-algo](assets/freqai_algo.png)
## Background and vocabulary
**Features** are the quantities with which a model is trained. $X_i$ represents the
vector of all features for a single candle. In FreqAI, the user
builds the features from anything they can construct in the strategy.
**Labels** are the target values with which the weights inside a model are trained
toward. Each set of features is associated with a single label, which is also
defined within the strategy by the user. These labels intentionally look into the
future, and are not available to the model during dryrun/live/backtesting.
**Training** refers to the process of feeding individual feature sets into the
model with associated labels with the goal of matching input feature sets to associated labels.
**Train data** is a subset of the historic data which is fed to the model during
training to adjust weights. This data directly influences weight connections in the model.
**Test data** is a subset of the historic data which is used to evaluate the
intermediate performance of the model during training. This data does not
directly influence nodal weights within the model.
## Install prerequisites
The normal Freqtrade install process will ask the user if they wish to install FreqAI dependencies. The user should reply "yes" to this question if they wish to use FreqAI. If the user did not reply yes, they can manually install these dependencies after the install with:
``` bash
pip install -r requirements-freqai.txt
```
!!! Note
Catboost will not be installed on arm devices (raspberry, Mac M1, ARM based VPS, ...), since Catboost does not provide wheels for this platform.
### Usage with docker
For docker users, 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.
## Configuring FreqAI
### Parameter table
The table below will list all configuration parameters available for FreqAI.
Mandatory parameters are marked as **Required**, which means that they are required to be set in one of the possible ways.
| Parameter | Description |
|------------|-------------|
| `freqai` | **Required.** The parent dictionary containing all the parameters below for controlling FreqAI. <br> **Datatype:** dictionary.
| `identifier` | **Required.** A unique name for the current model. This can be reused to reload pre-trained models/data. <br> **Datatype:** string.
| `train_period_days` | **Required.** Number of days to use for the training data (width of the sliding window). <br> **Datatype:** positive integer.
| `backtest_period_days` | **Required.** Number of days to inference into the trained model before sliding the window and retraining. This can be fractional days, but beware that the user provided `timerange` will be divided by this number to yield the number of trainings necessary to complete the backtest. <br> **Datatype:** Float.
| `live_retrain_hours` | Frequency of retraining during dry/live runs. Default set to 0, which means it will retrain as often as possible. <br> **Datatype:** Float > 0.
| `follow_mode` | If true, this instance of FreqAI will look for models associated with `identifier` and load those for inferencing. A `follower` will **not** train new models. `False` by default. <br> **Datatype:** boolean.
| `startup_candles` | Number of candles needed for *backtesting only* to ensure all indicators are non NaNs at the start of the first train period. <br> **Datatype:** positive integer.
| `fit_live_predictions_candles` | Computes target (label) statistics from prediction data, instead of from the training data set. Number of candles is the number of historical candles it uses to generate the statistics. <br> **Datatype:** positive integer.
| `purge_old_models` | Tell FreqAI to delete obsolete models. Otherwise, all historic models will remain on disk. Defaults to `False`. <br> **Datatype:** boolean.
| `expiration_hours` | Ask FreqAI to avoid making predictions if a model is more than `expiration_hours` old. Defaults to 0 which means models never expire. <br> **Datatype:** positive integer.
| | **Feature Parameters**
| `feature_parameters` | A dictionary containing the parameters used to engineer the feature set. Details and examples shown [here](#feature-engineering) <br> **Datatype:** dictionary.
| `include_corr_pairlist` | A list of correlated coins that FreqAI will add as additional features to all `pair_whitelist` coins. All indicators set in `populate_any_indicators` will be created for each coin in this list, and that set of features is added to the base asset feature set. <br> **Datatype:** list of assets (strings).
| `include_timeframes` | A list of timeframes that all indicators in `populate_any_indicators` will be created for and added as features to the base asset feature set. <br> **Datatype:** list of timeframes (strings).
| `label_period_candles` | Number of candles into the future that the labels are created for. This is used in `populate_any_indicators`, refer to `templates/FreqaiExampleStrategy.py` for detailed usage. The user can create custom labels, making use of this parameter not. <br> **Datatype:** positive integer.
| `include_shifted_candles` | Parameter used to add a sense of temporal recency to flattened regression type input data. `include_shifted_candles` takes all features, duplicates and shifts them by the number indicated by user. <br> **Datatype:** positive integer.
| `DI_threshold` | Activates the Dissimilarity Index for outlier detection when above 0, explained in detail [here](#removing-outliers-with-the-dissimilarity-index). <br> **Datatype:** positive float (typically below 1).
| `weight_factor` | Used to set weights for training data points according to their recency, see details and a figure of how it works [here](#controlling-the-model-learning-process). <br> **Datatype:** positive float (typically below 1).
| `principal_component_analysis` | Ask FreqAI to automatically reduce the dimensionality of the data set using PCA. <br> **Datatype:** boolean.
| `use_SVM_to_remove_outliers` | Ask FreqAI to train a support vector machine to detect and remove outliers from the training data set as well as from incoming data points. <br> **Datatype:** boolean.
| `svm_params` | All parameters available in Sklearn's `SGDOneClassSVM()`. E.g. `nu` *Very* broadly, is the percentage of data points that should be considered outliers. `shuffle` is by default false to maintain reproducibility. But these and all others can be added/changed in this dictionary. <br> **Datatype:** dictionary.
| `stratify_training_data` | This value is used to indicate the stratification of the data. e.g. 2 would set every 2nd data point into a separate dataset to be pulled from during training/testing. <br> **Datatype:** positive integer.
| `indicator_max_period_candles` | The maximum *period* used in `populate_any_indicators()` for indicator creation. FreqAI uses this information in combination with the maximum timeframe to calculate how many data points it should download so that the first data point does not have a NaN <br> **Datatype:** positive integer.
| `indicator_periods_candles` | A list of integers used to duplicate all indicators according to a set of periods and add them to the feature set. <br> **Datatype:** list of positive integers.
| `use_DBSCAN_to_remove_outliers` | Inactive by default. If true, FreqAI clusters data using DBSCAN to identify and remove outliers from training and prediction data. <br> **Datatype:** float (fraction of 1).
| | **Data split parameters**
| `data_split_parameters` | Include any additional parameters available from Scikit-learn `test_train_split()`, which are shown [here](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html) <br> **Datatype:** dictionary.
| `test_size` | Fraction of data that should be used for testing instead of training. <br> **Datatype:** positive float below 1.
| `shuffle` | Shuffle the training data points during training. Typically for time-series forecasting, this is set to False. <br> **Datatype:** boolean.
| | **Model training parameters**
| `model_training_parameters` | A flexible dictionary that includes all parameters available by the user selected library. For example, if the user uses `LightGBMRegressor`, then this dictionary can contain any parameter available by the `LightGBMRegressor` [here](https://lightgbm.readthedocs.io/en/latest/pythonapi/lightgbm.LGBMRegressor.html). If the user selects a different model, then this dictionary can contain any parameter from that different model. <br> **Datatype:** dictionary.
| `n_estimators` | A common parameter among regressors which sets the number of boosted trees to fit <br> **Datatype:** integer.
| `learning_rate` | A common parameter among regressors which sets the boosting learning rate. <br> **Datatype:** float.
| `n_jobs`, `thread_count`, `task_type` | Different libraries use different parameter names to control the number of threads used for parallel processing or whether or not it is a `task_type` of `gpu` or `cpu`. <br> **Datatype:** float.
| | **Extraneous parameters**
| `keras` | If your model makes use of keras (typical of Tensorflow based prediction models), activate this flag so that the model save/loading follows keras standards. Default value `false` <br> **Datatype:** boolean.
| `conv_width` | The width of a convolutional neural network input tensor. This replaces the need for `shift` 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. Default value, 2 <br> **Datatype:** integer.
### Important FreqAI dataframe key patterns
Here are the values the user can expect to include/use inside the typical strategy dataframe (`df[]`):
| DataFrame Key | Description |
|------------|-------------|
| `df['&*']` | Any dataframe column prepended with `&` in `populate_any_indicators()` is treated as a training target inside FreqAI (typically following the naming convention `&-s*`). These same dataframe columns names are fed back to the user as the predictions. For example, the user wishes to predict the price change in the next 40 candles (similar to `templates/FreqaiExampleStrategy.py`) by setting `df['&-s_close']`. FreqAI makes the predictions and gives them back to the user 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']` | The standard deviation and mean values of the user defined labels during training (or live tracking with `fit_live_predictions_candles`). Commonly used to understand rarity of prediction (use the z-score as shown in `templates/FreqaiExampleStrategy.py` to evaluate how often a particular prediction was observed during training (or historically with `fit_live_predictions_candles`)<br> **Datatype:** float.
| `df['do_predict']` | An indication of an outlier, this return value is integer between -1 and 2 which lets the user understand if the prediction is trustworthy or not. `do_predict==1` means the prediction is trustworthy. If the [Dissimilarity Index](#removing-outliers-with-the-dissimilarity-index) is above the user defined threshold, it will subtract 1 from `do_predict`. If `use_SVM_to_remove_outliers()` is active, then the Support Vector Machine (SVM) may also detect outliers in training and prediction data. In this case, the SVM will also subtract one from `do_predict`. A particular case is when `do_predict == 2`, it means that the model has expired due to `expired_hours`. <br> **Datatype:** integer between -1 and 2.
| `df['DI_values']` | The raw Dissimilarity Index values to give the user a sense of confidence in the prediction. Lower DI means the data point is closer to the trained parameter space. <br> **Datatype:** float.
| `df['%*']` | Any dataframe column prepended with `%` in `populate_any_indicators()` is treated as a training feature inside FreqAI. For example, the user can include the rsi in the training feature set (similar to `templates/FreqaiExampleStrategy.py`) by setting `df['%-rsi']`. See more details on how this is done [here](#building-the-feature-set). <br>**Note**: since the number of features prepended with `%` can multiply very quickly (10s of thousands of features is easily engineered using the multiplictative functionality described in the `feature_parameters` table.) these features are removed from the dataframe upon return from FreqAI. If the user wishes to keep a particular type of feature for plotting purposes, you can prepend it with `%%`. <br> **Datatype:** depends on the output of the model.
### Example config file
The user interface is isolated to the typical config file. A typical FreqAI config setup could include:
```json
"freqai": {
"startup_candles": 10000,
"purge_old_models": true,
"train_period_days": 30,
"backtest_period_days": 7,
"identifier" : "unique-id",
"feature_parameters" : {
"include_timeframes": ["5m","15m","4h"],
"include_corr_pairlist": [
"ETH/USD",
"LINK/USD",
"BNB/USD"
],
"label_period_candles": 24,
"include_shifted_candles": 2,
"weight_factor": 0,
"indicator_max_period_candles": 20,
"indicator_periods_candles": [10, 20]
},
"data_split_parameters" : {
"test_size": 0.25,
"random_state": 42
},
"model_training_parameters" : {
"n_estimators": 100,
"random_state": 42,
"learning_rate": 0.02,
"task_type": "CPU",
},
}
```
### Feature engineering
Features are added by the user inside the `populate_any_indicators()` method of the strategy
by prepending indicators with `%` and labels are added by prepending `&`.
There are some important components/structures that the user *must* include when building their feature set.
Another structure to consider is the location of the labels at the bottom of the example function (below `if set_generalized_indicators:`).
This is where the user will add single features and labels to their feature set to avoid duplication from
various configuration parameters which multiply the feature set such as `include_timeframes`.
```python
def populate_any_indicators(
self, pair, df, tf, informative=None, set_generalized_indicators=False
):
"""
Function designed to automatically generate, name and merge features
from user indicated timeframes in the configuration file. User controls the indicators
passed to the training/prediction by prepending indicators with `'%-' + coin `
(see convention below). I.e. user should not prepend any supporting metrics
(e.g. bb_lowerband below) with % unless they explicitly want to pass that metric to the
model.
:param pair: pair to be used as informative
:param df: strategy dataframe which will receive merges from informatives
:param tf: timeframe of the dataframe which will modify the feature names
:param informative: the dataframe associated with the informative pair
:param coin: the name of the coin which will modify the feature names.
"""
coint = pair.split('/')[0]
if informative is None:
informative = self.dp.get_pair_dataframe(pair, tf)
# first loop is automatically duplicating indicators for time periods
for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]:
t = int(t)
informative[f"%-{coin}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t)
informative[f"%-{coin}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t)
informative[f"%-{coin}adx-period_{t}"] = ta.ADX(informative, window=t)
bollinger = qtpylib.bollinger_bands(
qtpylib.typical_price(informative), window=t, stds=2.2
)
informative[f"{coin}bb_lowerband-period_{t}"] = bollinger["lower"]
informative[f"{coin}bb_middleband-period_{t}"] = bollinger["mid"]
informative[f"{coin}bb_upperband-period_{t}"] = bollinger["upper"]
informative[f"%-{coin}bb_width-period_{t}"] = (
informative[f"{coin}bb_upperband-period_{t}"]
- informative[f"{coin}bb_lowerband-period_{t}"]
) / informative[f"{coin}bb_middleband-period_{t}"]
informative[f"%-{coin}close-bb_lower-period_{t}"] = (
informative["close"] / informative[f"{coin}bb_lowerband-period_{t}"]
)
informative[f"%-{coin}relative_volume-period_{t}"] = (
informative["volume"] / informative["volume"].rolling(t).mean()
)
indicators = [col for col in informative if col.startswith("%")]
# This loop duplicates and shifts all indicators to add a sense of recency to data
for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1):
if n == 0:
continue
informative_shift = informative[indicators].shift(n)
informative_shift = informative_shift.add_suffix("_shift-" + str(n))
informative = pd.concat((informative, informative_shift), axis=1)
df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True)
skip_columns = [
(s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"]
]
df = df.drop(columns=skip_columns)
# Add generalized indicators here (because in live, it will call this
# function to populate indicators during training). Notice how we ensure not to
# add them multiple times
if set_generalized_indicators:
df["%-day_of_week"] = (df["date"].dt.dayofweek + 1) / 7
df["%-hour_of_day"] = (df["date"].dt.hour + 1) / 25
# user adds targets here by prepending them with &- (see convention below)
# If user wishes to use multiple targets, a multioutput prediction model
# needs to be used such as templates/CatboostPredictionMultiModel.py
df["&-s_close"] = (
df["close"]
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
.mean()
/ df["close"]
- 1
)
return df
```
The user of the present example does not wish to pass the `bb_lowerband` as a feature to the model,
and has therefore not prepended it with `%`. The user does, however, wish to pass `bb_width` to the
model for training/prediction and has therefore prepended it with `%`.
The `include_timeframes` from the example config above are the timeframes (`tf`) of each call to `populate_any_indicators()`
included metric for inclusion in the feature set. In the present case, the user is asking for the
`5m`, `15m`, and `4h` timeframes of the `rsi`, `mfi`, `roc`, and `bb_width` to be included in the feature set.
In addition, the user can ask for each of these features to be included from
informative pairs using the `include_corr_pairlist`. This means that the present feature
set will include all the features from `populate_any_indicators` on all the `include_timeframes` for each of
`ETH/USD`, `LINK/USD`, and `BNB/USD`.
`include_shifted_candles` is another user controlled parameter which indicates the number of previous
candles to include in the present feature set. In other words, `include_shifted_candles: 2`, tells
FreqAI to include the the past 2 candles for each of the features included in the dataset.
In total, the number of features the present user has created is:
length of `include_timeframes` * no. features in `populate_any_indicators()` * length of `include_corr_pairlist` * no. `include_shifted_candles` * length of `indicator_periods_candles`
$3 * 3 * 3 * 2 * 2 = 108$.
!!! Note
Features **must** be defined in `populate_any_indicators()`. Making features in `populate_indicators()`
will fail in live/dry mode. If the user wishes to add generalized features that are not associated with
a specific pair or timeframe, they should use the following structure inside `populate_any_indicators()`
(as exemplified in `freqtrade/templates/FreqaiExampleStrategy.py`:
```python
def populate_any_indicators(self, metadata, pair, df, tf, informative=None, coin="", set_generalized_indicators=False):
...
# Add generalized indicators here (because in live, it will call only this function to populate
# indicators for retraining). Notice how we ensure not to add them multiple times by associating
# these generalized indicators to the basepair/timeframe
if set_generalized_indicators:
df['%-day_of_week'] = (df["date"].dt.dayofweek + 1) / 7
df['%-hour_of_day'] = (df['date'].dt.hour + 1) / 25
# user adds targets here by prepending them with &- (see convention below)
# If user wishes to use multiple targets, a multioutput prediction model
# needs to be used such as templates/CatboostPredictionMultiModel.py
df["&-s_close"] = (
df["close"]
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
.mean()
/ df["close"]
- 1
)
```
(Please see the example script located in `freqtrade/templates/FreqaiExampleStrategy.py` for a full example of `populate_any_indicators()`)
### Deciding the sliding training window and backtesting duration
Users define the backtesting timerange with the typical `--timerange` parameter in the user
configuration file. `train_period_days` is the duration of the sliding training window, while
`backtest_period_days` is the sliding backtesting window, both in number of days (`backtest_period_days` can be
a float to indicate sub daily retraining in live/dry mode). In the present example,
the user is asking FreqAI to use a training period of 30 days and backtest the subsequent 7 days.
This means that if the user sets `--timerange 20210501-20210701`,
FreqAI will train 8 separate models (because the full range comprises 8 weeks),
and then backtest the subsequent week associated with each of the 8 training
data set timerange months. Users can think of this as a "sliding window" which
emulates FreqAI retraining itself once per week in live using the previous
month of data.
In live, the required training data is automatically computed and downloaded. However, in backtesting
the user must manually enter the required number of `startup_candles` in the config. This value
is used to increase the available data to FreqAI and should be sufficient to enable all indicators
to be NaN free at the beginning of the first training timerange. This boils down to identifying the
highest timeframe (`4h` in present example) and the longest indicator period (25 in present example)
and adding this to the `train_period_days`. The units need to be in the base candle time frame:
`startup_candles` = ( 4 hours * 25 max period * 60 minutes/hour + 30 day train_period_days * 1440 minutes per day ) / 5 min (base time frame) = 1488.
!!! Note
In dry/live, this is all precomputed and handled automatically. Thus, `startup_candle` has no influence on dry/live.
!!! Note
Although fractional `backtest_period_days` is allowed, the user should be ware that the `--timerange` is divided by this value to determine the number of models that FreqAI will need to train in order to backtest the full range. For example, if the user wants to set a `--timerange` of 10 days, and asks for a `backtest_period_days` of 0.1, FreqAI will need to train 100 models per pair to complete the full backtest. This is why it is physically impossible to truly backtest FreqAI adaptive training. The best way to fully test a model is to run it dry and let it constantly train. In this case, backtesting would take the exact same amount of time as a dry run.
## Running FreqAI
### Backtesting
The FreqAI backtesting module can be executed with the following command:
```bash
freqtrade backtesting --strategy FreqaiExampleStrategy --config config_freqai.example.json --freqaimodel LightGBMRegressor --timerange 20210501-20210701
```
Backtesting mode requires the user to have the data pre-downloaded (unlike dry/live, where FreqAI automatically downloads the necessary data). The user should be careful to consider that the range of the downloaded data is more than the backtesting range. This is because FreqAI needs data prior to the desired backtesting range in order to train a model to be ready to make predictions on the first candle of the user set backtesting range. More details on how to calculate the data download timerange can be found [here](#deciding-the-sliding-training-window-and-backtesting-duration).
If this command has never been executed with the existing config file, then it will train a new model
for each pair, for each backtesting window within the bigger `--timerange`.
!!! Note "Model reuse"
Once the training is completed, the user can execute this again with the same config file and
FreqAI will find the trained models and load them instead of spending time training. This is useful
if the user wants to tweak (or even hyperopt) buy and sell criteria inside the strategy. IF the user
*wants* to retrain a new model with the same config file, then he/she should simply change the `identifier`.
This way, the user can return to using any model they wish by simply changing the `identifier`.
---
### Building a freqai strategy
The FreqAI strategy requires the user to include the following lines of code in the strategy:
```python
def informative_pairs(self):
whitelist_pairs = self.dp.current_whitelist()
corr_pairs = self.config["freqai"]["feature_parameters"]["include_corr_pairlist"]
informative_pairs = []
for tf in self.config["freqai"]["feature_parameters"]["include_timeframes"]:
for pair in whitelist_pairs:
informative_pairs.append((pair, tf))
for pair in corr_pairs:
if pair in whitelist_pairs:
continue # avoid duplication
informative_pairs.append((pair, tf))
return informative_pairs
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# All indicators must be populated by populate_any_indicators() for live functionality
# to work correctly.
# the model will return all labels created by user in `populate_any_indicators`
# (& appended targets), an indication of whether or not the prediction should be accepted,
# the target mean/std values for each of the labels created by user in
# `populate_any_indicators()` for each training period.
dataframe = self.freqai.start(dataframe, metadata, self)
return dataframe
def populate_any_indicators(
self, pair, df, tf, informative=None, set_generalized_indicators=False
):
"""
Function designed to automatically generate, name and merge features
from user indicated timeframes in the configuration file. User controls the indicators
passed to the training/prediction by prepending indicators with `'%-' + coin `
(see convention below). I.e. user should not prepend any supporting metrics
(e.g. bb_lowerband below) with % unless they explicitly want to pass that metric to the
model.
:param pair: pair to be used as informative
:param df: strategy dataframe which will receive merges from informatives
:param tf: timeframe of the dataframe which will modify the feature names
:param informative: the dataframe associated with the informative pair
:param coin: the name of the coin which will modify the feature names.
"""
coin = pair.split('/')[0]
if informative is None:
informative = self.dp.get_pair_dataframe(pair, tf)
# first loop is automatically duplicating indicators for time periods
for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]:
t = int(t)
informative[f"%-{coin}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t)
informative[f"%-{coin}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t)
informative[f"%-{coin}adx-period_{t}"] = ta.ADX(informative, window=t)
indicators = [col for col in informative if col.startswith("%")]
# This loop duplicates and shifts all indicators to add a sense of recency to data
for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1):
if n == 0:
continue
informative_shift = informative[indicators].shift(n)
informative_shift = informative_shift.add_suffix("_shift-" + str(n))
informative = pd.concat((informative, informative_shift), axis=1)
df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True)
skip_columns = [
(s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"]
]
df = df.drop(columns=skip_columns)
# Add generalized indicators here (because in live, it will call this
# function to populate indicators during training). Notice how we ensure not to
# add them multiple times
if set_generalized_indicators:
# user adds targets here by prepending them with &- (see convention below)
# If user wishes to use multiple targets, a multioutput prediction model
# needs to be used such as templates/CatboostPredictionMultiModel.py
df["&-s_close"] = (
df["close"]
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
.mean()
/ df["close"]
- 1
)
return df
```
Notice how the `populate_any_indicators()` is where the user adds their own features and labels ([more information](#feature-engineering)). See a full example at `templates/FreqaiExampleStrategy.py`.
### Setting classifier targets
FreqAI includes a the `CatboostClassifier` via the flag `--freqaimodel CatboostClassifier`. Typically, the user would set the targets using strings:
```python
df['&s-up_or_down'] = np.where( df["close"].shift(-100) > df["close"], 'up', 'down')
```
### Running the model live
FreqAI can be run dry/live using the following command
```bash
freqtrade trade --strategy FreqaiExampleStrategy --config config_freqai.example.json --freqaimodel LightGBMRegressor
```
By default, FreqAI will not find any existing models and will start by training a new one
given the user configuration settings. Following training, it will use that model to make predictions on incoming candles until a new model is available. New models are typically generated as often as possible, with FreqAI managing an internal queue of the pairs to try and keep all models equally "young." FreqAI will always use the newest trained model to make predictions on incoming live data. If users do not want FreqAI to retrain new models as often as possible, they can set `live_retrain_hours` to tell FreqAI to wait at least that number of hours before retraining a new model. Additionally, users can set `expired_hours` to tell FreqAI to avoid making predictions on models aged over this number of hours.
If the user wishes to start dry/live from a backtested saved model, the user only needs to reuse
the same `identifier` parameter
```json
"freqai": {
"identifier": "example",
"live_retrain_hours": 1
}
```
In this case, although FreqAI will initiate with a
pre-trained model, it will still check to see how much time has elapsed since the model was trained,
and if a full `live_retrain_hours` has elapsed since the end of the loaded model, FreqAI will self retrain.
## Data analysis techniques
### Controlling the model learning process
Model training parameters are unique to the ML library used by the user. FreqAI allows users to set any parameter for any library using the `model_training_parameters` dictionary in the user configuration file. The example configuration files show some of the example parameters associated with `Catboost` and `LightGBM`, but users can add any parameters available in those libraries.
Data split parameters are defined in `data_split_parameters` which can be any parameters associated with `Sklearn`'s `train_test_split()` function. FreqAI includes some additional parameters such `weight_factor` which allows the user to weight more recent data more strongly
than past data via an exponential function:
$$ W_i = \exp(\frac{-i}{\alpha*n}) $$
where $W_i$ is the weight of data point $i$ in a total set of $n$ data points.
![weight-factor](assets/weights_factor.png)
`train_test_split()` has a parameters called `shuffle`, which users also have access to in FreqAI, that allows them to keep the data unshuffled. This is particularly useful to avoid biasing training with temporally auto-correlated data.
Finally, `label_period_candles` defines the offset used for the `labels`. In the present example,
the user is asking for `labels` that are 24 candles in the future.
### Removing outliers with the Dissimilarity Index
The Dissimilarity Index (DI) aims to quantify the uncertainty associated with each
prediction by the model. To do so, FreqAI measures the distance between each training
data point and all other training data points:
$$ d_{ab} = \sqrt{\sum_{j=1}^p(X_{a,j}-X_{b,j})^2} $$
where $d_{ab}$ is the distance between the normalized points $a$ and $b$. $p$
is the number of features i.e. the length of the vector $X$.
The characteristic distance, $\overline{d}$ for a set of training data points is simply the mean
of the average distances:
$$ \overline{d} = \sum_{a=1}^n(\sum_{b=1}^n(d_{ab}/n)/n) $$
$\overline{d}$ quantifies the spread of the training data, which is compared to
the distance between the new prediction feature vectors, $X_k$ and all the training
data:
$$ d_k = \arg \min d_{k,i} $$
which enables the estimation of a Dissimilarity Index:
$$ DI_k = d_k/\overline{d} $$
Equity and crypto markets suffer from a high level of non-patterned noise in the
form of outlier data points. The dissimilarity index allows predictions which
are outliers and not existent in the model feature space, to be thrown out due
to low levels of certainty. Activating the Dissimilarity Index can be achieved with:
```json
"freqai": {
"feature_parameters" : {
"DI_threshold": 1
}
}
```
The user can tweak the DI with `DI_threshold` to increase or decrease the extrapolation of the trained model.
### Reducing data dimensionality with Principal Component Analysis
Users can reduce the dimensionality of their features by activating the `principal_component_analysis`:
```json
"freqai": {
"feature_parameters" : {
"principal_component_analysis": true
}
}
```
Which will perform PCA on the features and reduce the dimensionality of the data so that the explained
variance of the data set is >= 0.999.
### Removing outliers using a Support Vector Machine (SVM)
The user can tell FreqAI to remove outlier data points from the training/test data sets by setting:
```json
"freqai": {
"feature_parameters" : {
"use_SVM_to_remove_outliers": true
}
}
```
FreqAI will train an SVM on the training data (or components if the user activated
`principal_component_analysis`) and remove any data point that it deems to be sitting beyond the feature space.
### Clustering the training data and removing outliers with DBSCAN
The user can configure FreqAI to use DBSCAN to cluster training data and remove outliers from the training data set. The user activates `use_DBSCAN_to_remove_outliers` to cluster training data for identification of outliers. Also used to detect incoming outliers for prediction data points.
```json
"freqai": {
"feature_parameters" : {
"use_DBSCAN_to_remove_outliers": true
}
}
```
### Stratifying the data
The user can stratify the training/testing data using:
```json
"freqai": {
"feature_parameters" : {
"stratify_training_data": 3
}
}
```
which will split the data chronologically so that every Xth data points is a testing data point. In the
present example, the user is asking for every third data point in the dataframe to be used for
testing, the other points are used for training.
## Setting up a follower
The user can define:
```json
"freqai": {
"follow_mode": true,
"identifier": "example"
}
```
to indicate to the bot that it should not train models, but instead should look for models trained
by a leader with the same `identifier`. In this example, the user has a leader bot with the
`identifier: "example"` already running or launching simultaneously as the present follower.
The follower will load models created by the leader and inference them to obtain predictions.
## Purging old model data
FreqAI stores new model files each time it retrains. These files become obsolete as new models
are trained and FreqAI adapts to the new market conditions. Users planning to leave FreqAI running
for extended periods of time with high frequency retraining should set `purge_old_models` in their
config:
```json
"freqai": {
"purge_old_models": true,
}
```
which will automatically purge all models older than the two most recently trained ones.
## Defining model expirations
During dry/live, FreqAI trains each pair sequentially (on separate threads/GPU from the main
Freqtrade bot). This means there is always an age discrepancy between models. If a user is training
on 50 pairs, and each pair requires 5 minutes to train, the oldest model will be over 4 hours old.
This may be undesirable if the characteristic time scale (read trade duration target) for a strategy
is much less than 4 hours. The user can decide to only make trade entries if the model is less than
a certain number of hours in age by setting the `expiration_hours` in the config file:
```json
"freqai": {
"expiration_hours": 0.5,
}
```
In the present example, the user will only allow predictions on models that are less than 1/2 hours
old.
## Choosing the calculation of the `target_roi`
As shown in `templates/FreqaiExampleStrategy.py`, the `target_roi` is based on two metrics computed
by FreqAI: `label_mean` and `label_std`. These are the statistics associated with the labels used
*during the most recent training*.
This allows the model to know what magnitude of a target to be expecting since it is directly stemming from the training data.
By default, FreqAI computes this based on training data and it assumes the labels are Gaussian distributed.
These are big assumptions that the user should consider when creating their labels. If the user wants to consider the population
of *historical predictions* for creating the dynamic target instead of the trained labels, the user
can do so by setting `fit_live_prediction_candles` to the number of historical prediction candles
the user wishes to use to generate target statistics.
```json
"freqai": {
"fit_live_prediction_candles": 300,
}
```
If the user sets this value, FreqAI will initially use the predictions from the training data set
and then subsequently begin introducing real prediction data as it is generated. FreqAI will save
this historical data to be reloaded if the user stops and restarts with the same `identifier`.
## Extra returns per train
Users may find that there are some important metrics that they'd like to return to the strategy at the end of each retrain.
Users can include these metrics by assigning them to `dk.data['extra_returns_per_train']['my_new_value'] = XYZ` inside their custom prediction
model class. FreqAI takes the `my_new_value` assigned in this dictionary and expands it to fit the return dataframe to the strategy.
The user can then use the value in the strategy with `dataframe['my_new_value']`. An example of how this is already used in FreqAI is
the `&*_mean` and `&*_std` values, which indicate the mean and standard deviation of that particular label during the most recent training.
Another example is shown below if the user wants to use live metrics from the trade database.
The user needs to set the standard dictionary in the config so FreqAI can return proper dataframe shapes:
```json
"freqai": {
"extra_returns_per_train": {"total_profit": 4}
}
```
These values will likely be overridden by the user prediction model, but in the case where the user model has yet to set them, or needs
a default initial value - this is the value that will be returned.
## Building an IFreqaiModel
FreqAI has multiple example prediction model based libraries such as `Catboost` regression (`freqai/prediction_models/CatboostRegressor.py`) and `LightGBM` regression.
However, users can customize and create their own prediction models using the `IFreqaiModel` class.
Users are encouraged to inherit `train()` and `predict()` to let them customize various aspects of their training procedures.
## Additional information
### Common pitfalls
FreqAI cannot be combined with `VolumePairlists` (or any pairlist filter that adds and removes pairs dynamically).
This is for performance reasons - FreqAI relies on making quick predictions/retrains. To do this effectively,
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. But this means that if new pairs arrive later in the dry run due
to a volume pairlist, it will not have the data ready. FreqAI does work, however, with the `ShufflePairlist`.
### Feature normalization
The feature set created by the user is automatically normalized to the training data only.
This includes all test data and unseen prediction data (dry/live/backtest).
### File structure
`user_data_dir/models/` contains all the data associated with the trainings and backtests.
This file structure is heavily controlled and read by the `FreqaiDataKitchen()`
and should therefore not be modified.
## Credits
FreqAI was developed by a group of individuals who all contributed specific skillsets to the project.
Conception and software development:
Robert Caulk @robcaulk
Theoretical brainstorming:
Elin Törnquist @thorntwig
Code review, software architecture brainstorming:
@xmatthias
Beta testing and bug reporting:
@bloodhunter4rc, Salah Lamkadem @ikonx, @ken11o2, @longyu, @paranoidandy, @smidelis, @smarm
Juha Nykänen @suikula, Wagner Costa @wagnercosta

View File

@@ -40,13 +40,15 @@ pip install -r requirements-hyperopt.txt
```
usage: freqtrade hyperopt [-h] [-v] [--logfile FILE] [-V] [-c PATH] [-d PATH]
[--userdir PATH] [-s NAME] [--strategy-path PATH]
[-i TIMEFRAME] [--timerange TIMERANGE]
[--recursive-strategy-search] [-i TIMEFRAME]
[--timerange TIMERANGE]
[--data-format-ohlcv {json,jsongz,hdf5}]
[--max-open-trades INT]
[--stake-amount STAKE_AMOUNT] [--fee FLOAT]
[-p PAIRS [PAIRS ...]] [--hyperopt-path PATH]
[--eps] [--dmmp] [--enable-protections]
[--dry-run-wallet DRY_RUN_WALLET] [-e INT]
[--dry-run-wallet DRY_RUN_WALLET]
[--timeframe-detail TIMEFRAME_DETAIL] [-e INT]
[--spaces {all,buy,sell,roi,stoploss,trailing,protection,default} [{all,buy,sell,roi,stoploss,trailing,protection,default} ...]]
[--print-all] [--no-color] [--print-json] [-j JOBS]
[--random-state INT] [--min-trades INT]
@@ -89,6 +91,9 @@ optional arguments:
--dry-run-wallet DRY_RUN_WALLET, --starting-balance DRY_RUN_WALLET
Starting balance, used for backtesting / hyperopt and
dry-runs.
--timeframe-detail TIMEFRAME_DETAIL
Specify detail timeframe for backtesting (`1m`, `5m`,
`30m`, `1h`, `1d`).
-e INT, --epochs INT Specify number of epochs (default: 100).
--spaces {all,buy,sell,roi,stoploss,trailing,protection,default} [{all,buy,sell,roi,stoploss,trailing,protection,default} ...]
Specify which parameters to hyperopt. Space-separated
@@ -116,7 +121,9 @@ optional arguments:
ShortTradeDurHyperOptLoss, OnlyProfitHyperOptLoss,
SharpeHyperOptLoss, SharpeHyperOptLossDaily,
SortinoHyperOptLoss, SortinoHyperOptLossDaily,
CalmarHyperOptLoss, MaxDrawDownHyperOptLoss, ProfitDrawDownHyperOptLoss
CalmarHyperOptLoss, MaxDrawDownHyperOptLoss,
MaxDrawDownRelativeHyperOptLoss,
ProfitDrawDownHyperOptLoss
--disable-param-export
Disable automatic hyperopt parameter export.
--ignore-missing-spaces, --ignore-unparameterized-spaces
@@ -144,7 +151,9 @@ Strategy arguments:
Specify strategy class name which will be used by the
bot.
--strategy-path PATH Specify additional strategy lookup path.
--recursive-strategy-search
Recursively search for a strategy in the strategies
folder.
```
### Hyperopt checklist
@@ -270,6 +279,7 @@ The last one we call `trigger` and use it to decide which buy trigger we want to
!!! Note "Parameter space assignment"
Parameters must either be assigned to a variable named `buy_*` or `sell_*` - or contain `space='buy'` | `space='sell'` to be assigned to a space correctly.
If no parameter is available for a space, you'll receive the error that no space was found when running hyperopt.
Parameters with unclear space (e.g. `adx_period = IntParameter(4, 24, default=14)` - no explicit nor implicit space) will not be detected and will therefore be ignored.
So let's write the buy strategy using these values:
@@ -332,6 +342,7 @@ There are four parameter types each suited for different purposes.
## Optimizing an indicator parameter
Assuming you have a simple strategy in mind - a EMA cross strategy (2 Moving averages crossing) - and you'd like to find the ideal parameters for this strategy.
By default, we assume a stoploss of 5% - and a take-profit (`minimal_roi`) of 10% - which means freqtrade will sell the trade once 10% profit has been reached.
``` python
from pandas import DataFrame
@@ -346,6 +357,9 @@ import freqtrade.vendor.qtpylib.indicators as qtpylib
class MyAwesomeStrategy(IStrategy):
stoploss = -0.05
timeframe = '15m'
minimal_roi = {
"0": 0.10
},
# Define the parameter spaces
buy_ema_short = IntParameter(3, 50, default=5)
buy_ema_long = IntParameter(15, 200, default=50)
@@ -401,7 +415,7 @@ Using `self.buy_ema_short.range` will return a range object containing all entri
In this case (`IntParameter(3, 50, default=5)`), the loop would run for all numbers between 3 and 50 (`[3, 4, 5, ... 49, 50]`).
By using this in a loop, hyperopt will generate 48 new columns (`['buy_ema_3', 'buy_ema_4', ... , 'buy_ema_50']`).
Hyperopt itself will then use the selected value to create the buy and sell signals
Hyperopt itself will then use the selected value to create the buy and sell signals.
While this strategy is most likely too simple to provide consistent profit, it should serve as an example how optimize indicator parameters.
@@ -563,7 +577,8 @@ Currently, the following loss functions are builtin:
* `SharpeHyperOptLossDaily` - optimizes Sharpe Ratio calculated on **daily** trade returns relative to standard deviation.
* `SortinoHyperOptLoss` - optimizes Sortino Ratio calculated on trade returns relative to **downside** standard deviation.
* `SortinoHyperOptLossDaily` - optimizes Sortino Ratio calculated on **daily** trade returns relative to **downside** standard deviation.
* `MaxDrawDownHyperOptLoss` - Optimizes Maximum drawdown.
* `MaxDrawDownHyperOptLoss` - Optimizes Maximum absolute drawdown.
* `MaxDrawDownRelativeHyperOptLoss` - Optimizes both maximum absolute drawdown while also adjusting for maximum relative drawdown.
* `CalmarHyperOptLoss` - Optimizes Calmar Ratio calculated on trade returns relative to max drawdown.
* `ProfitDrawDownHyperOptLoss` - Optimizes by max Profit & min Drawdown objective. `DRAWDOWN_MULT` variable within the hyperoptloss file can be adjusted to be stricter or more flexible on drawdown purposes.
@@ -677,7 +692,7 @@ class MyAwesomeStrategy(IStrategy):
!!! Note
Values in the configuration file will overwrite Parameter-file level parameters - and both will overwrite parameters within the strategy.
The prevalence is therefore: config > parameter file > strategy
The prevalence is therefore: config > parameter file > strategy `*_params` > parameter default
### Understand Hyperopt ROI results
@@ -859,10 +874,28 @@ You can also enable position stacking in the configuration file by explicitly se
As hyperopt consumes a lot of memory (the complete data needs to be in memory once per parallel backtesting process), it's likely that you run into "out of memory" errors.
To combat these, you have multiple options:
* reduce the amount of pairs
* reduce the timerange used (`--timerange <timerange>`)
* reduce the number of parallel processes (`-j <n>`)
* Increase the memory of your machine
* Reduce the amount of pairs.
* Reduce the timerange used (`--timerange <timerange>`).
* Avoid using `--timeframe-detail` (this loads a lot of additional data into memory).
* Reduce the number of parallel processes (`-j <n>`).
* Increase the memory of your machine.
## The objective has been evaluated at this point before.
If you see `The objective has been evaluated at this point before.` - then this is a sign that your space has been exhausted, or is close to that.
Basically all points in your space have been hit (or a local minima has been hit) - and hyperopt does no longer find points in the multi-dimensional space it did not try yet.
Freqtrade tries to counter the "local minima" problem by using new, randomized points in this case.
Example:
``` python
buy_ema_short = IntParameter(5, 20, default=10, space="buy", optimize=True)
# This is the only parameter in the buy space
```
The `buy_ema_short` space has 15 possible values (`5, 6, ... 19, 20`). If you now run hyperopt for the buy space, hyperopt will only have 15 values to try before running out of options.
Your epochs should therefore be aligned to the possible values - or you should be ready to interrupt a run if you norice a lot of `The objective has been evaluated at this point before.` warnings.
## Show details of Hyperopt results

View File

@@ -160,17 +160,17 @@ This filter allows freqtrade to ignore pairs until they have been listed for at
Offsets an incoming pairlist by a given `offset` value.
As an example it can be used in conjunction with `VolumeFilter` to remove the top X volume pairs. Or to split
a larger pairlist on two bot instances.
As an example it can be used in conjunction with `VolumeFilter` to remove the top X volume pairs. Or to split a larger pairlist on two bot instances.
Example to remove the first 10 pairs from the pairlist:
Example to remove the first 10 pairs from the pairlist, and takes the next 20 (taking items 10-30 of the initial list):
```json
"pairlists": [
// ...
{
"method": "OffsetFilter",
"offset": 10
"offset": 10,
"number_assets": 20
}
],
```
@@ -181,7 +181,7 @@ Example to remove the first 10 pairs from the pairlist:
`VolumeFilter`.
!!! Note
An offset larger then the total length of the incoming pairlist will result in an empty pairlist.
An offset larger than the total length of the incoming pairlist will result in an empty pairlist.
#### PerformanceFilter

View File

@@ -48,6 +48,10 @@ If `trade_limit` or more trades resulted in stoploss, trading will stop for `sto
This applies across all pairs, unless `only_per_pair` is set to true, which will then only look at one pair at a time.
Similarly, this protection will by default look at all trades (long and short). For futures bots, setting `only_per_side` will make the bot only consider one side, and will then only lock this one side, allowing for example shorts to continue after a series of long stoplosses.
`required_profit` will determine the required relative profit (or loss) for stoplosses to consider. This should normally not be set and defaults to 0.0 - which means all losing stoplosses will be triggering a block.
The below example stops trading for all pairs for 4 candles after the last trade if the bot hit stoploss 4 times within the last 24 candles.
``` python
@@ -59,7 +63,9 @@ def protections(self):
"lookback_period_candles": 24,
"trade_limit": 4,
"stop_duration_candles": 4,
"only_per_pair": False
"required_profit": 0.0,
"only_per_pair": False,
"only_per_side": False
}
]
```
@@ -93,6 +99,8 @@ def protections(self):
`LowProfitPairs` uses all trades for a pair within `lookback_period` in minutes (or in candles when using `lookback_period_candles`) to determine the overall profit ratio.
If that ratio is below `required_profit`, that pair will be locked for `stop_duration` in minutes (or in candles when using `stop_duration_candles`).
For futures bots, setting `only_per_side` will make the bot only consider one side, and will then only lock this one side, allowing for example shorts to continue after a series of long losses.
The below example will stop trading a pair for 60 minutes if the pair does not have a required profit of 2% (and a minimum of 2 trades) within the last 6 candles.
``` python
@@ -104,7 +112,8 @@ def protections(self):
"lookback_period_candles": 6,
"trade_limit": 2,
"stop_duration": 60,
"required_profit": 0.02
"required_profit": 0.02,
"only_per_pair": False,
}
]
```

View File

@@ -22,10 +22,6 @@ Freqtrade is a free and open source crypto trading bot written in Python. It is
![freqtrade screenshot](assets/freqtrade-screenshot.png)
## Sponsored promotion
[![tokenbot-promo](assets/TokenBot-Freqtrade-banner.png)](https://tokenbot.com/?utm_source=github&utm_medium=freqtrade&utm_campaign=algodevs)
## Features
- Develop your Strategy: Write your strategy in python, using [pandas](https://pandas.pydata.org/). Example strategies to inspire you are available in the [strategy repository](https://github.com/freqtrade/freqtrade-strategies).
@@ -51,7 +47,7 @@ Please read the [exchange specific notes](exchanges.md) to learn about eventual,
- [X] [OKX](https://okx.com/) (Former OKEX)
- [ ] [potentially many others through <img alt="ccxt" width="30px" src="assets/ccxt-logo.svg" />](https://github.com/ccxt/ccxt/). _(We cannot guarantee they will work)_
### Experimentally, freqtrade also supports futures on the following exchanges:
### Supported Futures Exchanges (experimental)
- [X] [Binance](https://www.binance.com/)
- [X] [Gate.io](https://www.gate.io/ref/6266643)

View File

@@ -326,6 +326,16 @@ python3 -m pip install --upgrade pip
python3 -m pip install -e .
```
Patch conda libta-lib (Linux only)
```bash
# Ensure that the environment is active!
conda activate freqtrade-conda
cd build_helpers
bash install_ta-lib.sh ${CONDA_PREFIX} nosudo
```
### Congratulations
[You are ready](#you-are-ready), and run the bot

View File

@@ -64,7 +64,10 @@ You will also have to pick a "margin mode" (explanation below) - with freqtrade
### Margin mode
The possible values are: `isolated`, or `cross`(*currently unavailable*)
On top of `trading_mode` - you will also have to configure your `margin_mode`.
While freqtrade currently only supports one margin mode, this will change, and by configuring it now you're all set for future updates.
The possible values are: `isolated`, or `cross`(*currently unavailable*).
#### Isolated margin mode
@@ -82,6 +85,16 @@ One account is used to share collateral between markets (trading pairs). Margin
"margin_mode": "cross"
```
## Set leverage to use
Different strategies and risk profiles will require different levels of leverage.
While you could configure one static leverage value - freqtrade offers you the flexibility to adjust this via [strategy leverage callback](strategy-callbacks.md#leverage-callback) - which allows you to use different leverages by pair, or based on some other factor benefitting your strategy result.
If not implemented, leverage defaults to 1x (no leverage).
!!! Warning
Higher leverage also equals higher risk - be sure you fully understand the implications of using leverage!
## Understand `liquidation_buffer`
*Defaults to `0.05`*
@@ -101,6 +114,13 @@ Possible values are any floats between 0.0 and 0.99
!!! Danger "A `liquidation_buffer` of 0.0, or a low `liquidation_buffer` is likely to result in liquidations, and liquidation fees"
Currently Freqtrade is able to calculate liquidation prices, but does not calculate liquidation fees. Setting your `liquidation_buffer` to 0.0, or using a low `liquidation_buffer` could result in your positions being liquidated. Freqtrade does not track liquidation fees, so liquidations will result in inaccurate profit/loss results for your bot. If you use a low `liquidation_buffer`, it is recommended to use `stoploss_on_exchange` if your exchange supports this.
## Unavailable funding rates
For futures data, exchanges commonly provide the futures candles, the marks, and the funding rates. However, it is common that whilst candles and marks might be available, the funding rates are not. This can affect backtesting timeranges, i.e. you may only be able to test recent timeranges and not earlier, experiencing the `No data found. Terminating.` error. To get around this, add the `futures_funding_rate` config option as listed in [configuration.md](configuration.md), and it is recommended that you set this to `0`, unless you know a given specific funding rate for your pair, exchange and timerange. Setting this to anything other than `0` can have drastic effects on your profit calculations within strategy, e.g. within the `custom_exit`, `custom_stoploss`, etc functions.
!!! Warning "This will mean your backtests are inaccurate."
This will not overwrite funding rates that are available from the exchange, but bear in mind that setting a false funding rate will mean backtesting results will be inaccurate for historical timeranges where funding rates are not available.
### Developer
#### Margin mode

View File

@@ -1,5 +1,6 @@
mkdocs==1.3.0
mkdocs-material==8.2.10
mdx_truly_sane_lists==1.2
pymdown-extensions==9.4
jinja2==3.1.1
markdown==3.3.7
mkdocs==1.3.1
mkdocs-material==8.4.0
mdx_truly_sane_lists==1.3
pymdown-extensions==9.5
jinja2==3.1.2

View File

@@ -89,11 +89,12 @@ WHERE id=31;
If you'd still like to remove a trade from the database directly, you can use the below query.
```sql
DELETE FROM trades WHERE id = <tradeid>;
```
!!! Danger
Some systems (Ubuntu) disable foreign keys in their sqlite3 packaging. When using sqlite - please ensure that foreign keys are on by running `PRAGMA foreign_keys = ON` before the above query.
```sql
DELETE FROM trades WHERE id = <tradeid>;
DELETE FROM trades WHERE id = 31;
```
@@ -102,13 +103,20 @@ DELETE FROM trades WHERE id = 31;
## Use a different database system
Freqtrade is using SQLAlchemy, which supports multiple different database systems. As such, a multitude of database systems should be supported.
Freqtrade does not depend or install any additional database driver. Please refer to the [SQLAlchemy docs](https://docs.sqlalchemy.org/en/14/core/engines.html#database-urls) on installation instructions for the respective database systems.
The following systems have been tested and are known to work with freqtrade:
* sqlite (default)
* PostgreSQL)
* MariaDB
!!! Warning
By using one of the below database systems, you acknowledge that you know how to manage such a system. Freqtrade will not provide any support with setup or maintenance (or backups) of the below database systems.
By using one of the below database systems, you acknowledge that you know how to manage such a system. The freqtrade team will not provide any support with setup or maintenance (or backups) of the below database systems.
### PostgreSQL
Freqtrade supports PostgreSQL by using SQLAlchemy, which supports multiple different database systems.
Installation:
`pip install psycopg2-binary`

View File

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

View File

@@ -224,3 +224,5 @@ for val in self.buy_ema_short.range:
# Append columns to existing dataframe
merged_frame = 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

@@ -17,6 +17,7 @@ Currently available callbacks:
* [`confirm_trade_entry()`](#trade-entry-buy-order-confirmation)
* [`confirm_trade_exit()`](#trade-exit-sell-order-confirmation)
* [`adjust_trade_position()`](#adjust-trade-position)
* [`adjust_entry_price()`](#adjust-entry-price)
* [`leverage()`](#leverage-callback)
!!! Tip "Callback calling sequence"
@@ -45,6 +46,9 @@ class AwesomeStrategy(IStrategy):
self.cust_remote_data = requests.get('https://some_remote_source.example.com')
```
During hyperopt, this runs only once at startup.
## Bot loop start
A simple callback which is called once at the start of every bot throttling iteration (roughly every 5 seconds, unless configured differently).
@@ -78,8 +82,9 @@ Called before entering a trade, makes it possible to manage your position size w
```python
class AwesomeStrategy(IStrategy):
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
proposed_stake: float, min_stake: float, max_stake: float,
entry_tag: Optional[str], side: str, **kwargs) -> float:
proposed_stake: float, min_stake: Optional[float], max_stake: float,
leverage: float, entry_tag: Optional[str], side: str,
**kwargs) -> float:
dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
current_candle = dataframe.iloc[-1].squeeze()
@@ -545,10 +550,12 @@ class AwesomeStrategy(IStrategy):
:param pair: Pair that's about to be bought/shorted.
:param order_type: Order type (as configured in order_types). usually limit or market.
:param amount: Amount in target (quote) currency that's going to be traded.
:param amount: Amount in target (base) currency that's going to be traded.
:param rate: Rate that's going to be used when using limit orders
or current rate for market orders.
:param time_in_force: Time in force. Defaults to GTC (Good-til-cancelled).
:param current_time: datetime object, containing the current datetime
:param entry_tag: Optional entry_tag (buy_tag) if provided with the buy signal.
:param side: 'long' or 'short' - indicating the direction of the proposed trade
:param **kwargs: Ensure to keep this here so updates to this won't break your strategy.
:return bool: When True is returned, then the buy-order is placed on the exchange.
@@ -562,6 +569,14 @@ class AwesomeStrategy(IStrategy):
`confirm_trade_exit()` can be used to abort a trade exit (sell) at the latest second (maybe because the price is not what we expect).
`confirm_trade_exit()` may be called multiple times within one iteration for the same trade if different exit-reasons apply.
The exit-reasons (if applicable) will be in the following sequence:
* `exit_signal` / `custom_exit`
* `stop_loss`
* `roi`
* `trailing_stop_loss`
``` python
from freqtrade.persistence import Trade
@@ -574,7 +589,7 @@ class AwesomeStrategy(IStrategy):
rate: float, time_in_force: str, exit_reason: str,
current_time: datetime, **kwargs) -> bool:
"""
Called right before placing a regular sell order.
Called right before placing a regular exit order.
Timing for this function is critical, so avoid doing heavy computations or
network requests in this method.
@@ -582,17 +597,19 @@ class AwesomeStrategy(IStrategy):
When not implemented by a strategy, returns True (always confirming).
:param pair: Pair that's about to be sold.
:param pair: Pair for trade that's about to be exited.
:param trade: trade object.
:param order_type: Order type (as configured in order_types). usually limit or market.
:param amount: Amount in quote currency.
:param amount: Amount in base currency.
:param rate: Rate that's going to be used when using limit orders
or current rate for market orders.
:param time_in_force: Time in force. Defaults to GTC (Good-til-cancelled).
:param exit_reason: Exit reason.
Can be any of ['roi', 'stop_loss', 'stoploss_on_exchange', 'trailing_stop_loss',
'exit_signal', 'force_exit', 'emergency_exit']
:param current_time: datetime object, containing the current datetime
:param **kwargs: Ensure to keep this here so updates to this won't break your strategy.
:return bool: When True is returned, then the exit-order is placed on the exchange.
:return bool: When True, then the exit-order is placed on the exchange.
False aborts the process
"""
if exit_reason == 'force_exit' and trade.calc_profit_ratio(rate) < 0:
@@ -604,11 +621,15 @@ class AwesomeStrategy(IStrategy):
```
!!! Warning
`confirm_trade_exit()` can prevent stoploss exits, causing significant losses as this would ignore stoploss exits.
`confirm_trade_exit()` will not be called for Liquidations - as liquidations are forced by the exchange, and therefore cannot be rejected.
## Adjust trade position
The `position_adjustment_enable` strategy property enables the usage of `adjust_trade_position()` callback in the strategy.
For performance reasons, it's disabled by default and freqtrade will show a warning message on startup if enabled.
`adjust_trade_position()` can be used to perform additional orders, for example to manage risk with DCA (Dollar Cost Averaging).
`adjust_trade_position()` can be used to perform additional orders, for example to manage risk with DCA (Dollar Cost Averaging) or to increase or decrease positions.
`max_entry_position_adjustment` property is used to limit the number of additional buys per trade (on top of the first buy) that the bot can execute. By default, the value is -1 which means the bot have no limit on number of adjustment buys.
@@ -616,10 +637,13 @@ The strategy is expected to return a stake_amount (in stake currency) between `m
If there are not enough funds in the wallet (the return value is above `max_stake`) then the signal will be ignored.
Additional orders also result in additional fees and those orders don't count towards `max_open_trades`.
This callback is **not** called when there is an open order (either buy or sell) waiting for execution, or when you have reached the maximum amount of extra buys that you have set on `max_entry_position_adjustment`.
This callback is **not** called when there is an open order (either buy or sell) waiting for execution.
`adjust_trade_position()` is called very frequently for the duration of a trade, so you must keep your implementation as performant as possible.
Position adjustments will always be applied in the direction of the trade, so a positive value will always increase your position, no matter if it's a long or short trade. Modifications to leverage are not possible.
Additional Buys are ignored once you have reached the maximum amount of extra buys that you have set on `max_entry_position_adjustment`, but the callback is called anyway looking for partial exits.
Position adjustments will always be applied in the direction of the trade, so a positive value will always increase your position (negative values will decrease your position), no matter if it's a long or short trade. Modifications to leverage are not possible.
!!! Note "About stake size"
Using fixed stake size means it will be the amount used for the first order, just like without position adjustment.
@@ -628,12 +652,12 @@ Position adjustments will always be applied in the direction of the trade, so a
!!! Warning
Stoploss is still calculated from the initial opening price, not averaged price.
Regular stoploss rules still apply (cannot move down).
!!! Warning "/stopbuy"
While `/stopbuy` command stops the bot from entering new trades, the position adjustment feature will continue buying new orders on existing trades.
!!! Warning "Backtesting"
During backtesting this callback is called for each candle in `timeframe` or `timeframe_detail`, so performance will be affected.
During backtesting this callback is called for each candle in `timeframe` or `timeframe_detail`, so run-time performance will be affected.
``` python
from freqtrade.persistence import Trade
@@ -655,30 +679,50 @@ class DigDeeperStrategy(IStrategy):
# This is called when placing the initial order (opening trade)
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
proposed_stake: float, min_stake: float, max_stake: float,
entry_tag: Optional[str], side: str, **kwargs) -> float:
proposed_stake: float, min_stake: Optional[float], max_stake: float,
leverage: float, entry_tag: Optional[str], side: str,
**kwargs) -> float:
# We need to leave most of the funds for possible further DCA orders
# This also applies to fixed stakes
return proposed_stake / self.max_dca_multiplier
def adjust_trade_position(self, trade: Trade, current_time: datetime,
current_rate: float, current_profit: float, min_stake: float,
max_stake: float, **kwargs):
current_rate: float, current_profit: float,
min_stake: Optional[float], max_stake: float,
current_entry_rate: float, current_exit_rate: float,
current_entry_profit: float, current_exit_profit: float,
**kwargs) -> Optional[float]:
"""
Custom trade adjustment logic, returning the stake amount that a trade should be increased.
This means extra buy orders with additional fees.
Custom trade adjustment logic, returning the stake amount that a trade should be
increased or decreased.
This means extra buy or sell orders with additional fees.
Only called when `position_adjustment_enable` is set to True.
For full documentation please go to https://www.freqtrade.io/en/latest/strategy-advanced/
When not implemented by a strategy, returns None
:param trade: trade object.
:param current_time: datetime object, containing the current datetime
:param current_rate: Current buy rate.
:param current_profit: Current profit (as ratio), calculated based on current_rate.
:param min_stake: Minimal stake size allowed by exchange.
:param max_stake: Balance available for trading.
:param min_stake: Minimal stake size allowed by exchange (for both entries and exits)
:param max_stake: Maximum stake allowed (either through balance, or by exchange limits).
:param current_entry_rate: Current rate using entry pricing.
:param current_exit_rate: Current rate using exit pricing.
:param current_entry_profit: Current profit using entry pricing.
:param current_exit_profit: Current profit using exit pricing.
:param **kwargs: Ensure to keep this here so updates to this won't break your strategy.
:return float: Stake amount to adjust your trade
:return float: Stake amount to adjust your trade,
Positive values to increase position, Negative values to decrease position.
Return None for no action.
"""
if current_profit > 0.05 and trade.nr_of_successful_exits == 0:
# Take half of the profit at +5%
return -(trade.stake_amount / 2)
if current_profit > -0.05:
return None
@@ -713,6 +757,88 @@ class DigDeeperStrategy(IStrategy):
```
### Position adjust calculations
* Entry rates are calculated using weighted averages.
* Exits will not influence the average entry rate.
* Partial exit relative profit is relative to the average entry price at this point.
* Final exit relative profit is calculated based on the total invested capital. (See example below)
??? example "Calculation example"
*This example assumes 0 fees for simplicity, and a long position on an imaginary coin.*
* Buy 100@8\$
* Buy 100@9\$ -> Avg price: 8.5\$
* Sell 100@10\$ -> Avg price: 8.5\$, realized profit 150\$, 17.65%
* Buy 150@11\$ -> Avg price: 10\$, realized profit 150\$, 17.65%
* Sell 100@12\$ -> Avg price: 10\$, total realized profit 350\$, 20%
* Sell 150@14\$ -> Avg price: 10\$, total realized profit 950\$, 40%
The total profit for this trade was 950$ on a 3350$ investment (`100@8$ + 100@9$ + 150@11$`). As such - the final relative profit is 28.35% (`950 / 3350`).
## Adjust Entry Price
The `adjust_entry_price()` callback may be used by strategy developer to refresh/replace limit orders upon arrival of new candles.
Be aware that `custom_entry_price()` is still the one dictating initial entry limit order price target at the time of entry trigger.
Orders can be cancelled out of this callback by returning `None`.
Returning `current_order_rate` will keep the order on the exchange "as is".
Returning any other price will cancel the existing order, and replace it with a new order.
The trade open-date (`trade.open_date_utc`) will remain at the time of the very first order placed.
Please make sure to be aware of this - and eventually adjust your logic in other callbacks to account for this, and use the date of the first filled order instead.
!!! Warning "Regular timeout"
Entry `unfilledtimeout` mechanism (as well as `check_entry_timeout()`) takes precedence over this.
Entry Orders that are cancelled via the above methods will not have this callback called. Be sure to update timeout values to match your expectations.
```python
from freqtrade.persistence import Trade
from datetime import timedelta
class AwesomeStrategy(IStrategy):
# ... populate_* methods
def adjust_entry_price(self, trade: Trade, order: Optional[Order], pair: str,
current_time: datetime, proposed_rate: float, current_order_rate: float,
entry_tag: Optional[str], side: str, **kwargs) -> float:
"""
Entry price re-adjustment logic, returning the user desired limit price.
This only executes when a order was already placed, still open (unfilled fully or partially)
and not timed out on subsequent candles after entry trigger.
When not implemented by a strategy, returns current_order_rate as default.
If current_order_rate is returned then the existing order is maintained.
If None is returned then order gets canceled but not replaced by a new one.
:param pair: Pair that's currently analyzed
:param trade: Trade object.
:param order: Order object
:param current_time: datetime object, containing the current datetime
:param proposed_rate: Rate, calculated based on pricing settings in entry_pricing.
:param current_order_rate: Rate of the existing order in place.
:param entry_tag: Optional entry_tag (buy_tag) if provided with the buy signal.
:param side: 'long' or 'short' - indicating the direction of the proposed trade
:param **kwargs: Ensure to keep this here so updates to this won't break your strategy.
:return float: New entry price value if provided
"""
# Limit orders to use and follow SMA200 as price target for the first 10 minutes since entry trigger for BTC/USDT pair.
if pair == 'BTC/USDT' and entry_tag == 'long_sma200' and side == 'long' and (current_time - timedelta(minutes=10) > trade.open_date_utc:
# just cancel the order if it has been filled more than half of the amount
if order.filled > order.remaining:
return None
else:
dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
current_candle = dataframe.iloc[-1].squeeze()
# desired price
return current_candle['sma_200']
# default: maintain existing order
return current_order_rate
```
## Leverage Callback
When trading in markets that allow leverage, this method must return the desired Leverage (Defaults to 1 -> No leverage).
@@ -724,19 +850,23 @@ For markets / exchanges that don't support leverage, this method is ignored.
``` python
class AwesomeStrategy(IStrategy):
def leverage(self, pair: str, current_time: 'datetime', current_rate: float,
proposed_leverage: float, max_leverage: float, side: str,
def leverage(self, pair: str, current_time: datetime, current_rate: float,
proposed_leverage: float, max_leverage: float, entry_tag: Optional[str], side: str,
**kwargs) -> float:
"""
Customize leverage for each new trade.
Customize leverage for each new trade. This method is only called in futures mode.
:param pair: Pair that's currently analyzed
:param current_time: datetime object, containing the current datetime
:param current_rate: Rate, calculated based on pricing settings in exit_pricing.
:param proposed_leverage: A leverage proposed by the bot.
:param max_leverage: Max leverage allowed on this pair
:param entry_tag: Optional entry_tag (buy_tag) if provided with the buy signal.
:param side: 'long' or 'short' - indicating the direction of the proposed trade
:return: A leverage amount, which is between 1.0 and max_leverage.
"""
return 1.0
```
All profit calculations include leverage. Stoploss / ROI also include leverage in their calculation.
Defining a stoploss of 10% at 10x leverage would trigger the stoploss with a 1% move to the downside.

View File

@@ -617,7 +617,6 @@ Please always check the mode of operation to select the correct method to get da
### *available_pairs*
``` python
if self.dp:
for pair, timeframe in self.dp.available_pairs:
print(f"available {pair}, {timeframe}")
```
@@ -630,7 +629,7 @@ The strategy might look something like this:
*Scan through the top 10 pairs by volume using the `VolumePairList` every 5 minutes and use a 14 day RSI to buy and sell.*
Due to the limited available data, it's very difficult to resample `5m` candles into daily candles for use in a 14 day RSI. Most exchanges limit us to just 500 candles which effectively gives us around 1.74 daily candles. We need 14 days at least!
Due to the limited available data, it's very difficult to resample `5m` candles into daily candles for use in a 14 day RSI. Most exchanges limit us to just 500-1000 candles which effectively gives us around 1.74 daily candles. We need 14 days at least!
Since we can't resample the data we will have to use an informative pair; and since the whitelist will be dynamic we don't know which pair(s) to use.
@@ -646,11 +645,13 @@ This is where calling `self.dp.current_whitelist()` comes in handy.
return informative_pairs
```
??? Note "Plotting with current_whitelist"
Current whitelist is not supported for `plot-dataframe`, as this command is usually used by providing an explicit pairlist - and would therefore make the return values of this method misleading.
### *get_pair_dataframe(pair, timeframe)*
``` python
# fetch live / historical candle (OHLCV) data for the first informative pair
if self.dp:
inf_pair, inf_timeframe = self.informative_pairs()[0]
informative = self.dp.get_pair_dataframe(pair=inf_pair,
timeframe=inf_timeframe)
@@ -668,7 +669,6 @@ It can also be used in specific callbacks to get the signal that caused the acti
``` python
# fetch current dataframe
if self.dp:
if self.dp.runmode.value in ('live', 'dry_run'):
dataframe, last_updated = self.dp.get_analyzed_dataframe(pair=metadata['pair'],
timeframe=self.timeframe)
@@ -681,7 +681,6 @@ if self.dp:
### *orderbook(pair, maximum)*
``` python
if self.dp:
if self.dp.runmode.value in ('live', 'dry_run'):
ob = self.dp.orderbook(metadata['pair'], 1)
dataframe['best_bid'] = ob['bids'][0][0]
@@ -714,7 +713,6 @@ Therefore, using `ob['bids'][0][0]` as demonstrated above will result in using t
### *ticker(pair)*
``` python
if self.dp:
if self.dp.runmode.value in ('live', 'dry_run'):
ticker = self.dp.ticker(metadata['pair'])
dataframe['last_price'] = ticker['last']
@@ -729,7 +727,24 @@ if self.dp:
data returned from the exchange and add appropriate error handling / defaults.
!!! Warning "Warning about backtesting"
This method will always return up-to-date values - so usage during backtesting / hyperopt will lead to wrong results.
This method will always return up-to-date values - so usage during backtesting / hyperopt without runmode checks will lead to wrong results.
### Send Notification
The dataprovider `.send_msg()` function allows you to send custom notifications from your strategy.
Identical notifications will only be sent once per candle, unless the 2nd argument (`always_send`) is set to True.
``` python
self.dp.send_msg(f"{metadata['pair']} just got hot!")
# Force send this notification, avoid caching (Please read warning below!)
self.dp.send_msg(f"{metadata['pair']} just got hot!", always_send=True)
```
Notifications will only be sent in trading modes (Live/Dry-run) - so this method can be called without conditions for backtesting.
!!! Warning "Spamming"
You can spam yourself pretty good by setting `always_send=True` in this method. Use this with great care and only in conditions you know will not happen throughout a candle to avoid a message every 5 seconds.
### Complete Data-provider sample

View File

@@ -14,7 +14,7 @@ from freqtrade.configuration import Configuration
# Initialize empty configuration object
config = Configuration.from_files([])
# Optionally, use existing configuration file
# Optionally (recommended), use existing configuration file
# config = Configuration.from_files(["config.json"])
# Define some constants
@@ -22,7 +22,7 @@ config["timeframe"] = "5m"
# Name of the strategy class
config["strategy"] = "SampleStrategy"
# Location of the data
data_location = Path(config['user_data_dir'], 'data', 'binance')
data_location = config['datadir']
# Pair to analyze - Only use one pair here
pair = "BTC/USDT"
```
@@ -31,11 +31,13 @@ pair = "BTC/USDT"
```python
# Load data using values set above
from freqtrade.data.history import load_pair_history
from freqtrade.enums import CandleType
candles = load_pair_history(datadir=data_location,
timeframe=config["timeframe"],
pair=pair,
data_format = "hdf5",
candle_type=CandleType.SPOT,
)
# Confirm success

View File

@@ -18,7 +18,7 @@ Note : `forcesell`, `forcebuy`, `emergencysell` are changed to `force_exit`, `fo
* [`check_buy_timeout()` -> `check_entry_timeout()`](#custom_entry_timeout)
* [`check_sell_timeout()` -> `check_exit_timeout()`](#custom_entry_timeout)
* New `side` argument to callbacks without trade object
* [`custom_stake_amount`](#custom-stake-amount)
* [`custom_stake_amount`](#custom_stake_amount)
* [`confirm_trade_entry`](#confirm_trade_entry)
* [`custom_entry_price`](#custom_entry_price)
* [Changed argument name in `confirm_trade_exit`](#confirm_trade_exit)
@@ -192,14 +192,14 @@ class AwesomeStrategy(IStrategy):
return False
```
### Custom-stake-amount
### `custom_stake_amount`
New string argument `side` - which can be either `"long"` or `"short"`.
``` python hl_lines="4"
class AwesomeStrategy(IStrategy):
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
proposed_stake: float, min_stake: float, max_stake: float,
proposed_stake: float, min_stake: Optional[float], max_stake: float,
entry_tag: Optional[str], **kwargs) -> float:
# ...
return proposed_stake
@@ -208,7 +208,7 @@ class AwesomeStrategy(IStrategy):
``` python hl_lines="4"
class AwesomeStrategy(IStrategy):
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
proposed_stake: float, min_stake: float, max_stake: float,
proposed_stake: float, min_stake: Optional[float], max_stake: float,
entry_tag: Optional[str], side: str, **kwargs) -> float:
# ...
return proposed_stake

View File

@@ -97,7 +97,9 @@ Example configuration showing the different settings:
"entry_fill": "off",
"exit_fill": "off",
"protection_trigger": "off",
"protection_trigger_global": "on"
"protection_trigger_global": "on",
"strategy_msg": "off",
"show_candle": "off"
},
"reload": true,
"balance_dust_level": 0.01
@@ -108,7 +110,8 @@ Example configuration showing the different settings:
`exit` notifications are sent when the order is placed, while `exit_fill` notifications are sent when the order is filled on the exchange.
`*_fill` notifications are off by default and must be explicitly enabled.
`protection_trigger` notifications are sent when a protection triggers and `protection_trigger_global` notifications trigger when global protections are triggered.
`strategy_msg` - Receive notifications from the strategy, sent via `self.dp.send_msg()` from the strategy [more details](strategy-customization.md#send-notification).
`show_candle` - show candle values as part of entry/exit messages. Only possible values are `"ohlc"` or `"off"`.
`balance_dust_level` will define what the `/balance` command takes as "dust" - Currencies with a balance below this will be shown.
`reload` allows you to disable reload-buttons on selected messages.
@@ -171,8 +174,8 @@ official commands. You can ask at any moment for help with `/help`.
| `/locks` | Show currently locked pairs.
| `/unlock <pair or lock_id>` | Remove the lock for this pair (or for this lock id).
| `/profit [<n>]` | Display a summary of your profit/loss from close trades and some stats about your performance, over the last n days (all trades by default)
| `/forceexit <trade_id>` | Instantly exits the given trade (Ignoring `minimum_roi`).
| `/forceexit all` | Instantly exits all open trades (Ignoring `minimum_roi`).
| `/forceexit <trade_id> | /fx <tradeid>` | Instantly exits the given trade (Ignoring `minimum_roi`).
| `/forceexit all | /fx all` | Instantly exits all open trades (Ignoring `minimum_roi`).
| `/fx` | alias for `/forceexit`
| `/forcelong <pair> [rate]` | Instantly buys the given pair. Rate is optional and only applies to limit orders. (`force_entry_enable` must be set to True)
| `/forceshort <pair> [rate]` | Instantly shorts the given pair. Rate is optional and only applies to limit orders. This will only work on non-spot markets. (`force_entry_enable` must be set to True)
@@ -184,7 +187,7 @@ official commands. You can ask at any moment for help with `/help`.
| `/stats` | Shows Wins / losses by Exit reason as well as Avg. holding durations for buys and sells
| `/exits` | Shows Wins / losses by Exit reason as well as Avg. holding durations for buys and sells
| `/entries` | Shows Wins / losses by Exit reason as well as Avg. holding durations for buys and sells
| `/whitelist` | Show the current whitelist
| `/whitelist [sorted] [baseonly]` | Show the current whitelist. Optionally display in alphabetical order and/or with just the base currency of each pairing.
| `/blacklist [pair]` | Show the current blacklist, or adds a pair to the blacklist.
| `/edge` | Show validated pairs by Edge if it is enabled.
| `/help` | Show help message
@@ -270,10 +273,15 @@ Return a summary of your profit/loss and performance.
> **Latest Trade opened:** `2 minutes ago`
> **Avg. Duration:** `2:33:45`
> **Best Performing:** `PAY/BTC: 50.23%`
> **Trading volume:** `0.5 BTC`
> **Profit factor:** `1.04`
> **Max Drawdown:** `9.23% (0.01255 BTC)`
The relative profit of `1.2%` is the average profit per trade.
The relative profit of `15.2 Σ%` is be based on the starting capital - so in this case, the starting capital was `0.00485701 * 1.152 = 0.00738 BTC`.
Starting capital is either taken from the `available_capital` setting, or calculated by using current wallet size - profits.
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)`.
### /forceexit <trade_id>
@@ -281,6 +289,7 @@ Starting capital is either taken from the `available_capital` setting, or calcul
!!! Tip
You can get a list of all open trades by calling `/forceexit` without parameter, which will show a list of buttons to simply exit a trade.
This command has an alias in `/fx` - which has the same capabilities, but is faster to type in "emergency" situations.
### /forcelong <pair> [rate] | /forceshort <pair> [rate]
@@ -328,11 +337,11 @@ Per default `/daily` will return the 7 last days. The example below if for `/dai
> **Daily Profit over the last 3 days:**
```
Day Profit BTC Profit USD
---------- -------------- ------------
2018-01-03 0.00224175 BTC 29,142 USD
2018-01-02 0.00033131 BTC 4,307 USD
2018-01-01 0.00269130 BTC 34.986 USD
Day (count) USDT USD Profit %
-------------- ------------ ---------- ----------
2022-06-11 (1) -0.746 USDT -0.75 USD -0.08%
2022-06-10 (0) 0 USDT 0.00 USD 0.00%
2022-06-09 (5) 20 USDT 20.10 USD 5.00%
```
### /weekly <n>
@@ -342,11 +351,11 @@ from Monday. The example below if for `/weekly 3`:
> **Weekly Profit over the last 3 weeks (starting from Monday):**
```
Monday Profit BTC Profit USD
---------- -------------- ------------
2018-01-03 0.00224175 BTC 29,142 USD
2017-12-27 0.00033131 BTC 4,307 USD
2017-12-20 0.00269130 BTC 34.986 USD
Monday (count) Profit BTC Profit USD Profit %
------------- -------------- ------------ ----------
2018-01-03 (5) 0.00224175 BTC 29,142 USD 4.98%
2017-12-27 (1) 0.00033131 BTC 4,307 USD 0.00%
2017-12-20 (4) 0.00269130 BTC 34.986 USD 5.12%
```
### /monthly <n>
@@ -356,11 +365,11 @@ if for `/monthly 3`:
> **Monthly Profit over the last 3 months:**
```
Month Profit BTC Profit USD
---------- -------------- ------------
2018-01 0.00224175 BTC 29,142 USD
2017-12 0.00033131 BTC 4,307 USD
2017-11 0.00269130 BTC 34.986 USD
Month (count) Profit BTC Profit USD Profit %
------------- -------------- ------------ ----------
2018-01 (20) 0.00224175 BTC 29,142 USD 4.98%
2017-12 (5) 0.00033131 BTC 4,307 USD 0.00%
2017-11 (10) 0.00269130 BTC 34.986 USD 5.10%
```
### /whitelist

View File

@@ -32,4 +32,8 @@ Please ensure that you're also updating dependencies - otherwise things might br
``` bash
git pull
pip install -U -r requirements.txt
pip install -e .
# Ensure freqUI is at the latest version
freqtrade install-ui
```

View File

@@ -119,6 +119,7 @@ This subcommand is useful for finding problems in your environment with loading
usage: freqtrade list-strategies [-h] [-v] [--logfile FILE] [-V] [-c PATH]
[-d PATH] [--userdir PATH]
[--strategy-path PATH] [-1] [--no-color]
[--recursive-strategy-search]
optional arguments:
-h, --help show this help message and exit
@@ -126,6 +127,9 @@ optional arguments:
-1, --one-column Print output in one column.
--no-color Disable colorization of hyperopt results. May be
useful if you are redirecting output to a file.
--recursive-strategy-search
Recursively search for a strategy in the strategies
folder.
Common arguments:
-v, --verbose Verbose mode (-vv for more, -vvv to get all messages).
@@ -134,9 +138,10 @@ Common arguments:
details.
-V, --version show program's version number and exit
-c PATH, --config PATH
Specify configuration file (default: `config.json`).
Multiple --config options may be used. Can be set to
`-` to read config from stdin.
Specify configuration file (default:
`userdir/config.json` or `config.json` whichever
exists). Multiple --config options may be used. Can be
set to `-` to read config from stdin.
-d PATH, --datadir PATH
Path to directory with historical backtesting data.
--userdir PATH, --user-data-dir PATH
@@ -549,6 +554,27 @@ Show whitelist when using a [dynamic pairlist](plugins.md#pairlists).
freqtrade test-pairlist --config config.json --quote USDT BTC
```
## Convert database
`freqtrade convert-db` can be used to convert your database from one system to another (sqlite -> postgres, postgres -> other postgres), migrating all trades, orders and Pairlocks.
Please refer to the [SQL cheatsheet](sql_cheatsheet.md#use-a-different-database-system) to learn about requirements for different database systems.
```
usage: freqtrade convert-db [-h] [--db-url PATH] [--db-url-from PATH]
optional arguments:
-h, --help show this help message and exit
--db-url PATH Override trades database URL, this is useful in custom
deployments (default: `sqlite:///tradesv3.sqlite` for
Live Run mode, `sqlite:///tradesv3.dryrun.sqlite` for
Dry Run).
--db-url-from PATH Source db url to use when migrating a database.
```
!!! Warning
Please ensure to only use this on an empty target database. Freqtrade will perform a regular migration, but may fail if entries already existed.
## Webserver mode
!!! Warning "Experimental"
@@ -585,6 +611,26 @@ Common arguments:
```
### Webserver mode - docker
You can also use webserver mode via docker.
Starting a one-off container requires the configuration of the port explicitly, as ports are not exposed by default.
You can use `docker-compose run --rm -p 127.0.0.1:8080:8080 freqtrade webserver` to start a one-off container that'll be removed once you stop it. This assumes that port 8080 is still available and no other bot is running on that port.
Alternatively, you can reconfigure the docker-compose file to have the command updated:
``` yml
command: >
webserver
--config /freqtrade/user_data/config.json
```
You can now use `docker-compose up` to start the webserver.
This assumes that the configuration has a webserver enabled and configured for docker (listening port = `0.0.0.0`).
!!! Tip
Don't forget to reset the command back to the trade command if you want to start a live or dry-run bot.
## Show previous Backtest results
Allows you to show previous backtest results.
@@ -625,6 +671,61 @@ Common arguments:
```
## Detailed backtest analysis
Advanced backtest result analysis.
More details in the [Backtesting analysis](advanced-backtesting.md#analyze-the-buyentry-and-sellexit-tags) Section.
```
usage: freqtrade backtesting-analysis [-h] [-v] [--logfile FILE] [-V]
[-c PATH] [-d PATH] [--userdir PATH]
[--export-filename PATH]
[--analysis-groups {0,1,2,3,4} [{0,1,2,3,4} ...]]
[--enter-reason-list ENTER_REASON_LIST [ENTER_REASON_LIST ...]]
[--exit-reason-list EXIT_REASON_LIST [EXIT_REASON_LIST ...]]
[--indicator-list INDICATOR_LIST [INDICATOR_LIST ...]]
optional arguments:
-h, --help show this help message and exit
--export-filename PATH, --backtest-filename PATH
Use this filename for backtest results.Requires
`--export` to be set as well. Example: `--export-filen
ame=user_data/backtest_results/backtest_today.json`
--analysis-groups {0,1,2,3,4} [{0,1,2,3,4} ...]
grouping output - 0: simple wins/losses by enter tag,
1: by enter_tag, 2: by enter_tag and exit_tag, 3: by
pair and enter_tag, 4: by pair, enter_ and exit_tag
(this can get quite large)
--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'
--exit-reason-list EXIT_REASON_LIST [EXIT_REASON_LIST ...]
Comma separated list of exit signals to analyse.
Default: all. e.g.
'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'
Common arguments:
-v, --verbose Verbose mode (-vv for more, -vvv to get all messages).
--logfile FILE Log to the file specified. Special values are:
'syslog', 'journald'. See the documentation for more
details.
-V, --version show program's version number and exit
-c PATH, --config PATH
Specify configuration file (default:
`userdir/config.json` or `config.json` whichever
exists). Multiple --config options may be used. Can be
set to `-` to read config from stdin.
-d PATH, --datadir PATH
Path to directory with historical backtesting data.
--userdir PATH, --user-data-dir PATH
Path to userdata directory.
```
## List Hyperopt results
You can list the hyperoptimization epochs the Hyperopt module evaluated previously with the `hyperopt-list` sub-command.

View File

@@ -239,3 +239,52 @@ Possible parameters are:
The fields in `webhook.webhookstatus` are used for regular status messages (Started / Stopped / ...). Parameters are filled using string.format.
The only possible value here is `{status}`.
## Discord
A special form of webhooks is available for discord.
You can configure this as follows:
```json
"discord": {
"enabled": true,
"webhook_url": "https://discord.com/api/webhooks/<Your webhook URL ...>",
"exit_fill": [
{"Trade ID": "{trade_id}"},
{"Exchange": "{exchange}"},
{"Pair": "{pair}"},
{"Direction": "{direction}"},
{"Open rate": "{open_rate}"},
{"Close rate": "{close_rate}"},
{"Amount": "{amount}"},
{"Open date": "{open_date:%Y-%m-%d %H:%M:%S}"},
{"Close date": "{close_date:%Y-%m-%d %H:%M:%S}"},
{"Profit": "{profit_amount} {stake_currency}"},
{"Profitability": "{profit_ratio:.2%}"},
{"Enter tag": "{enter_tag}"},
{"Exit Reason": "{exit_reason}"},
{"Strategy": "{strategy}"},
{"Timeframe": "{timeframe}"},
],
"entry_fill": [
{"Trade ID": "{trade_id}"},
{"Exchange": "{exchange}"},
{"Pair": "{pair}"},
{"Direction": "{direction}"},
{"Open rate": "{open_rate}"},
{"Amount": "{amount}"},
{"Open date": "{open_date:%Y-%m-%d %H:%M:%S}"},
{"Enter tag": "{enter_tag}"},
{"Strategy": "{strategy} {timeframe}"},
]
}
```
The above represents the default (`exit_fill` and `entry_fill` are optional and will default to the above configuration) - modifications are obviously possible.
Available fields correspond to the fields for webhooks and are documented in the corresponding webhook sections.
The notifications will look as follows by default.
![discord-notification](assets/discord_notification.png)

View File

@@ -9,6 +9,7 @@ dependencies:
- pandas
- pip
- py-find-1st
- aiohttp
- SQLAlchemy
- python-telegram-bot
@@ -64,7 +65,7 @@ dependencies:
- pip:
- pycoingecko
- py_find_1st
# - py_find_1st
- tables
- pytest-random-order
- ccxt

View File

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

View File

@@ -6,10 +6,12 @@ Contains all start-commands, subcommands and CLI Interface creation.
Note: Be careful with file-scoped imports in these subfiles.
as they are parsed on startup, nothing containing optional modules should be loaded.
"""
from freqtrade.commands.analyze_commands import start_analysis_entries_exits
from freqtrade.commands.arguments import Arguments
from freqtrade.commands.build_config_commands import start_new_config
from freqtrade.commands.data_commands import (start_convert_data, start_convert_trades,
start_download_data, start_list_data)
from freqtrade.commands.db_commands import start_convert_db
from freqtrade.commands.deploy_commands import (start_create_userdir, start_install_ui,
start_new_strategy)
from freqtrade.commands.hyperopt_commands import start_hyperopt_list, start_hyperopt_show

View File

@@ -0,0 +1,69 @@
import logging
from pathlib import Path
from typing import Any, Dict
from freqtrade.configuration import setup_utils_configuration
from freqtrade.enums import RunMode
from freqtrade.exceptions import OperationalException
logger = logging.getLogger(__name__)
def setup_analyze_configuration(args: Dict[str, Any], method: RunMode) -> Dict[str, Any]:
"""
Prepare the configuration for the entry/exit reason analysis module
:param args: Cli args from Arguments()
:param method: Bot running mode
:return: Configuration
"""
config = setup_utils_configuration(args, method)
no_unlimited_runmodes = {
RunMode.BACKTEST: 'backtesting',
}
if method in no_unlimited_runmodes.keys():
from freqtrade.data.btanalysis import get_latest_backtest_filename
if 'exportfilename' in config:
if config['exportfilename'].is_dir():
btfile = Path(get_latest_backtest_filename(config['exportfilename']))
signals_file = f"{config['exportfilename']}/{btfile.stem}_signals.pkl"
else:
if config['exportfilename'].exists():
btfile = Path(config['exportfilename'])
signals_file = f"{btfile.parent}/{btfile.stem}_signals.pkl"
else:
raise OperationalException(f"{config['exportfilename']} does not exist.")
else:
raise OperationalException('exportfilename not in config.')
if (not Path(signals_file).exists()):
raise OperationalException(
(f"Cannot find latest backtest signals file: {signals_file}."
"Run backtesting with `--export signals`.")
)
return config
def start_analysis_entries_exits(args: Dict[str, Any]) -> None:
"""
Start analysis script
:param args: Cli args from Arguments()
:return: None
"""
from freqtrade.data.entryexitanalysis import process_entry_exit_reasons
# Initialize configuration
config = setup_analyze_configuration(args, RunMode.BACKTEST)
logger.info('Starting freqtrade in analysis mode')
process_entry_exit_reasons(config['exportfilename'],
config['exchange']['pair_whitelist'],
config['analysis_groups'],
config['enter_reason_list'],
config['exit_reason_list'],
config['indicator_list']
)

View File

@@ -12,7 +12,8 @@ from freqtrade.constants import DEFAULT_CONFIG
ARGS_COMMON = ["verbosity", "logfile", "version", "config", "datadir", "user_data_dir"]
ARGS_STRATEGY = ["strategy", "strategy_path", "recursive_strategy_search"]
ARGS_STRATEGY = ["strategy", "strategy_path", "recursive_strategy_search", "freqaimodel",
"freqaimodel_path"]
ARGS_TRADE = ["db_url", "sd_notify", "dry_run", "dry_run_wallet", "fee"]
@@ -28,7 +29,7 @@ ARGS_BACKTEST = ARGS_COMMON_OPTIMIZE + ["position_stacking", "use_max_market_pos
ARGS_HYPEROPT = ARGS_COMMON_OPTIMIZE + ["hyperopt", "hyperopt_path",
"position_stacking", "use_max_market_positions",
"enable_protections", "dry_run_wallet",
"enable_protections", "dry_run_wallet", "timeframe_detail",
"epochs", "spaces", "print_all",
"print_colorized", "print_json", "hyperopt_jobs",
"hyperopt_random_state", "hyperopt_min_trades",
@@ -72,7 +73,8 @@ ARGS_LIST_DATA = ["exchange", "dataformat_ohlcv", "pairs", "trading_mode"]
ARGS_DOWNLOAD_DATA = ["pairs", "pairs_file", "days", "new_pairs_days", "include_inactive",
"timerange", "download_trades", "exchange", "timeframes",
"erase", "dataformat_ohlcv", "dataformat_trades", "trading_mode"]
"erase", "dataformat_ohlcv", "dataformat_trades", "trading_mode",
"prepend_data"]
ARGS_PLOT_DATAFRAME = ["pairs", "indicators1", "indicators2", "plot_limit",
"db_url", "trade_source", "export", "exportfilename",
@@ -81,7 +83,9 @@ ARGS_PLOT_DATAFRAME = ["pairs", "indicators1", "indicators2", "plot_limit",
ARGS_PLOT_PROFIT = ["pairs", "timerange", "export", "exportfilename", "db_url",
"trade_source", "timeframe", "plot_auto_open", ]
ARGS_INSTALL_UI = ["erase_ui_only", 'ui_version']
ARGS_CONVERT_DB = ["db_url", "db_url_from"]
ARGS_INSTALL_UI = ["erase_ui_only", "ui_version"]
ARGS_SHOW_TRADES = ["db_url", "trade_ids", "print_json"]
@@ -98,6 +102,9 @@ ARGS_HYPEROPT_SHOW = ["hyperopt_list_best", "hyperopt_list_profitable", "hyperop
"print_json", "hyperoptexportfilename", "hyperopt_show_no_header",
"disableparamexport", "backtest_breakdown"]
ARGS_ANALYZE_ENTRIES_EXITS = ["exportfilename", "analysis_groups", "enter_reason_list",
"exit_reason_list", "indicator_list"]
NO_CONF_REQURIED = ["convert-data", "convert-trade-data", "download-data", "list-timeframes",
"list-markets", "list-pairs", "list-strategies", "list-data",
"hyperopt-list", "hyperopt-show", "backtest-filter",
@@ -179,8 +186,9 @@ class Arguments:
self.parser = argparse.ArgumentParser(description='Free, open source crypto trading bot')
self._build_args(optionlist=['version'], parser=self.parser)
from freqtrade.commands import (start_backtesting, start_backtesting_show,
start_convert_data, start_convert_trades,
from freqtrade.commands import (start_analysis_entries_exits, start_backtesting,
start_backtesting_show, start_convert_data,
start_convert_db, start_convert_trades,
start_create_userdir, start_download_data, start_edge,
start_hyperopt, start_hyperopt_list, start_hyperopt_show,
start_install_ui, start_list_data, start_list_exchanges,
@@ -280,6 +288,13 @@ class Arguments:
backtesting_show_cmd.set_defaults(func=start_backtesting_show)
self._build_args(optionlist=ARGS_BACKTEST_SHOW, parser=backtesting_show_cmd)
# Add backtesting analysis subcommand
analysis_cmd = subparsers.add_parser('backtesting-analysis',
help='Backtest Analysis module.',
parents=[_common_parser])
analysis_cmd.set_defaults(func=start_analysis_entries_exits)
self._build_args(optionlist=ARGS_ANALYZE_ENTRIES_EXITS, parser=analysis_cmd)
# Add edge subcommand
edge_cmd = subparsers.add_parser('edge', help='Edge module.',
parents=[_common_parser, _strategy_parser])
@@ -373,6 +388,14 @@ class Arguments:
test_pairlist_cmd.set_defaults(func=start_test_pairlist)
self._build_args(optionlist=ARGS_TEST_PAIRLIST, parser=test_pairlist_cmd)
# Add db-convert subcommand
convert_db = subparsers.add_parser(
"convert-db",
help="Migrate database to different system",
)
convert_db.set_defaults(func=start_convert_db)
self._build_args(optionlist=ARGS_CONVERT_DB, parser=convert_db)
# Add install-ui subcommand
install_ui_cmd = subparsers.add_parser(
'install-ui',

View File

@@ -67,7 +67,7 @@ def ask_user_config() -> Dict[str, Any]:
"type": "text",
"name": "stake_amount",
"message": f"Please insert your stake amount (Number or '{UNLIMITED_STAKE_AMOUNT}'):",
"default": "100",
"default": "unlimited",
"validate": lambda val: val == UNLIMITED_STAKE_AMOUNT or validate_is_float(val),
"filter": lambda val: '"' + UNLIMITED_STAKE_AMOUNT + '"'
if val == UNLIMITED_STAKE_AMOUNT
@@ -164,7 +164,7 @@ def ask_user_config() -> Dict[str, Any]:
"when": lambda x: x['telegram']
},
{
"type": "text",
"type": "password",
"name": "telegram_chat_id",
"message": "Insert Telegram chat id",
"when": lambda x: x['telegram']
@@ -191,7 +191,7 @@ def ask_user_config() -> Dict[str, Any]:
"when": lambda x: x['api_server']
},
{
"type": "text",
"type": "password",
"name": "api_server_password",
"message": "Insert api-server password",
"when": lambda x: x['api_server']

View File

@@ -106,6 +106,11 @@ AVAILABLE_CLI_OPTIONS = {
f'`{constants.DEFAULT_DB_DRYRUN_URL}` for Dry Run).',
metavar='PATH',
),
"db_url_from": Arg(
'--db-url-from',
help='Source db url to use when migrating a database.',
metavar='PATH',
),
"sd_notify": Arg(
'--sd-notify',
help='Notify systemd service manager.',
@@ -443,6 +448,11 @@ AVAILABLE_CLI_OPTIONS = {
default=['1m', '5m'],
nargs='+',
),
"prepend_data": Arg(
'--prepend',
help='Allow data prepending.',
action='store_true',
),
"erase": Arg(
'--erase',
help='Clean all existing data for the selected exchange/pairs/timeframes.',
@@ -604,4 +614,47 @@ AVAILABLE_CLI_OPTIONS = {
"that do not contain any parameters."),
action="store_true",
),
"analysis_groups": Arg(
"--analysis-groups",
help=("grouping output - "
"0: simple wins/losses by enter tag, "
"1: by enter_tag, "
"2: by enter_tag and exit_tag, "
"3: by pair and enter_tag, "
"4: by pair, enter_ and exit_tag (this can get quite large)"),
nargs='+',
default=['0', '1', '2'],
choices=['0', '1', '2', '3', '4'],
),
"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'"),
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'"),
nargs='+',
default=['all'],
),
"indicator_list": Arg(
"--indicator-list",
help=("Comma separated list of indicators to analyse. "
"e.g. 'close,rsi,bb_lowerband,profit_abs'"),
nargs='+',
default=[],
),
"freqaimodel": Arg(
'--freqaimodel',
help='Specify a custom freqaimodels.',
metavar='NAME',
),
"freqaimodel_path": Arg(
'--freqaimodel-path',
help='Specify additional lookup path for freqaimodels.',
metavar='PATH',
),
}

View File

@@ -12,7 +12,7 @@ from freqtrade.enums import CandleType, RunMode, TradingMode
from freqtrade.exceptions import OperationalException
from freqtrade.exchange import timeframe_to_minutes
from freqtrade.exchange.exchange import market_is_active
from freqtrade.plugins.pairlist.pairlist_helpers import expand_pairlist
from freqtrade.plugins.pairlist.pairlist_helpers import dynamic_expand_pairlist, expand_pairlist
from freqtrade.resolvers import ExchangeResolver
@@ -50,7 +50,8 @@ def start_download_data(args: Dict[str, Any]) -> None:
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 = expand_pairlist(config['pairs'], markets)
expanded_pairs = dynamic_expand_pairlist(config, markets)
# Manual validations of relevant settings
if not config['exchange'].get('skip_pair_validation', False):
@@ -79,12 +80,19 @@ def start_download_data(args: Dict[str, Any]) -> None:
data_format_trades=config['dataformat_trades'],
)
else:
if not exchange._ft_has.get('ohlcv_has_history', True):
raise OperationalException(
f"Historic klines not available for {exchange.name}. "
"Please use `--dl-trades` instead for this exchange "
"(will unfortunately take a long time)."
)
pairs_not_available = refresh_backtest_ohlcv_data(
exchange, pairs=expanded_pairs, timeframes=config['timeframes'],
datadir=config['datadir'], timerange=timerange,
new_pairs_days=config['new_pairs_days'],
erase=bool(config.get('erase')), data_format=config['dataformat_ohlcv'],
trading_mode=config.get('trading_mode', 'spot'),
prepend=config.get('prepend_data', False)
)
except KeyboardInterrupt:

View File

@@ -0,0 +1,55 @@
import logging
from typing import Any, Dict
from sqlalchemy import func
from freqtrade.configuration.config_setup import setup_utils_configuration
from freqtrade.enums.runmode import RunMode
logger = logging.getLogger(__name__)
def start_convert_db(args: Dict[str, Any]) -> None:
from sqlalchemy.orm import make_transient
from freqtrade.persistence import Order, Trade, init_db
from freqtrade.persistence.migrations import set_sequence_ids
from freqtrade.persistence.pairlock import PairLock
config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE)
init_db(config['db_url'])
session_target = Trade._session
init_db(config['db_url_from'])
logger.info("Starting db migration.")
trade_count = 0
pairlock_count = 0
for trade in Trade.get_trades():
trade_count += 1
make_transient(trade)
for o in trade.orders:
make_transient(o)
session_target.add(trade)
session_target.commit()
for pairlock in PairLock.query:
pairlock_count += 1
make_transient(pairlock)
session_target.add(pairlock)
session_target.commit()
# Update sequences
max_trade_id = session_target.query(func.max(Trade.id)).scalar()
max_order_id = session_target.query(func.max(Order.id)).scalar()
max_pairlock_id = session_target.query(func.max(PairLock.id)).scalar()
set_sequence_ids(session_target.get_bind(),
trade_id=max_trade_id,
order_id=max_order_id,
pairlock_id=max_pairlock_id)
logger.info(f"Migrated {trade_count} Trades, and {pairlock_count} Pairlocks.")

View File

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

View File

@@ -212,7 +212,7 @@ def start_show_trades(args: Dict[str, Any]) -> None:
raise OperationalException("--db-url is required for this command.")
logger.info(f'Using DB: "{parse_db_uri_for_logging(config["db_url"])}"')
init_db(config['db_url'], clean_open_orders=False)
init_db(config['db_url'])
tfilter = []
if config.get('trade_ids'):

View File

@@ -4,5 +4,4 @@ from freqtrade.configuration.check_exchange import check_exchange
from freqtrade.configuration.config_setup import setup_utils_configuration
from freqtrade.configuration.config_validation import validate_config_consistency
from freqtrade.configuration.configuration import Configuration
from freqtrade.configuration.PeriodicCache import PeriodicCache
from freqtrade.configuration.timerange import TimeRange

View File

@@ -27,7 +27,7 @@ def check_exchange(config: Dict[str, Any], check_for_bad: bool = True) -> bool:
return True
logger.info("Checking exchange...")
exchange = config.get('exchange', {}).get('name').lower()
exchange = config.get('exchange', {}).get('name', '').lower()
if not exchange:
raise OperationalException(
f'This command requires a configured exchange. You should either use '

View File

@@ -95,6 +95,10 @@ class Configuration:
self._process_data_options(config)
self._process_analyze_options(config)
self._process_freqai_options(config)
# Check if the exchange set by the user is supported
check_exchange(config, config.get('experimental', {}).get('block_bad_exchanges', True))
@@ -127,7 +131,7 @@ class Configuration:
# Default to in-memory db for dry_run if not specified
config['db_url'] = constants.DEFAULT_DB_DRYRUN_URL
else:
if not config.get('db_url', None):
if not config.get('db_url'):
config['db_url'] = constants.DEFAULT_DB_PROD_URL
logger.info('Dry run is disabled')
@@ -147,6 +151,9 @@ class Configuration:
config.update({'db_url': self.args['db_url']})
logger.info('Parameter --db-url detected ...')
self._args_to_config(config, argname='db_url_from',
logstring='Parameter --db-url-from detected ...')
if config.get('force_entry_enable', False):
logger.warning('`force_entry_enable` RPC message enabled.')
@@ -177,7 +184,7 @@ class Configuration:
config['user_data_dir'] = create_userdata_dir(config['user_data_dir'], create_dir=False)
logger.info('Using user-data directory: %s ...', config['user_data_dir'])
config.update({'datadir': create_datadir(config, self.args.get('datadir', None))})
config.update({'datadir': create_datadir(config, self.args.get('datadir'))})
logger.info('Using data directory: %s ...', config.get('datadir'))
if self.args.get('exportfilename'):
@@ -216,7 +223,7 @@ class Configuration:
if config.get('max_open_trades') == -1:
config['max_open_trades'] = float('inf')
if self.args.get('stake_amount', None):
if self.args.get('stake_amount'):
# Convert explicitly to float to support CLI argument for both unlimited and value
try:
self.args['stake_amount'] = float(self.args['stake_amount'])
@@ -393,6 +400,8 @@ class Configuration:
self._args_to_config(config, argname='trade_source',
logstring='Using trades from: {}')
self._args_to_config(config, argname='prepend_data',
logstring='Prepend detected. Allowing data prepending.')
self._args_to_config(config, argname='erase',
logstring='Erase detected. Deleting existing data.')
@@ -428,6 +437,19 @@ class Configuration:
self._args_to_config(config, argname='candle_types',
logstring='Detected --candle-types: {}')
def _process_analyze_options(self, config: Dict[str, Any]) -> None:
self._args_to_config(config, argname='analysis_groups',
logstring='Analysis reason groups: {}')
self._args_to_config(config, argname='enter_reason_list',
logstring='Analysis enter tag list: {}')
self._args_to_config(config, argname='exit_reason_list',
logstring='Analysis exit tag list: {}')
self._args_to_config(config, argname='indicator_list',
logstring='Analysis indicator list: {}')
def _process_runmode(self, config: Dict[str, Any]) -> None:
self._args_to_config(config, argname='dry_run',
@@ -441,6 +463,16 @@ class Configuration:
config.update({'runmode': self.runmode})
def _process_freqai_options(self, config: Dict[str, Any]) -> None:
self._args_to_config(config, argname='freqaimodel',
logstring='Using freqaimodel class name: {}')
self._args_to_config(config, argname='freqaimodel_path',
logstring='Using freqaimodel path: {}')
return
def _args_to_config(self, config: Dict[str, Any], argname: str,
logstring: str, logfun: Optional[Callable] = None,
deprecated_msg: Optional[str] = None) -> None:
@@ -485,6 +517,7 @@ class Configuration:
if not pairs_file.exists():
raise OperationalException(f'No pairs file found with path "{pairs_file}".')
config['pairs'] = load_file(pairs_file)
if isinstance(config['pairs'], list):
config['pairs'].sort()
return
@@ -496,5 +529,5 @@ class Configuration:
pairs_file = config['datadir'] / 'pairs.json'
if pairs_file.exists():
config['pairs'] = load_file(pairs_file)
if 'pairs' in config:
if 'pairs' in config and isinstance(config['pairs'], list):
config['pairs'].sort()

View File

@@ -113,7 +113,7 @@ def process_temporary_deprecated_settings(config: Dict[str, Any]) -> None:
process_removed_setting(config, 'experimental', 'ignore_roi_if_buy_signal',
None, 'ignore_roi_if_entry_signal')
process_removed_setting(config, 'ask_strategy', 'use_sell_signal', None, 'exit_sell_signal')
process_removed_setting(config, 'ask_strategy', 'use_sell_signal', None, 'use_exit_signal')
process_removed_setting(config, 'ask_strategy', 'sell_profit_only', None, 'exit_profit_only')
process_removed_setting(config, 'ask_strategy', 'sell_profit_offset',
None, 'exit_profit_offset')

View File

@@ -15,7 +15,7 @@ def create_datadir(config: Dict[str, Any], datadir: Optional[str] = None) -> Pat
folder = Path(datadir) if datadir else Path(f"{config['user_data_dir']}/data")
if not datadir:
# set datadir
exchange_name = config.get('exchange', {}).get('name').lower()
exchange_name = config.get('exchange', {}).get('name', '').lower()
folder = folder.joinpath(exchange_name)
if not folder.is_dir():

View File

@@ -28,7 +28,8 @@ HYPEROPT_LOSS_BUILTIN = ['ShortTradeDurHyperOptLoss', 'OnlyProfitHyperOptLoss',
'SharpeHyperOptLoss', 'SharpeHyperOptLossDaily',
'SortinoHyperOptLoss', 'SortinoHyperOptLossDaily',
'CalmarHyperOptLoss',
'MaxDrawDownHyperOptLoss', 'ProfitDrawDownHyperOptLoss']
'MaxDrawDownHyperOptLoss', 'MaxDrawDownRelativeHyperOptLoss',
'ProfitDrawDownHyperOptLoss']
AVAILABLE_PAIRLISTS = ['StaticPairList', 'VolumePairList',
'AgeFilter', 'OffsetFilter', 'PerformanceFilter',
'PrecisionFilter', 'PriceFilter', 'RangeStabilityFilter',
@@ -54,6 +55,7 @@ FTHYPT_FILEVERSION = 'fthypt_fileversion'
USERPATH_HYPEROPTS = 'hyperopts'
USERPATH_STRATEGIES = 'strategies'
USERPATH_NOTEBOOKS = 'notebooks'
USERPATH_FREQAIMODELS = 'freqaimodels'
TELEGRAM_SETTING_OPTIONS = ['on', 'off', 'silent']
WEBHOOK_FORMAT_OPTIONS = ['form', 'json', 'raw']
@@ -239,6 +241,7 @@ CONF_SCHEMA = {
},
'exchange': {'$ref': '#/definitions/exchange'},
'edge': {'$ref': '#/definitions/edge'},
'freqai': {'$ref': '#/definitions/freqai'},
'experimental': {
'type': 'object',
'properties': {
@@ -301,17 +304,25 @@ CONF_SCHEMA = {
'exit_fill': {
'type': 'string',
'enum': TELEGRAM_SETTING_OPTIONS,
'default': 'off'
'default': 'on'
},
'protection_trigger': {
'type': 'string',
'enum': TELEGRAM_SETTING_OPTIONS,
'default': 'off'
'default': 'on'
},
'protection_trigger_global': {
'type': 'string',
'enum': TELEGRAM_SETTING_OPTIONS,
},
'show_candle': {
'type': 'string',
'enum': ['off', 'ohlc'],
},
'strategy_msg': {
'type': 'string',
'enum': TELEGRAM_SETTING_OPTIONS,
},
}
},
'reload': {'type': 'boolean'},
@@ -335,6 +346,47 @@ CONF_SCHEMA = {
'webhookstatus': {'type': 'object'},
},
},
'discord': {
'type': 'object',
'properties': {
'enabled': {'type': 'boolean'},
'webhook_url': {'type': 'string'},
"exit_fill": {
'type': 'array', 'items': {'type': 'object'},
'default': [
{"Trade ID": "{trade_id}"},
{"Exchange": "{exchange}"},
{"Pair": "{pair}"},
{"Direction": "{direction}"},
{"Open rate": "{open_rate}"},
{"Close rate": "{close_rate}"},
{"Amount": "{amount}"},
{"Open date": "{open_date:%Y-%m-%d %H:%M:%S}"},
{"Close date": "{close_date:%Y-%m-%d %H:%M:%S}"},
{"Profit": "{profit_amount} {stake_currency}"},
{"Profitability": "{profit_ratio:.2%}"},
{"Enter tag": "{enter_tag}"},
{"Exit Reason": "{exit_reason}"},
{"Strategy": "{strategy}"},
{"Timeframe": "{timeframe}"},
]
},
"entry_fill": {
'type': 'array', 'items': {'type': 'object'},
'default': [
{"Trade ID": "{trade_id}"},
{"Exchange": "{exchange}"},
{"Pair": "{pair}"},
{"Direction": "{direction}"},
{"Open rate": "{open_rate}"},
{"Amount": "{amount}"},
{"Open date": "{open_date:%Y-%m-%d %H:%M:%S}"},
{"Enter tag": "{enter_tag}"},
{"Strategy": "{strategy} {timeframe}"},
]
},
}
},
'api_server': {
'type': 'object',
'properties': {
@@ -430,8 +482,61 @@ CONF_SCHEMA = {
'remove_pumps': {'type': 'boolean'}
},
'required': ['process_throttle_secs', 'allowed_risk']
},
"freqai": {
"type": "object",
"properties": {
"enabled": {"type": "boolean", "default": False},
"keras": {"type": "boolean", "default": False},
"conv_width": {"type": "integer", "default": 2},
"train_period_days": {"type": "integer", "default": 0},
"backtest_period_days": {"type": "number", "default": 7},
"identifier": {"type": "string", "default": "example"},
"feature_parameters": {
"type": "object",
"properties": {
"include_corr_pairlist": {"type": "array"},
"include_timeframes": {"type": "array"},
"label_period_candles": {"type": "integer"},
"include_shifted_candles": {"type": "integer", "default": 0},
"DI_threshold": {"type": "number", "default": 0},
"weight_factor": {"type": "number", "default": 0},
"principal_component_analysis": {"type": "boolean", "default": False},
"use_SVM_to_remove_outliers": {"type": "boolean", "default": False},
"svm_params": {"type": "object",
"properties": {
"shuffle": {"type": "boolean", "default": False},
"nu": {"type": "number", "default": 0.1}
},
}
},
"required": ["include_timeframes", "include_corr_pairlist", ]
},
"data_split_parameters": {
"type": "object",
"properties": {
"test_size": {"type": "number"},
"random_state": {"type": "integer"},
},
},
"model_training_parameters": {
"type": "object",
"properties": {
"n_estimators": {"type": "integer", "default": 1000}
},
},
},
"required": [
"enabled",
"train_period_days",
"backtest_period_days",
"identifier",
"feature_parameters",
"data_split_parameters",
"model_training_parameters"
]
},
},
}
SCHEMA_TRADE_REQUIRED = [
@@ -482,6 +587,8 @@ CANCEL_REASON = {
"ALL_CANCELLED": "cancelled (all unfilled and partially filled open orders cancelled)",
"CANCELLED_ON_EXCHANGE": "cancelled on exchange",
"FORCE_EXIT": "forcesold",
"REPLACE": "cancelled to be replaced by new limit order",
"USER_CANCEL": "user requested order cancel"
}
# List of pairs with their timeframes
@@ -493,3 +600,5 @@ TradeList = List[List]
LongShort = Literal['long', 'short']
EntryExit = Literal['entry', 'exit']
BuySell = Literal['buy', 'sell']
MakerTaker = Literal['maker', 'taker']

View File

@@ -26,7 +26,7 @@ BT_DATA_COLUMNS = ['pair', 'stake_amount', 'amount', 'open_date', 'close_date',
'profit_ratio', 'profit_abs', 'exit_reason',
'initial_stop_loss_abs', 'initial_stop_loss_ratio', 'stop_loss_abs',
'stop_loss_ratio', 'min_rate', 'max_rate', 'is_open', 'enter_tag',
'is_short'
'is_short', 'open_timestamp', 'close_timestamp', 'orders'
]
@@ -283,6 +283,8 @@ def load_backtest_data(filename: Union[Path, str], strategy: Optional[str] = Non
if 'enter_tag' not in df.columns:
df['enter_tag'] = df['buy_tag']
df = df.drop(['buy_tag'], axis=1)
if 'orders' not in df.columns:
df.loc[:, 'orders'] = None
else:
# old format - only with lists.
@@ -337,7 +339,7 @@ def trade_list_to_dataframe(trades: List[LocalTrade]) -> pd.DataFrame:
:param trades: List of trade objects
:return: Dataframe with BT_DATA_COLUMNS
"""
df = pd.DataFrame.from_records([t.to_json() for t in trades], columns=BT_DATA_COLUMNS)
df = pd.DataFrame.from_records([t.to_json(True) for t in trades], columns=BT_DATA_COLUMNS)
if len(df) > 0:
df.loc[:, 'close_date'] = pd.to_datetime(df['close_date'], utc=True)
df.loc[:, 'open_date'] = pd.to_datetime(df['open_date'], utc=True)
@@ -353,7 +355,7 @@ def load_trades_from_db(db_url: str, strategy: Optional[str] = None) -> pd.DataF
Can also serve as protection to load the correct result.
:return: Dataframe containing Trades
"""
init_db(db_url, clean_open_orders=False)
init_db(db_url)
filters = []
if strategy:

View File

@@ -5,6 +5,7 @@ including ticker and orderbook data, live and historical candle (OHLCV) data
Common Interface for bot and strategy to access data.
"""
import logging
from collections import deque
from datetime import datetime, timezone
from typing import Any, Dict, List, Optional, Tuple
@@ -16,6 +17,7 @@ from freqtrade.data.history import load_pair_history
from freqtrade.enums import CandleType, RunMode
from freqtrade.exceptions import ExchangeError, OperationalException
from freqtrade.exchange import Exchange, timeframe_to_seconds
from freqtrade.util import PeriodicCache
logger = logging.getLogger(__name__)
@@ -33,6 +35,10 @@ class DataProvider:
self.__cached_pairs: Dict[PairWithTimeframe, Tuple[DataFrame, datetime]] = {}
self.__slice_index: Optional[int] = None
self.__cached_pairs_backtesting: Dict[PairWithTimeframe, DataFrame] = {}
self._msg_queue: deque = deque()
self.__msg_cache = PeriodicCache(
maxsize=1000, ttl=timeframe_to_seconds(self._config.get('timeframe', '1h')))
def _set_dataframe_max_index(self, limit_index: int):
"""
@@ -265,3 +271,20 @@ class DataProvider:
if self._exchange is None:
raise OperationalException(NO_EXCHANGE_EXCEPTION)
return self._exchange.fetch_l2_order_book(pair, maximum)
def send_msg(self, message: str, *, always_send: bool = False) -> None:
"""
Send custom RPC Notifications from your bot.
Will not send any bot in modes other than Dry-run or Live.
:param message: Message to be sent. Must be below 4096.
:param always_send: If False, will send the message only once per candle, and surpress
identical messages.
Careful as this can end up spaming your chat.
Defaults to False
"""
if self.runmode not in (RunMode.DRY_RUN, RunMode.LIVE):
return
if always_send or message not in self.__msg_cache:
self._msg_queue.append(message)
self.__msg_cache[message] = True

View File

@@ -0,0 +1,227 @@
import logging
from pathlib import Path
from typing import List, Optional
import joblib
import pandas as pd
from tabulate import tabulate
from freqtrade.data.btanalysis import (get_latest_backtest_filename, load_backtest_data,
load_backtest_stats)
from freqtrade.exceptions import OperationalException
logger = logging.getLogger(__name__)
def _load_signal_candles(backtest_dir: Path):
if backtest_dir.is_dir():
scpf = Path(backtest_dir,
Path(get_latest_backtest_filename(backtest_dir)).stem + "_signals.pkl"
)
else:
scpf = Path(backtest_dir.parent / f"{backtest_dir.stem}_signals.pkl")
try:
scp = open(scpf, "rb")
signal_candles = joblib.load(scp)
logger.info(f"Loaded signal candles: {str(scpf)}")
except Exception as e:
logger.error("Cannot load signal candles from pickled results: ", e)
return signal_candles
def _process_candles_and_indicators(pairlist, strategy_name, trades, signal_candles):
analysed_trades_dict = {}
analysed_trades_dict[strategy_name] = {}
try:
logger.info(f"Processing {strategy_name} : {len(pairlist)} pairs")
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])
except Exception as e:
print(f"Cannot process entry/exit reasons for {strategy_name}: ", e)
return analysed_trades_dict
def _analyze_candles_and_indicators(pair, trades, signal_candles):
buyf = signal_candles
if len(buyf) > 0:
buyf = buyf.set_index('date', drop=False)
trades_red = trades.loc[trades['pair'] == pair].copy()
trades_inds = pd.DataFrame()
if trades_red.shape[0] > 0 and buyf.shape[0] > 0:
for t, v in trades_red.open_date.items():
allinds = buyf.loc[(buyf['date'] < v)]
if allinds.shape[0] > 0:
tmp_inds = allinds.iloc[[-1]]
trades_red.loc[t, 'signal_date'] = tmp_inds['date'].values[0]
trades_red.loc[t, 'enter_reason'] = trades_red.loc[t, 'enter_tag']
tmp_inds.index.rename('signal_date', inplace=True)
trades_inds = pd.concat([trades_inds, tmp_inds])
if 'signal_date' in trades_red:
trades_red['signal_date'] = pd.to_datetime(trades_red['signal_date'], utc=True)
trades_red.set_index('signal_date', inplace=True)
try:
trades_red = pd.merge(trades_red, trades_inds, on='signal_date', how='outer')
except Exception as e:
raise e
return trades_red
else:
return pd.DataFrame()
def _do_group_table_output(bigdf, glist):
for g in glist:
# 0: summary wins/losses grouped by enter tag
if g == "0":
group_mask = ['enter_reason']
wins = bigdf.loc[bigdf['profit_abs'] >= 0] \
.groupby(group_mask) \
.agg({'profit_abs': ['sum']})
wins.columns = ['profit_abs_wins']
loss = bigdf.loc[bigdf['profit_abs'] < 0] \
.groupby(group_mask) \
.agg({'profit_abs': ['sum']})
loss.columns = ['profit_abs_loss']
new = bigdf.groupby(group_mask).agg({'profit_abs': [
'count',
lambda x: sum(x > 0),
lambda x: sum(x <= 0)]})
new = pd.concat([new, wins, loss], axis=1).fillna(0)
new['profit_tot'] = new['profit_abs_wins'] - abs(new['profit_abs_loss'])
new['wl_ratio_pct'] = (new.iloc[:, 1] / new.iloc[:, 0] * 100).fillna(0)
new['avg_win'] = (new['profit_abs_wins'] / new.iloc[:, 1]).fillna(0)
new['avg_loss'] = (new['profit_abs_loss'] / new.iloc[:, 2]).fillna(0)
new.columns = ['total_num_buys', 'wins', 'losses', 'profit_abs_wins', 'profit_abs_loss',
'profit_tot', 'wl_ratio_pct', 'avg_win', 'avg_loss']
sortcols = ['total_num_buys']
_print_table(new, sortcols, show_index=True)
else:
agg_mask = {'profit_abs': ['count', 'sum', 'median', 'mean'],
'profit_ratio': ['sum', 'median', 'mean']}
agg_cols = ['num_buys', 'profit_abs_sum', 'profit_abs_median',
'profit_abs_mean', 'median_profit_pct', 'mean_profit_pct',
'total_profit_pct']
sortcols = ['profit_abs_sum', 'enter_reason']
# 1: profit summaries grouped by enter_tag
if g == "1":
group_mask = ['enter_reason']
# 2: profit summaries grouped by enter_tag and exit_tag
if g == "2":
group_mask = ['enter_reason', 'exit_reason']
# 3: profit summaries grouped by pair and enter_tag
if g == "3":
group_mask = ['pair', 'enter_reason']
# 4: profit summaries grouped by pair, enter_ and exit_tag (this can get quite large)
if g == "4":
group_mask = ['pair', 'enter_reason', 'exit_reason']
if group_mask:
new = bigdf.groupby(group_mask).agg(agg_mask).reset_index()
new.columns = group_mask + agg_cols
new['median_profit_pct'] = new['median_profit_pct'] * 100
new['mean_profit_pct'] = new['mean_profit_pct'] * 100
new['total_profit_pct'] = new['total_profit_pct'] * 100
_print_table(new, sortcols)
else:
logger.warning("Invalid group mask specified.")
def _print_results(analysed_trades, stratname, analysis_groups,
enter_reason_list, exit_reason_list,
indicator_list, columns=None):
if columns is None:
columns = ['pair', 'open_date', 'close_date', 'profit_abs', 'enter_reason', 'exit_reason']
bigdf = pd.DataFrame()
for pair, trades in analysed_trades[stratname].items():
bigdf = pd.concat([bigdf, trades], ignore_index=True)
if bigdf.shape[0] > 0 and ('enter_reason' in bigdf.columns):
if analysis_groups:
_do_group_table_output(bigdf, analysis_groups)
if enter_reason_list and "all" not in enter_reason_list:
bigdf = bigdf.loc[(bigdf['enter_reason'].isin(enter_reason_list))]
if exit_reason_list and "all" not in exit_reason_list:
bigdf = bigdf.loc[(bigdf['exit_reason'].isin(exit_reason_list))]
if "all" in indicator_list:
print(bigdf)
elif indicator_list is not None:
available_inds = []
for ind in indicator_list:
if ind in bigdf:
available_inds.append(ind)
ilist = ["pair", "enter_reason", "exit_reason"] + available_inds
_print_table(bigdf[ilist], sortcols=['exit_reason'], show_index=False)
else:
print("\\_ No trades to show")
def _print_table(df, sortcols=None, show_index=False):
if (sortcols is not None):
data = df.sort_values(sortcols)
else:
data = df
print(
tabulate(
data,
headers='keys',
tablefmt='psql',
showindex=show_index
)
)
def process_entry_exit_reasons(backtest_dir: Path,
pairlist: List[str],
analysis_groups: Optional[List[str]] = ["0", "1", "2"],
enter_reason_list: Optional[List[str]] = ["all"],
exit_reason_list: Optional[List[str]] = ["all"],
indicator_list: Optional[List[str]] = []):
try:
backtest_stats = load_backtest_stats(backtest_dir)
for strategy_name, results in backtest_stats['strategy'].items():
trades = load_backtest_data(backtest_dir, strategy_name)
if not trades.empty:
signal_candles = _load_signal_candles(backtest_dir)
analysed_trades_dict = _process_candles_and_indicators(pairlist, strategy_name,
trades, signal_candles)
_print_results(analysed_trades_dict,
strategy_name,
analysis_groups,
enter_reason_list,
exit_reason_list,
indicator_list)
except ValueError as e:
raise OperationalException(e) from e

View File

@@ -7,9 +7,8 @@ import numpy as np
import pandas as pd
from freqtrade.configuration import TimeRange
from freqtrade.constants import (DEFAULT_DATAFRAME_COLUMNS, DEFAULT_TRADES_COLUMNS,
ListPairsWithTimeframes, TradeList)
from freqtrade.enums import CandleType, TradingMode
from freqtrade.constants import DEFAULT_DATAFRAME_COLUMNS, DEFAULT_TRADES_COLUMNS, TradeList
from freqtrade.enums import CandleType
from .idatahandler import IDataHandler
@@ -21,29 +20,6 @@ class HDF5DataHandler(IDataHandler):
_columns = DEFAULT_DATAFRAME_COLUMNS
@classmethod
def ohlcv_get_available_data(
cls, datadir: Path, trading_mode: TradingMode) -> ListPairsWithTimeframes:
"""
Returns a list of all pairs with ohlcv data available in this datadir
:param datadir: Directory to search for ohlcv files
:param trading_mode: trading-mode to be used
:return: List of Tuples of (pair, timeframe)
"""
if trading_mode == TradingMode.FUTURES:
datadir = datadir.joinpath('futures')
_tmp = [
re.search(
cls._OHLCV_REGEX, p.name
) for p in datadir.glob("*.h5")
]
return [
(
cls.rebuild_pair_from_filename(match[1]),
match[2],
CandleType.from_string(match[3])
) for match in _tmp if match and len(match.groups()) > 1]
@classmethod
def ohlcv_get_pairs(cls, datadir: Path, timeframe: str, candle_type: CandleType) -> List[str]:
"""
@@ -108,6 +84,10 @@ class HDF5DataHandler(IDataHandler):
candle_type=candle_type
)
if not filename.exists():
# Fallback mode for 1M files
filename = self._pair_data_filename(
self._datadir, pair, timeframe, candle_type=candle_type, no_timeframe_modify=True)
if not filename.exists():
return pd.DataFrame(columns=self._columns)
where = []

View File

@@ -56,7 +56,7 @@ def load_pair_history(pair: str,
fill_missing=fill_up_missing,
drop_incomplete=drop_incomplete,
startup_candles=startup_candles,
candle_type=candle_type
candle_type=candle_type,
)
@@ -68,7 +68,8 @@ def load_data(datadir: Path,
startup_candles: int = 0,
fail_without_data: bool = False,
data_format: str = 'json',
candle_type: CandleType = CandleType.SPOT
candle_type: CandleType = CandleType.SPOT,
user_futures_funding_rate: int = None,
) -> Dict[str, DataFrame]:
"""
Load ohlcv history data for a list of pairs.
@@ -96,10 +97,15 @@ def load_data(datadir: Path,
fill_up_missing=fill_up_missing,
startup_candles=startup_candles,
data_handler=data_handler,
candle_type=candle_type
candle_type=candle_type,
)
if not hist.empty:
result[pair] = hist
else:
if candle_type is CandleType.FUNDING_RATE and user_futures_funding_rate is not None:
logger.warn(f"{pair} using user specified [{user_futures_funding_rate}]")
elif candle_type not in (CandleType.SPOT, CandleType.FUTURES):
result[pair] = DataFrame(columns=["date", "open", "close", "high", "low", "volume"])
if fail_without_data and not result:
raise OperationalException("No data found. Terminating.")
@@ -139,8 +145,9 @@ def _load_cached_data_for_updating(
timeframe: str,
timerange: Optional[TimeRange],
data_handler: IDataHandler,
candle_type: CandleType
) -> Tuple[DataFrame, Optional[int]]:
candle_type: CandleType,
prepend: bool = False,
) -> Tuple[DataFrame, Optional[int], Optional[int]]:
"""
Load cached data to download more data.
If timerange is passed in, checks whether data from an before the stored data will be
@@ -150,9 +157,12 @@ def _load_cached_data_for_updating(
Note: Only used by download_pair_history().
"""
start = None
end = None
if timerange:
if timerange.starttype == 'date':
start = datetime.fromtimestamp(timerange.startts, tz=timezone.utc)
if timerange.stoptype == 'date':
end = datetime.fromtimestamp(timerange.stopts, tz=timezone.utc)
# Intentionally don't pass timerange in - since we need to load the full dataset.
data = data_handler.ohlcv_load(pair, timeframe=timeframe,
@@ -160,14 +170,17 @@ def _load_cached_data_for_updating(
drop_incomplete=True, warn_no_data=False,
candle_type=candle_type)
if not data.empty:
if start and start < data.iloc[0]['date']:
if not prepend and start and start < data.iloc[0]['date']:
# Earlier data than existing data requested, redownload all
data = DataFrame(columns=DEFAULT_DATAFRAME_COLUMNS)
else:
if prepend:
end = data.iloc[0]['date']
else:
start = data.iloc[-1]['date']
start_ms = int(start.timestamp() * 1000) if start else None
return data, start_ms
end_ms = int(end.timestamp() * 1000) if end else None
return data, start_ms, end_ms
def _download_pair_history(pair: str, *,
@@ -180,6 +193,7 @@ def _download_pair_history(pair: str, *,
timerange: Optional[TimeRange] = None,
candle_type: CandleType,
erase: bool = False,
prepend: bool = False,
) -> bool:
"""
Download latest candles from the exchange for the pair and timeframe passed in parameters
@@ -187,8 +201,6 @@ def _download_pair_history(pair: str, *,
exists in a cache. If timerange starts earlier than the data in the cache,
the full data will be redownloaded
Based on @Rybolov work: https://github.com/rybolov/freqtrade-data
:param pair: pair to download
:param timeframe: Timeframe (e.g "5m")
:param timerange: range of time to download
@@ -203,14 +215,17 @@ def _download_pair_history(pair: str, *,
if data_handler.ohlcv_purge(pair, timeframe, candle_type=candle_type):
logger.info(f'Deleting existing data for pair {pair}, {timeframe}, {candle_type}.')
logger.info(
f'Download history data for pair: "{pair}" ({process}), timeframe: {timeframe}, '
f'candle type: {candle_type} and store in {datadir}.'
)
data, since_ms = _load_cached_data_for_updating(pair, timeframe, timerange,
data, since_ms, until_ms = _load_cached_data_for_updating(
pair, timeframe, timerange,
data_handler=data_handler,
candle_type=candle_type)
candle_type=candle_type,
prepend=prepend)
logger.info(f'({process}) - Download history data for "{pair}", {timeframe}, '
f'{candle_type} and store in {datadir}. '
f'From {format_ms_time(since_ms) if since_ms else "start"} to '
f'{format_ms_time(until_ms) if until_ms else "now"}'
)
logger.debug("Current Start: %s",
f"{data.iloc[0]['date']:%Y-%m-%d %H:%M:%S}" if not data.empty else 'None')
@@ -225,6 +240,7 @@ def _download_pair_history(pair: str, *,
days=-new_pairs_days).int_timestamp * 1000,
is_new_pair=data.empty,
candle_type=candle_type,
until_ms=until_ms if until_ms else None
)
# TODO: Maybe move parsing to exchange class (?)
new_dataframe = ohlcv_to_dataframe(new_data, timeframe, pair,
@@ -257,6 +273,7 @@ def refresh_backtest_ohlcv_data(exchange: Exchange, pairs: List[str], timeframes
timerange: Optional[TimeRange] = None,
new_pairs_days: int = 30, erase: bool = False,
data_format: str = None,
prepend: bool = False,
) -> List[str]:
"""
Refresh stored ohlcv data for backtesting and hyperopt operations.
@@ -266,6 +283,7 @@ def refresh_backtest_ohlcv_data(exchange: Exchange, pairs: List[str], timeframes
pairs_not_available = []
data_handler = get_datahandler(datadir, data_format)
candle_type = CandleType.get_default(trading_mode)
process = ''
for idx, pair in enumerate(pairs, start=1):
if pair not in exchange.markets:
pairs_not_available.append(pair)
@@ -280,7 +298,7 @@ def refresh_backtest_ohlcv_data(exchange: Exchange, pairs: List[str], timeframes
timerange=timerange, data_handler=data_handler,
timeframe=str(timeframe), new_pairs_days=new_pairs_days,
candle_type=candle_type,
erase=erase)
erase=erase, prepend=prepend)
if trading_mode == 'futures':
# Predefined candletype (and timeframe) depending on exchange
# Downloads what is necessary to backtest based on futures data.
@@ -294,7 +312,7 @@ def refresh_backtest_ohlcv_data(exchange: Exchange, pairs: List[str], timeframes
timerange=timerange, data_handler=data_handler,
timeframe=str(tf_mark), new_pairs_days=new_pairs_days,
candle_type=funding_candle_type,
erase=erase)
erase=erase, prepend=prepend)
return pairs_not_available
@@ -312,7 +330,8 @@ def _download_trades_history(exchange: Exchange,
try:
until = None
if (timerange and timerange.starttype == 'date'):
if timerange:
if timerange.starttype == 'date':
since = timerange.startts * 1000
if timerange.stoptype == 'date':
until = timerange.stopts * 1000

View File

@@ -5,7 +5,7 @@ It's subclasses handle and storing data from disk.
"""
import logging
import re
from abc import ABC, abstractclassmethod, abstractmethod
from abc import ABC, abstractmethod
from copy import deepcopy
from datetime import datetime, timezone
from pathlib import Path
@@ -26,7 +26,7 @@ logger = logging.getLogger(__name__)
class IDataHandler(ABC):
_OHLCV_REGEX = r'^([a-zA-Z_-]+)\-(\d+\S)\-?([a-zA-Z_]*)?(?=\.)'
_OHLCV_REGEX = r'^([a-zA-Z_-]+)\-(\d+[a-zA-Z]{1,2})\-?([a-zA-Z_]*)?(?=\.)'
def __init__(self, datadir: Path) -> None:
self._datadir = datadir
@@ -38,17 +38,30 @@ class IDataHandler(ABC):
"""
raise NotImplementedError()
@abstractclassmethod
@classmethod
def ohlcv_get_available_data(
cls, datadir: Path, trading_mode: TradingMode) -> ListPairsWithTimeframes:
"""
Returns a list of all pairs with ohlcv data available in this datadir
:param datadir: Directory to search for ohlcv files
:param trading_mode: trading-mode to be used
:return: List of Tuples of (pair, timeframe)
:return: List of Tuples of (pair, timeframe, CandleType)
"""
if trading_mode == TradingMode.FUTURES:
datadir = datadir.joinpath('futures')
_tmp = [
re.search(
cls._OHLCV_REGEX, p.name
) for p in datadir.glob(f"*.{cls._get_file_extension()}")]
return [
(
cls.rebuild_pair_from_filename(match[1]),
cls.rebuild_timeframe_from_filename(match[2]),
CandleType.from_string(match[3])
) for match in _tmp if match and len(match.groups()) > 1]
@abstractclassmethod
@classmethod
@abstractmethod
def ohlcv_get_pairs(cls, datadir: Path, timeframe: str, candle_type: CandleType) -> List[str]:
"""
Returns a list of all pairs with ohlcv data available in this datadir
@@ -118,7 +131,8 @@ class IDataHandler(ABC):
:param candle_type: Any of the enum CandleType (must match trading mode!)
"""
@abstractclassmethod
@classmethod
@abstractmethod
def trades_get_pairs(cls, datadir: Path) -> List[str]:
"""
Returns a list of all pairs for which trade data is available in this
@@ -190,10 +204,14 @@ class IDataHandler(ABC):
datadir: Path,
pair: str,
timeframe: str,
candle_type: CandleType
candle_type: CandleType,
no_timeframe_modify: bool = False
) -> Path:
pair_s = misc.pair_to_filename(pair)
candle = ""
if not no_timeframe_modify:
timeframe = cls.timeframe_to_file(timeframe)
if candle_type != CandleType.SPOT:
datadir = datadir.joinpath('futures')
candle = f"-{candle_type}"
@@ -207,6 +225,18 @@ class IDataHandler(ABC):
filename = datadir.joinpath(f'{pair_s}-trades.{cls._get_file_extension()}')
return filename
@staticmethod
def timeframe_to_file(timeframe: str):
return timeframe.replace('M', 'Mo')
@staticmethod
def rebuild_timeframe_from_filename(timeframe: str) -> str:
"""
converts timeframe from disk to file
Replaces mo with M (to avoid problems on case-insensitive filesystems)
"""
return re.sub('1mo', '1M', timeframe, flags=re.IGNORECASE)
@staticmethod
def rebuild_pair_from_filename(pair: str) -> str:
"""

View File

@@ -8,9 +8,9 @@ from pandas import DataFrame, read_json, to_datetime
from freqtrade import misc
from freqtrade.configuration import TimeRange
from freqtrade.constants import DEFAULT_DATAFRAME_COLUMNS, ListPairsWithTimeframes, TradeList
from freqtrade.constants import DEFAULT_DATAFRAME_COLUMNS, TradeList
from freqtrade.data.converter import trades_dict_to_list
from freqtrade.enums import CandleType, TradingMode
from freqtrade.enums import CandleType
from .idatahandler import IDataHandler
@@ -23,28 +23,6 @@ class JsonDataHandler(IDataHandler):
_use_zip = False
_columns = DEFAULT_DATAFRAME_COLUMNS
@classmethod
def ohlcv_get_available_data(
cls, datadir: Path, trading_mode: TradingMode) -> ListPairsWithTimeframes:
"""
Returns a list of all pairs with ohlcv data available in this datadir
:param datadir: Directory to search for ohlcv files
:param trading_mode: trading-mode to be used
:return: List of Tuples of (pair, timeframe)
"""
if trading_mode == 'futures':
datadir = datadir.joinpath('futures')
_tmp = [
re.search(
cls._OHLCV_REGEX, p.name
) for p in datadir.glob(f"*.{cls._get_file_extension()}")]
return [
(
cls.rebuild_pair_from_filename(match[1]),
match[2],
CandleType.from_string(match[3])
) for match in _tmp if match and len(match.groups()) > 1]
@classmethod
def ohlcv_get_pairs(cls, datadir: Path, timeframe: str, candle_type: CandleType) -> List[str]:
"""
@@ -103,7 +81,12 @@ class JsonDataHandler(IDataHandler):
:param candle_type: Any of the enum CandleType (must match trading mode!)
:return: DataFrame with ohlcv data, or empty DataFrame
"""
filename = self._pair_data_filename(self._datadir, pair, timeframe, candle_type=candle_type)
filename = self._pair_data_filename(
self._datadir, pair, timeframe, candle_type=candle_type)
if not filename.exists():
# Fallback mode for 1M files
filename = self._pair_data_filename(
self._datadir, pair, timeframe, candle_type=candle_type, no_timeframe_modify=True)
if not filename.exists():
return DataFrame(columns=self._columns)
try:

View File

@@ -72,18 +72,28 @@ def create_cum_profit(df: pd.DataFrame, trades: pd.DataFrame, col_name: str,
return df
def _calc_drawdown_series(profit_results: pd.DataFrame, *, date_col: str, value_col: str
) -> pd.DataFrame:
def _calc_drawdown_series(profit_results: pd.DataFrame, *, date_col: str, value_col: str,
starting_balance: float) -> pd.DataFrame:
max_drawdown_df = pd.DataFrame()
max_drawdown_df['cumulative'] = profit_results[value_col].cumsum()
max_drawdown_df['high_value'] = max_drawdown_df['cumulative'].cummax()
max_drawdown_df['drawdown'] = max_drawdown_df['cumulative'] - max_drawdown_df['high_value']
max_drawdown_df['date'] = profit_results.loc[:, date_col]
if starting_balance:
cumulative_balance = starting_balance + max_drawdown_df['cumulative']
max_balance = starting_balance + max_drawdown_df['high_value']
max_drawdown_df['drawdown_relative'] = ((max_balance - cumulative_balance) / max_balance)
else:
# NOTE: This is not completely accurate,
# but might good enough if starting_balance is not available
max_drawdown_df['drawdown_relative'] = (
(max_drawdown_df['high_value'] - max_drawdown_df['cumulative'])
/ max_drawdown_df['high_value'])
return max_drawdown_df
def calculate_underwater(trades: pd.DataFrame, *, date_col: str = 'close_date',
value_col: str = 'profit_ratio'
value_col: str = 'profit_ratio', starting_balance: float = 0.0
):
"""
Calculate max drawdown and the corresponding close dates
@@ -97,13 +107,18 @@ def calculate_underwater(trades: pd.DataFrame, *, date_col: str = 'close_date',
if len(trades) == 0:
raise ValueError("Trade dataframe empty.")
profit_results = trades.sort_values(date_col).reset_index(drop=True)
max_drawdown_df = _calc_drawdown_series(profit_results, date_col=date_col, value_col=value_col)
max_drawdown_df = _calc_drawdown_series(
profit_results,
date_col=date_col,
value_col=value_col,
starting_balance=starting_balance)
return max_drawdown_df
def calculate_max_drawdown(trades: pd.DataFrame, *, date_col: str = 'close_date',
value_col: str = 'profit_abs', starting_balance: float = 0
value_col: str = 'profit_abs', starting_balance: float = 0,
relative: bool = False
) -> Tuple[float, pd.Timestamp, pd.Timestamp, float, float, float]:
"""
Calculate max drawdown and the corresponding close dates
@@ -119,9 +134,15 @@ def calculate_max_drawdown(trades: pd.DataFrame, *, date_col: str = 'close_date'
if len(trades) == 0:
raise ValueError("Trade dataframe empty.")
profit_results = trades.sort_values(date_col).reset_index(drop=True)
max_drawdown_df = _calc_drawdown_series(profit_results, date_col=date_col, value_col=value_col)
max_drawdown_df = _calc_drawdown_series(
profit_results,
date_col=date_col,
value_col=value_col,
starting_balance=starting_balance
)
idxmin = max_drawdown_df['drawdown'].idxmin()
idxmin = max_drawdown_df['drawdown_relative'].idxmax() if relative \
else max_drawdown_df['drawdown'].idxmin()
if idxmin == 0:
raise ValueError("No losing trade, therefore no drawdown.")
high_date = profit_results.loc[max_drawdown_df.iloc[:idxmin]['high_value'].idxmax(), date_col]
@@ -129,12 +150,10 @@ def calculate_max_drawdown(trades: pd.DataFrame, *, date_col: str = 'close_date'
high_val = max_drawdown_df.loc[max_drawdown_df.iloc[:idxmin]
['high_value'].idxmax(), 'cumulative']
low_val = max_drawdown_df.loc[idxmin, 'cumulative']
max_drawdown_rel = 0.0
if high_val + starting_balance != 0:
max_drawdown_rel = (high_val - low_val) / (high_val + starting_balance)
max_drawdown_rel = max_drawdown_df.loc[idxmin, 'drawdown_relative']
return (
abs(min(max_drawdown_df['drawdown'])),
abs(max_drawdown_df.loc[idxmin, 'drawdown']),
high_date,
low_date,
high_val,

View File

@@ -15,3 +15,9 @@ class ExitCheckTuple:
@property
def exit_flag(self):
return self.exit_type != ExitType.NONE
def __eq__(self, other):
return self.exit_type == other.exit_type and self.exit_reason == other.exit_reason
def __repr__(self):
return f"ExitCheckTuple({self.exit_type}, {self.exit_reason})"

View File

@@ -9,10 +9,12 @@ class ExitType(Enum):
STOP_LOSS = "stop_loss"
STOPLOSS_ON_EXCHANGE = "stoploss_on_exchange"
TRAILING_STOP_LOSS = "trailing_stop_loss"
LIQUIDATION = "liquidation"
EXIT_SIGNAL = "exit_signal"
FORCE_EXIT = "force_exit"
EMERGENCY_EXIT = "emergency_exit"
CUSTOM_EXIT = "custom_exit"
PARTIAL_EXIT = "partial_exit"
NONE = ""
def __str__(self):

View File

@@ -17,6 +17,8 @@ class RPCMessageType(Enum):
PROTECTION_TRIGGER = 'protection_trigger'
PROTECTION_TRIGGER_GLOBAL = 'protection_trigger_global'
STRATEGY_MSG = 'strategy_msg'
def __repr__(self):
return self.value

View File

@@ -9,12 +9,13 @@ from freqtrade.exchange.bitpanda import Bitpanda
from freqtrade.exchange.bittrex import Bittrex
from freqtrade.exchange.bybit import Bybit
from freqtrade.exchange.coinbasepro import Coinbasepro
from freqtrade.exchange.exchange import (available_exchanges, ccxt_exchanges,
is_exchange_known_ccxt, is_exchange_officially_supported,
market_is_active, timeframe_to_minutes, timeframe_to_msecs,
timeframe_to_next_date, timeframe_to_prev_date,
timeframe_to_seconds, validate_exchange,
validate_exchanges)
from freqtrade.exchange.exchange import (amount_to_precision, available_exchanges, ccxt_exchanges,
date_minus_candles, is_exchange_known_ccxt,
is_exchange_officially_supported, 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)
from freqtrade.exchange.ftx import Ftx
from freqtrade.exchange.gateio import Gateio
from freqtrade.exchange.hitbtc import Hitbtc

View File

@@ -52,12 +52,17 @@ class Binance(Exchange):
ordertype = 'stop' if self.trading_mode == TradingMode.FUTURES else 'stop_loss_limit'
return order['type'] == ordertype and (
(side == "sell" and stop_loss > float(order['info']['stopPrice'])) or
(side == "buy" and stop_loss < float(order['info']['stopPrice']))
return (
order.get('stopPrice', None) is None
or (
order['type'] == ordertype
and (
(side == "sell" and stop_loss > float(order['stopPrice'])) or
(side == "buy" and stop_loss < float(order['stopPrice']))
)
))
def get_tickers(self, symbols: List[str] = None, cached: bool = False) -> Dict:
def get_tickers(self, symbols: Optional[List[str]] = None, cached: bool = False) -> Dict:
tickers = super().get_tickers(symbols=symbols, cached=cached)
if self.trading_mode == TradingMode.FUTURES:
# Binance's future result has no bid/ask values.
@@ -95,6 +100,7 @@ class Binance(Exchange):
async def _async_get_historic_ohlcv(self, pair: str, timeframe: str,
since_ms: int, candle_type: CandleType,
is_new_pair: bool = False, raise_: bool = False,
until_ms: Optional[int] = None
) -> Tuple[str, str, str, List]:
"""
Overwrite to introduce "fast new pair" functionality by detecting the pair's listing date
@@ -115,7 +121,8 @@ class Binance(Exchange):
since_ms=since_ms,
is_new_pair=is_new_pair,
raise_=raise_,
candle_type=candle_type
candle_type=candle_type,
until_ms=until_ms,
)
def funding_fee_cutoff(self, open_date: datetime):

File diff suppressed because it is too large Load Diff

View File

@@ -29,3 +29,17 @@ class Bybit(Exchange):
# (TradingMode.FUTURES, MarginMode.CROSS),
# (TradingMode.FUTURES, MarginMode.ISOLATED)
]
@property
def _ccxt_config(self) -> Dict:
# Parameters to add directly to ccxt sync/async initialization.
# ccxt defaults to swap mode.
config = {}
if self.trading_mode == TradingMode.SPOT:
config.update({
"options": {
"defaultType": "spot"
}
})
config.update(super()._ccxt_config)
return config

View File

@@ -2,6 +2,7 @@ import asyncio
import logging
import time
from functools import wraps
from typing import Any, Callable, Optional, TypeVar, cast, overload
from freqtrade.exceptions import DDosProtection, RetryableOrderError, TemporaryError
from freqtrade.mixins import LoggingMixin
@@ -11,6 +12,14 @@ logger = logging.getLogger(__name__)
__logging_mixin = None
def _reset_logging_mixin():
"""
Reset global logging mixin - used in tests only.
"""
global __logging_mixin
__logging_mixin = LoggingMixin(logger)
def _get_logging_mixin():
# Logging-mixin to cache kucoin responses
# Only to be used in retrier
@@ -37,6 +46,7 @@ MAP_EXCHANGE_CHILDCLASS = {
'binanceje': 'binance',
'binanceusdm': 'binance',
'okex': 'okx',
'gate': 'gateio',
}
SUPPORTED_EXCHANGES = [
@@ -54,17 +64,16 @@ EXCHANGE_HAS_REQUIRED = [
'fetchOrder',
'cancelOrder',
'createOrder',
# 'createLimitOrder', 'createMarketOrder',
'fetchBalance',
# Public endpoints
'loadMarkets',
'fetchOHLCV',
]
EXCHANGE_HAS_OPTIONAL = [
# Private
'fetchMyTrades', # Trades for order - fee detection
'createLimitOrder', 'createMarketOrder', # Either OR for orders
# 'setLeverage', # Margin/Futures trading
# 'setMarginMode', # Margin/Futures trading
# 'fetchFundingHistory', # Futures trading
@@ -133,8 +142,22 @@ def retrier_async(f):
return wrapper
def retrier(_func=None, retries=API_RETRY_COUNT):
def decorator(f):
F = TypeVar('F', bound=Callable[..., Any])
# Type shenanigans
@overload
def retrier(_func: F) -> F:
...
@overload
def retrier(*, retries=API_RETRY_COUNT) -> Callable[[F], F]:
...
def retrier(_func: Optional[F] = None, *, retries=API_RETRY_COUNT):
def decorator(f: F) -> F:
@wraps(f)
def wrapper(*args, **kwargs):
count = kwargs.pop('count', retries)
@@ -155,7 +178,7 @@ def retrier(_func=None, retries=API_RETRY_COUNT):
else:
logger.warning(msg + 'Giving up.')
raise ex
return wrapper
return cast(F, wrapper)
# Support both @retrier and @retrier(retries=2) syntax
if _func is None:
return decorator

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,10 @@
""" FTX exchange subclass """
import logging
from typing import Any, Dict, List, Tuple
from typing import Any, Dict, List, Optional, Tuple
import ccxt
from freqtrade.constants import BuySell
from freqtrade.enums import MarginMode, TradingMode
from freqtrade.exceptions import (DDosProtection, InsufficientFundsError, InvalidOrderException,
OperationalException, TemporaryError)
@@ -44,7 +45,7 @@ class Ftx(Exchange):
@retrier(retries=0)
def stoploss(self, pair: str, amount: float, stop_price: float,
order_types: Dict, side: str, leverage: float) -> Dict:
order_types: Dict, side: BuySell, leverage: float) -> Dict:
"""
Creates a stoploss order.
depending on order_types.stoploss configuration, uses 'market' or limit order.
@@ -103,7 +104,7 @@ class Ftx(Exchange):
raise OperationalException(e) from e
@retrier(retries=API_FETCH_ORDER_RETRY_COUNT)
def fetch_stoploss_order(self, order_id: str, pair: str) -> Dict:
def fetch_stoploss_order(self, order_id: str, pair: str, params: Dict = {}) -> Dict:
if self._config['dry_run']:
return self.fetch_dry_run_order(order_id)
@@ -115,9 +116,17 @@ class Ftx(Exchange):
if len(order) == 1:
if order[0].get('status') == 'closed':
# Trigger order was triggered ...
real_order_id = order[0].get('info', {}).get('orderId')
real_order_id: Optional[str] = order[0].get('info', {}).get('orderId')
# OrderId may be None for stoploss-market orders
# But contains "average" in these cases.
# So we need to get it through the endpoint
# /conditional_orders/{conditional_order_id}/triggers
if not real_order_id:
res = self._api.privateGetConditionalOrdersConditionalOrderIdTriggers(
params={'conditional_order_id': order_id})
self._log_exchange_response('fetch_stoploss_order2', res)
real_order_id = res['result'][0]['orderId'] if res.get(
'result', []) else None
if real_order_id:
order1 = self._api.fetch_order(real_order_id, pair)
self._log_exchange_response('fetch_stoploss_order1', order1)
@@ -144,7 +153,7 @@ class Ftx(Exchange):
raise OperationalException(e) from e
@retrier
def cancel_stoploss_order(self, order_id: str, pair: str) -> Dict:
def cancel_stoploss_order(self, order_id: str, pair: str, params: Dict = {}) -> Dict:
if self._config['dry_run']:
return {}
try:

View File

@@ -1,11 +1,13 @@
""" Gate.io exchange subclass """
import logging
from datetime import datetime
from typing import Dict, List, Optional, Tuple
from typing import Any, Dict, List, Optional, Tuple
from freqtrade.constants import BuySell
from freqtrade.enums import MarginMode, TradingMode
from freqtrade.exceptions import OperationalException
from freqtrade.exchange import Exchange
from freqtrade.misc import safe_value_fallback2
logger = logging.getLogger(__name__)
@@ -24,12 +26,17 @@ class Gateio(Exchange):
_ft_has: Dict = {
"ohlcv_candle_limit": 1000,
"ohlcv_volume_currency": "quote",
"time_in_force_parameter": "timeInForce",
"order_time_in_force": ['gtc', 'ioc'],
"stoploss_order_types": {"limit": "limit"},
"stoploss_on_exchange": True,
}
_ft_has_futures: Dict = {
"needs_trading_fees": True
"needs_trading_fees": True,
"ohlcv_volume_currency": "base",
"fee_cost_in_contracts": False, # Set explicitly to false for clarity
"order_props_in_contracts": ['amount', 'filled', 'remaining'],
}
_supported_trading_mode_margin_pairs: List[Tuple[TradingMode, MarginMode]] = [
@@ -40,13 +47,33 @@ class Gateio(Exchange):
]
def validate_ordertypes(self, order_types: Dict) -> None:
super().validate_ordertypes(order_types)
if self.trading_mode != TradingMode.FUTURES:
if any(v == 'market' for k, v in order_types.items()):
raise OperationalException(
f'Exchange {self.name} does not support market orders.')
def _get_params(
self,
side: BuySell,
ordertype: str,
leverage: float,
reduceOnly: bool,
time_in_force: str = 'gtc',
) -> Dict:
params = super()._get_params(
side=side,
ordertype=ordertype,
leverage=leverage,
reduceOnly=reduceOnly,
time_in_force=time_in_force,
)
if ordertype == 'market' and self.trading_mode == TradingMode.FUTURES:
params['type'] = 'market'
param = self._ft_has.get('time_in_force_parameter', '')
params.update({param: 'ioc'})
return params
def get_trades_for_order(self, order_id: str, pair: str, since: datetime,
params: Optional[Dict] = None) -> List:
trades = super().get_trades_for_order(order_id, pair, since, params)
@@ -61,7 +88,8 @@ class Gateio(Exchange):
pair_fees = self._trading_fees.get(pair, {})
if pair_fees:
for idx, trade in enumerate(trades):
if trade.get('fee', {}).get('cost') is None:
fee = trade.get('fee', {})
if fee and fee.get('cost') is None:
takerOrMaker = trade.get('takerOrMaker', 'taker')
if pair_fees.get(takerOrMaker) is not None:
trades[idx]['fee'] = {
@@ -71,14 +99,31 @@ class Gateio(Exchange):
}
return trades
def fetch_stoploss_order(self, order_id: str, pair: str, params={}) -> Dict:
return self.fetch_order(
def get_order_id_conditional(self, order: Dict[str, Any]) -> str:
if self.trading_mode == TradingMode.FUTURES:
return safe_value_fallback2(order, order, 'id_stop', 'id')
return order['id']
def fetch_stoploss_order(self, order_id: str, pair: str, params: Dict = {}) -> Dict:
order = self.fetch_order(
order_id=order_id,
pair=pair,
params={'stop': True}
)
if self.trading_mode == TradingMode.FUTURES:
if order['status'] == 'closed':
# Places a real order - which we need to fetch explicitly.
new_orderid = order.get('info', {}).get('trade_id')
if new_orderid:
order1 = self.fetch_order(order_id=new_orderid, pair=pair, params=params)
order1['id_stop'] = order1['id']
order1['id'] = order_id
order1['stopPrice'] = order.get('stopPrice')
def cancel_stoploss_order(self, order_id: str, pair: str, params={}) -> Dict:
return order1
return order
def cancel_stoploss_order(self, order_id: str, pair: str, params: Dict = {}) -> Dict:
return self.cancel_order(
order_id=order_id,
pair=pair,
@@ -90,5 +135,7 @@ class Gateio(Exchange):
Verify stop_loss against stoploss-order value (limit or price)
Returns True if adjustment is necessary.
"""
return ((side == "sell" and stop_loss > float(order['stopPrice'])) or
(side == "buy" and stop_loss < float(order['stopPrice'])))
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']))
)

View File

@@ -27,7 +27,13 @@ class Huobi(Exchange):
Verify stop_loss against stoploss-order value (limit or price)
Returns True if adjustment is necessary.
"""
return order['type'] == 'stop' and stop_loss > float(order['stopPrice'])
return (
order.get('stopPrice', None) is None
or (
order['type'] == 'stop'
and stop_loss > float(order['stopPrice'])
)
)
def _get_stop_params(self, ordertype: str, stop_price: float) -> Dict:

View File

@@ -6,6 +6,7 @@ from typing import Any, Dict, List, Optional, Tuple
import ccxt
from pandas import DataFrame
from freqtrade.constants import BuySell
from freqtrade.enums import MarginMode, TradingMode
from freqtrade.exceptions import (DDosProtection, InsufficientFundsError, InvalidOrderException,
OperationalException, TemporaryError)
@@ -22,6 +23,7 @@ class Kraken(Exchange):
_ft_has: Dict = {
"stoploss_on_exchange": True,
"ohlcv_candle_limit": 720,
"ohlcv_has_history": False,
"trades_pagination": "id",
"trades_pagination_arg": "since",
"mark_ohlcv_timeframe": "4h",
@@ -43,7 +45,7 @@ class Kraken(Exchange):
return (parent_check and
market.get('darkpool', False) is False)
def get_tickers(self, symbols: List[str] = None, cached: bool = False) -> Dict:
def get_tickers(self, symbols: Optional[List[str]] = None, cached: bool = False) -> Dict:
# Only fetch tickers for current stake currency
# Otherwise the request for kraken becomes too large.
symbols = list(self.get_markets(quote_currencies=[self._config['stake_currency']]))
@@ -95,7 +97,7 @@ class Kraken(Exchange):
@retrier(retries=0)
def stoploss(self, pair: str, amount: float, stop_price: float,
order_types: Dict, side: str, leverage: float) -> Dict:
order_types: Dict, side: BuySell, leverage: float) -> Dict:
"""
Creates a stoploss market order.
Stoploss market orders is the only stoploss type supported by kraken.
@@ -165,12 +167,14 @@ class Kraken(Exchange):
def _get_params(
self,
side: BuySell,
ordertype: str,
leverage: float,
reduceOnly: bool,
time_in_force: str = 'gtc'
) -> Dict:
params = super()._get_params(
side=side,
ordertype=ordertype,
leverage=leverage,
reduceOnly=reduceOnly,

View File

@@ -33,7 +33,10 @@ class Kucoin(Exchange):
Verify stop_loss against stoploss-order value (limit or price)
Returns True if adjustment is necessary.
"""
return order['info'].get('stop') is not None and stop_loss > float(order['stopPrice'])
return (
order.get('stopPrice', None) is None
or stop_loss > float(order['stopPrice'])
)
def _get_stop_params(self, ordertype: str, stop_price: float) -> Dict:

View File

@@ -1,11 +1,13 @@
import logging
from typing import Dict, List, Tuple
from typing import Dict, List, Optional, Tuple
import ccxt
from freqtrade.constants import BuySell
from freqtrade.enums import MarginMode, TradingMode
from freqtrade.enums.candletype import CandleType
from freqtrade.exceptions import DDosProtection, OperationalException, TemporaryError
from freqtrade.exchange import Exchange
from freqtrade.exchange import Exchange, date_minus_candles
from freqtrade.exchange.common import retrier
@@ -19,12 +21,13 @@ class Okx(Exchange):
"""
_ft_has: Dict = {
"ohlcv_candle_limit": 300,
"ohlcv_candle_limit": 100, # Warning, special case with data prior to X months
"mark_ohlcv_timeframe": "4h",
"funding_fee_timeframe": "8h",
}
_ft_has_futures: Dict = {
"tickers_have_quoteVolume": False,
"fee_cost_in_contracts": True,
}
_supported_trading_mode_margin_pairs: List[Tuple[TradingMode, MarginMode]] = [
@@ -34,14 +37,69 @@ class Okx(Exchange):
(TradingMode.FUTURES, MarginMode.ISOLATED),
]
net_only = True
def ohlcv_candle_limit(
self, timeframe: str, candle_type: CandleType, since_ms: Optional[int] = None) -> int:
"""
Exchange ohlcv candle limit
OKX has the following behaviour:
* 300 candles for uptodate data
* 100 candles for historic data
* 100 candles for additional candles (not futures or spot).
:param timeframe: Timeframe to check
:param candle_type: Candle-type
:param since_ms: Starting timestamp
:return: Candle limit as integer
"""
if (
candle_type in (CandleType.FUTURES, CandleType.SPOT) and
(not since_ms or since_ms > (date_minus_candles(timeframe, 300).timestamp() * 1000))
):
return 300
return super().ohlcv_candle_limit(timeframe, candle_type, since_ms)
@retrier
def additional_exchange_init(self) -> None:
"""
Additional exchange initialization logic.
.api will be available at this point.
Must be overridden in child methods if required.
"""
try:
if self.trading_mode == TradingMode.FUTURES and not self._config['dry_run']:
accounts = self._api.fetch_accounts()
if len(accounts) > 0:
self.net_only = accounts[0].get('info', {}).get('posMode') == 'net_mode'
except ccxt.DDoSProtection as e:
raise DDosProtection(e) from e
except (ccxt.NetworkError, ccxt.ExchangeError) as e:
raise TemporaryError(
f'Could not set leverage due to {e.__class__.__name__}. Message: {e}') from e
except ccxt.BaseError as e:
raise OperationalException(e) from e
def _get_posSide(self, side: BuySell, reduceOnly: bool):
if self.net_only:
return 'net'
if not reduceOnly:
# Enter
return 'long' if side == 'buy' else 'short'
else:
# Exit
return 'long' if side == 'sell' else 'short'
def _get_params(
self,
side: BuySell,
ordertype: str,
leverage: float,
reduceOnly: bool,
time_in_force: str = 'gtc',
) -> Dict:
params = super()._get_params(
side=side,
ordertype=ordertype,
leverage=leverage,
reduceOnly=reduceOnly,
@@ -49,10 +107,11 @@ class Okx(Exchange):
)
if self.trading_mode == TradingMode.FUTURES and self.margin_mode:
params['tdMode'] = self.margin_mode.value
params['posSide'] = self._get_posSide(side, reduceOnly)
return params
@retrier
def _lev_prep(self, pair: str, leverage: float, side: str):
def _lev_prep(self, pair: str, leverage: float, side: BuySell):
if self.trading_mode != TradingMode.SPOT and self.margin_mode is not None:
try:
# TODO-lev: Test me properly (check mgnMode passed)
@@ -61,7 +120,7 @@ class Okx(Exchange):
symbol=pair,
params={
"mgnMode": self.margin_mode.value,
# "posSide": "net"",
"posSide": self._get_posSide(side, False),
})
except ccxt.DDoSProtection as e:
raise DDosProtection(e) from e

View File

View File

@@ -0,0 +1,609 @@
import collections
import json
import logging
import re
import shutil
import threading
from pathlib import Path
from typing import Any, Dict, Tuple, TypedDict
import numpy as np
import pandas as pd
import rapidjson
from joblib import dump, load
from joblib.externals import cloudpickle
from numpy.typing import NDArray
from pandas import DataFrame
from freqtrade.configuration import TimeRange
from freqtrade.data.history import load_pair_history
from freqtrade.exceptions import OperationalException
from freqtrade.freqai.data_kitchen import FreqaiDataKitchen
from freqtrade.strategy.interface import IStrategy
logger = logging.getLogger(__name__)
class pair_info(TypedDict):
model_filename: str
first: bool
trained_timestamp: int
priority: int
data_path: str
extras: dict
class FreqaiDataDrawer:
"""
Class aimed at holding all pair models/info in memory for better inferencing/retrainig/saving
/loading to/from disk.
This object remains persistent throughout live/dry.
Record of contribution:
FreqAI was developed by a group of individuals who all contributed specific skillsets to the
project.
Conception and software development:
Robert Caulk @robcaulk
Theoretical brainstorming:
Elin Törnquist @th0rntwig
Code review, software architecture brainstorming:
@xmatthias
Beta testing and bug reporting:
@bloodhunter4rc, Salah Lamkadem @ikonx, @ken11o2, @longyu, @paranoidandy, @smidelis, @smarm
Juha Nykänen @suikula, Wagner Costa @wagnercosta, Johan Vlugt @Jooopieeert
"""
def __init__(self, full_path: Path, config: dict, follow_mode: bool = False):
self.config = config
self.freqai_info = config.get("freqai", {})
# dictionary holding all pair metadata necessary to load in from disk
self.pair_dict: Dict[str, pair_info] = {}
# dictionary holding all actively inferenced models in memory given a model filename
self.model_dictionary: Dict[str, Any] = {}
self.model_return_values: Dict[str, DataFrame] = {}
self.historic_data: Dict[str, Dict[str, DataFrame]] = {}
self.historic_predictions: Dict[str, DataFrame] = {}
self.follower_dict: Dict[str, pair_info] = {}
self.full_path = full_path
self.follower_name: str = self.config.get("bot_name", "follower1")
self.follower_dict_path = Path(
self.full_path / f"follower_dictionary-{self.follower_name}.json"
)
self.historic_predictions_path = Path(self.full_path / "historic_predictions.pkl")
self.pair_dictionary_path = Path(self.full_path / "pair_dictionary.json")
self.follow_mode = follow_mode
if follow_mode:
self.create_follower_dict()
self.load_drawer_from_disk()
self.load_historic_predictions_from_disk()
self.training_queue: Dict[str, int] = {}
self.history_lock = threading.Lock()
self.save_lock = threading.Lock()
self.pair_dict_lock = threading.Lock()
self.old_DBSCAN_eps: Dict[str, float] = {}
self.empty_pair_dict: pair_info = {
"model_filename": "", "trained_timestamp": 0,
"priority": 1, "first": True, "data_path": "", "extras": {}}
def load_drawer_from_disk(self):
"""
Locate and load a previously saved data drawer full of all pair model metadata in
present model folder.
:return: bool - whether or not the drawer was located
"""
exists = self.pair_dictionary_path.is_file()
if exists:
with open(self.pair_dictionary_path, "r") as fp:
self.pair_dict = json.load(fp)
elif not self.follow_mode:
logger.info("Could not find existing datadrawer, starting from scratch")
else:
logger.warning(
f"Follower could not find pair_dictionary at {self.full_path} "
"sending null values back to strategy"
)
return exists
def load_historic_predictions_from_disk(self):
"""
Locate and load a previously saved historic predictions.
:return: bool - whether or not the drawer was located
"""
exists = self.historic_predictions_path.is_file()
if exists:
with open(self.historic_predictions_path, "rb") as fp:
self.historic_predictions = cloudpickle.load(fp)
logger.info(
f"Found existing historic predictions at {self.full_path}, but beware "
"that statistics may be inaccurate if the bot has been offline for "
"an extended period of time."
)
elif not self.follow_mode:
logger.info("Could not find existing historic_predictions, starting from scratch")
else:
logger.warning(
f"Follower could not find historic predictions at {self.full_path} "
"sending null values back to strategy"
)
return exists
def save_historic_predictions_to_disk(self):
"""
Save data drawer full of all pair model metadata in present model folder.
"""
with open(self.historic_predictions_path, "wb") as fp:
cloudpickle.dump(self.historic_predictions, fp, protocol=cloudpickle.DEFAULT_PROTOCOL)
def save_drawer_to_disk(self):
"""
Save data drawer full of all pair model metadata in present model folder.
"""
with self.save_lock:
with open(self.pair_dictionary_path, 'w') as fp:
rapidjson.dump(self.pair_dict, fp, default=self.np_encoder,
number_mode=rapidjson.NM_NATIVE)
def save_follower_dict_to_disk(self):
"""
Save follower dictionary to disk (used by strategy for persistent prediction targets)
"""
with open(self.follower_dict_path, "w") as fp:
rapidjson.dump(self.follower_dict, fp, default=self.np_encoder,
number_mode=rapidjson.NM_NATIVE)
def create_follower_dict(self):
"""
Create or dictionary for each follower to maintain unique persistent prediction targets
"""
whitelist_pairs = self.config.get("exchange", {}).get("pair_whitelist")
exists = self.follower_dict_path.is_file()
if exists:
logger.info("Found an existing follower dictionary")
for pair in whitelist_pairs:
self.follower_dict[pair] = {}
self.save_follower_dict_to_disk()
def np_encoder(self, object):
if isinstance(object, np.generic):
return object.item()
def get_pair_dict_info(self, pair: str) -> Tuple[str, int, bool]:
"""
Locate and load existing model metadata from persistent storage. If not located,
create a new one and append the current pair to it and prepare it for its first
training
:param pair: str: pair to lookup
:return:
model_filename: str = unique filename used for loading persistent objects from disk
trained_timestamp: int = the last time the coin was trained
return_null_array: bool = Follower could not find pair metadata
"""
pair_dict = self.pair_dict.get(pair)
data_path_set = self.pair_dict.get(pair, self.empty_pair_dict).get("data_path", "")
return_null_array = False
if pair_dict:
model_filename = pair_dict["model_filename"]
trained_timestamp = pair_dict["trained_timestamp"]
elif not self.follow_mode:
self.pair_dict[pair] = self.empty_pair_dict.copy()
model_filename = ""
trained_timestamp = 0
self.pair_dict[pair]["priority"] = len(self.pair_dict)
if not data_path_set and self.follow_mode:
logger.warning(
f"Follower could not find current pair {pair} in "
f"pair_dictionary at path {self.full_path}, sending null values "
"back to strategy."
)
trained_timestamp = 0
model_filename = ''
return_null_array = True
return model_filename, trained_timestamp, return_null_array
def set_pair_dict_info(self, metadata: dict) -> None:
pair_in_dict = self.pair_dict.get(metadata["pair"])
if pair_in_dict:
return
else:
self.pair_dict[metadata["pair"]] = self.empty_pair_dict.copy()
self.pair_dict[metadata["pair"]]["priority"] = len(self.pair_dict)
return
def pair_to_end_of_training_queue(self, pair: str) -> None:
# march all pairs up in the queue
with self.pair_dict_lock:
for p in self.pair_dict:
self.pair_dict[p]["priority"] -= 1
# send pair to end of queue
self.pair_dict[pair]["priority"] = len(self.pair_dict)
def set_initial_return_values(self, pair: str, pred_df: DataFrame) -> None:
"""
Set the initial return values to the historical predictions dataframe. This avoids needing
to repredict on historical candles, and also stores historical predictions despite
retrainings (so stored predictions are true predictions, not just inferencing on trained
data)
"""
hist_df = self.historic_predictions
len_diff = len(hist_df[pair].index) - len(pred_df.index)
if len_diff < 0:
df_concat = pd.concat([pred_df.iloc[:abs(len_diff)], hist_df[pair]],
ignore_index=True, keys=hist_df[pair].keys())
else:
df_concat = hist_df[pair].tail(len(pred_df.index)).reset_index(drop=True)
df_concat = df_concat.fillna(0)
self.model_return_values[pair] = df_concat
def append_model_predictions(self, pair: str, predictions: DataFrame,
do_preds: NDArray[np.int_],
dk: FreqaiDataKitchen, len_df: int) -> None:
"""
Append model predictions to historic predictions dataframe, then set the
strategy return dataframe to the tail of the historic predictions. The length of
the tail is equivalent to the length of the dataframe that entered FreqAI from
the strategy originally. Doing this allows FreqUI to always display the correct
historic predictions.
"""
index = self.historic_predictions[pair].index[-1:]
columns = self.historic_predictions[pair].columns
nan_df = pd.DataFrame(np.nan, index=index, columns=columns)
self.historic_predictions[pair] = pd.concat(
[self.historic_predictions[pair], nan_df], ignore_index=True, axis=0)
df = self.historic_predictions[pair]
# model outputs and associated statistics
for label in predictions.columns:
df[label].iloc[-1] = predictions[label].iloc[-1]
if df[label].dtype == object:
continue
df[f"{label}_mean"].iloc[-1] = dk.data["labels_mean"][label]
df[f"{label}_std"].iloc[-1] = dk.data["labels_std"][label]
# outlier indicators
df["do_predict"].iloc[-1] = do_preds[-1]
if self.freqai_info["feature_parameters"].get("DI_threshold", 0) > 0:
df["DI_values"].iloc[-1] = dk.DI_values[-1]
# extra values the user added within custom prediction model
if dk.data['extra_returns_per_train']:
rets = dk.data['extra_returns_per_train']
for return_str in rets:
df[return_str].iloc[-1] = rets[return_str]
self.model_return_values[pair] = df.tail(len_df).reset_index(drop=True)
def attach_return_values_to_return_dataframe(
self, pair: str, dataframe: DataFrame) -> DataFrame:
"""
Attach the return values to the strat dataframe
:param dataframe: DataFrame = strategy dataframe
:return: DataFrame = strat dataframe with return values attached
"""
df = self.model_return_values[pair]
to_keep = [col for col in dataframe.columns if not col.startswith("&")]
dataframe = pd.concat([dataframe[to_keep], df], axis=1)
return dataframe
def return_null_values_to_strategy(self, dataframe: DataFrame, dk: FreqaiDataKitchen) -> None:
"""
Build 0 filled dataframe to return to strategy
"""
dk.find_features(dataframe)
full_labels = dk.label_list + dk.unique_class_list
for label in full_labels:
dataframe[label] = 0
dataframe[f"{label}_mean"] = 0
dataframe[f"{label}_std"] = 0
dataframe["do_predict"] = 0
if self.freqai_info["feature_parameters"].get("DI_threshold", 0) > 0:
dataframe["DI_values"] = 0
if dk.data['extra_returns_per_train']:
rets = dk.data['extra_returns_per_train']
for return_str in rets:
dataframe[return_str] = 0
dk.return_dataframe = dataframe
def purge_old_models(self) -> None:
model_folders = [x for x in self.full_path.iterdir() if x.is_dir()]
pattern = re.compile(r"sub-train-(\w+)_(\d{10})")
delete_dict: Dict[str, Any] = {}
for dir in model_folders:
result = pattern.match(str(dir.name))
if result is None:
break
coin = result.group(1)
timestamp = result.group(2)
if coin not in delete_dict:
delete_dict[coin] = {}
delete_dict[coin]["num_folders"] = 1
delete_dict[coin]["timestamps"] = {int(timestamp): dir}
else:
delete_dict[coin]["num_folders"] += 1
delete_dict[coin]["timestamps"][int(timestamp)] = dir
for coin in delete_dict:
if delete_dict[coin]["num_folders"] > 2:
sorted_dict = collections.OrderedDict(
sorted(delete_dict[coin]["timestamps"].items())
)
num_delete = len(sorted_dict) - 2
deleted = 0
for k, v in sorted_dict.items():
if deleted >= num_delete:
break
logger.info(f"Freqai purging old model file {v}")
shutil.rmtree(v)
deleted += 1
def update_follower_metadata(self):
# follower needs to load from disk to get any changes made by leader to pair_dict
self.load_drawer_from_disk()
if self.config.get("freqai", {}).get("purge_old_models", False):
self.purge_old_models()
# Functions pulled back from FreqaiDataKitchen because they relied on DataDrawer
def save_data(self, model: Any, coin: str, dk: FreqaiDataKitchen) -> None:
"""
Saves all data associated with a model for a single sub-train time range
:params:
:model: User trained model which can be reused for inferencing to generate
predictions
"""
if not dk.data_path.is_dir():
dk.data_path.mkdir(parents=True, exist_ok=True)
save_path = Path(dk.data_path)
# Save the trained model
if not dk.keras:
dump(model, save_path / f"{dk.model_filename}_model.joblib")
else:
model.save(save_path / f"{dk.model_filename}_model.h5")
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"] = list(dk.data_dictionary["train_features"].columns)
dk.data["label_list"] = dk.label_list
# store the metadata
with open(save_path / f"{dk.model_filename}_metadata.json", "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
dk.data_dictionary["train_features"].to_pickle(
save_path / f"{dk.model_filename}_trained_df.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, open(dk.data_path / f"{dk.model_filename}_pca_object.pkl", "wb")
)
# if self.live:
self.model_dictionary[dk.model_filename] = model
self.pair_dict[coin]["model_filename"] = dk.model_filename
self.pair_dict[coin]["data_path"] = str(dk.data_path)
self.save_drawer_to_disk()
return
def load_data(self, coin: str, dk: FreqaiDataKitchen) -> Any:
"""
loads all data required to make a prediction on a sub-train time range
:returns:
:model: User trained model which can be inferenced for new predictions
"""
if not self.pair_dict[coin]["model_filename"]:
return None
if dk.live:
dk.model_filename = self.pair_dict[coin]["model_filename"]
dk.data_path = Path(self.pair_dict[coin]["data_path"])
if self.freqai_info.get("follow_mode", False):
# follower can be on a different system which is rsynced from the leader:
dk.data_path = Path(
self.config["user_data_dir"]
/ "models"
/ dk.data_path.parts[-2]
/ dk.data_path.parts[-1]
)
with open(dk.data_path / f"{dk.model_filename}_metadata.json", "r") as fp:
dk.data = json.load(fp)
dk.training_features_list = dk.data["training_features_list"]
dk.label_list = dk.data["label_list"]
dk.data_dictionary["train_features"] = pd.read_pickle(
dk.data_path / f"{dk.model_filename}_trained_df.pkl"
)
# try to access model in memory instead of loading object from disk to save time
if dk.live and dk.model_filename in self.model_dictionary:
model = self.model_dictionary[dk.model_filename]
elif not dk.keras:
model = load(dk.data_path / f"{dk.model_filename}_model.joblib")
else:
from tensorflow import keras
model = keras.models.load_model(dk.data_path / f"{dk.model_filename}_model.h5")
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")
if not model:
raise OperationalException(
f"Unable to load model, ensure model exists at " f"{dk.data_path} "
)
if self.config["freqai"]["feature_parameters"]["principal_component_analysis"]:
dk.pca = cloudpickle.load(
open(dk.data_path / f"{dk.model_filename}_pca_object.pkl", "rb")
)
return model
def update_historic_data(self, strategy: IStrategy, dk: FreqaiDataKitchen) -> None:
"""
Append new candles to our stores historic data (in memory) so that
we do not need to load candle history from disk and we dont need to
pinging exchange multiple times for the same candle.
:params:
dataframe: DataFrame = strategy provided dataframe
"""
feat_params = self.freqai_info["feature_parameters"]
with self.history_lock:
history_data = self.historic_data
for pair in dk.all_pairs:
for tf in feat_params.get("include_timeframes"):
# check if newest candle is already appended
df_dp = strategy.dp.get_pair_dataframe(pair, tf)
if len(df_dp.index) == 0:
continue
if str(history_data[pair][tf].iloc[-1]["date"]) == str(
df_dp.iloc[-1:]["date"].iloc[-1]
):
continue
try:
index = (
df_dp.loc[
df_dp["date"] == history_data[pair][tf].iloc[-1]["date"]
].index[0]
+ 1
)
except IndexError:
logger.warning(
f"Unable to update pair history for {pair}. "
"If this does not resolve itself after 1 additional candle, "
"please report the error to #freqai discord channel"
)
return
history_data[pair][tf] = pd.concat(
[
history_data[pair][tf],
df_dp.iloc[index:],
],
ignore_index=True,
axis=0,
)
def load_all_pair_histories(self, timerange: TimeRange, dk: FreqaiDataKitchen) -> None:
"""
Load pair histories for all whitelist and corr_pairlist pairs.
Only called once upon startup of bot.
:params:
timerange: TimeRange = full timerange required to populate all indicators
for training according to user defined train_period_days
"""
history_data = self.historic_data
for pair in dk.all_pairs:
if pair not in history_data:
history_data[pair] = {}
for tf in self.freqai_info["feature_parameters"].get("include_timeframes"):
history_data[pair][tf] = load_pair_history(
datadir=self.config["datadir"],
timeframe=tf,
pair=pair,
timerange=timerange,
data_format=self.config.get("dataformat_ohlcv", "json"),
candle_type=self.config.get("trading_mode", "spot"),
)
def get_base_and_corr_dataframes(
self, timerange: TimeRange, pair: str, dk: FreqaiDataKitchen
) -> Tuple[Dict[Any, Any], Dict[Any, Any]]:
"""
Searches through our historic_data in memory and returns the dataframes relevant
to the present pair.
:params:
timerange: TimeRange = full timerange required to populate all indicators
for training according to user defined train_period_days
metadata: dict = strategy furnished pair metadata
"""
with self.history_lock:
corr_dataframes: Dict[Any, Any] = {}
base_dataframes: Dict[Any, Any] = {}
historic_data = self.historic_data
pairs = self.freqai_info["feature_parameters"].get(
"include_corr_pairlist", []
)
for tf in self.freqai_info["feature_parameters"].get("include_timeframes"):
base_dataframes[tf] = dk.slice_dataframe(timerange, historic_data[pair][tf])
if pairs:
for p in pairs:
if pair in p:
continue # dont repeat anything from whitelist
if p not in corr_dataframes:
corr_dataframes[p] = {}
corr_dataframes[p][tf] = dk.slice_dataframe(
timerange, historic_data[p][tf]
)
return corr_dataframes, base_dataframes
# to be used if we want to send predictions directly to the follower instead of forcing
# follower to load models and inference
# def save_model_return_values_to_disk(self) -> None:
# with open(self.full_path / str('model_return_values.json'), "w") as fp:
# json.dump(self.model_return_values, fp, default=self.np_encoder)
# def load_model_return_values_from_disk(self, dk: FreqaiDataKitchen) -> FreqaiDataKitchen:
# exists = Path(self.full_path / str('model_return_values.json')).resolve().exists()
# if exists:
# with open(self.full_path / str('model_return_values.json'), "r") as fp:
# self.model_return_values = json.load(fp)
# elif not self.follow_mode:
# logger.info("Could not find existing datadrawer, starting from scratch")
# else:
# logger.warning(f'Follower could not find pair_dictionary at {self.full_path} '
# 'sending null values back to strategy')
# return exists, dk

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,663 @@
# import contextlib
import datetime
import logging
import shutil
import threading
import time
from abc import ABC, abstractmethod
from pathlib import Path
from threading import Lock
from typing import Any, Dict, Tuple
import numpy as np
import pandas as pd
from numpy.typing import NDArray
from pandas import DataFrame
from freqtrade.configuration import TimeRange
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.strategy.interface import IStrategy
pd.options.mode.chained_assignment = None
logger = logging.getLogger(__name__)
def threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs).start()
return wrapper
class IFreqaiModel(ABC):
"""
Class containing all tools for training and prediction in the strategy.
Base*PredictionModels inherit from this class.
Record of contribution:
FreqAI was developed by a group of individuals who all contributed specific skillsets to the
project.
Conception and software development:
Robert Caulk @robcaulk
Theoretical brainstorming:
Elin Törnquist @th0rntwig
Code review, software architecture brainstorming:
@xmatthias
Beta testing and bug reporting:
@bloodhunter4rc, Salah Lamkadem @ikonx, @ken11o2, @longyu, @paranoidandy, @smidelis, @smarm
Juha Nykänen @suikula, Wagner Costa @wagnercosta, Johan Vlugt @Jooopieeert
"""
def __init__(self, config: Dict[str, Any]) -> None:
self.config = config
self.assert_config(self.config)
self.freqai_info: Dict[str, Any] = config["freqai"]
self.data_split_parameters: Dict[str, Any] = config.get("freqai", {}).get(
"data_split_parameters", {})
self.model_training_parameters: Dict[str, Any] = config.get("freqai", {}).get(
"model_training_parameters", {})
self.retrain = False
self.first = True
self.set_full_path()
self.follow_mode: bool = self.freqai_info.get("follow_mode", False)
self.dd = FreqaiDataDrawer(Path(self.full_path), self.config, self.follow_mode)
self.identifier: str = self.freqai_info.get("identifier", "no_id_provided")
self.scanning = False
self.ft_params = self.freqai_info["feature_parameters"]
self.keras: bool = self.freqai_info.get("keras", False)
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", 2)
if self.ft_params.get("inlier_metric_window", 0):
self.CONV_WIDTH = self.ft_params.get("inlier_metric_window", 0) * 2
self.pair_it = 0
self.total_pairs = len(self.config.get("exchange", {}).get("pair_whitelist"))
self.last_trade_database_summary: DataFrame = {}
self.current_trade_database_summary: DataFrame = {}
self.analysis_lock = Lock()
self.inference_time: float = 0
self.begin_time: float = 0
self.base_tf_seconds = timeframe_to_seconds(self.config['timeframe'])
def assert_config(self, config: Dict[str, Any]) -> None:
if not config.get("freqai", {}):
raise OperationalException("No freqai parameters found in configuration file.")
def start(self, dataframe: DataFrame, metadata: dict, strategy: IStrategy) -> DataFrame:
"""
Entry point to the FreqaiModel from a specific pair, it will train a new model if
necessary before making the prediction.
:param dataframe: Full dataframe coming from strategy - it contains entire
backtesting timerange + additional historical data necessary to train
the model.
:param metadata: pair metadata coming from strategy.
:param strategy: Strategy to train on
"""
self.live = strategy.dp.runmode in (RunMode.DRY_RUN, RunMode.LIVE)
self.dd.set_pair_dict_info(metadata)
if self.live:
self.inference_timer('start')
self.dk = FreqaiDataKitchen(self.config, self.live, metadata["pair"])
dk = self.start_live(dataframe, metadata, strategy, self.dk)
# For backtesting, each pair enters and then gets trained for each window along the
# sliding window defined by "train_period_days" (training window) and "live_retrain_hours"
# (backtest window, i.e. window immediately following the training window).
# FreqAI slides the window and sequentially builds the backtesting results before returning
# the concatenated results for the full backtesting period back to the strategy.
elif not self.follow_mode:
self.dk = FreqaiDataKitchen(self.config, self.live, metadata["pair"])
logger.info(f"Training {len(self.dk.training_timeranges)} timeranges")
with self.analysis_lock:
dataframe = self.dk.use_strategy_to_populate_indicators(
strategy, prediction_dataframe=dataframe, pair=metadata["pair"]
)
dk = self.start_backtesting(dataframe, metadata, self.dk)
dataframe = dk.remove_features_from_df(dk.return_dataframe)
del dk
if self.live:
self.inference_timer('stop')
return dataframe
@threaded
def start_scanning(self, strategy: IStrategy) -> None:
"""
Function designed to constantly scan pairs for retraining on a separate thread (intracandle)
to improve model youth. This function is agnostic to data preparation/collection/storage,
it simply trains on what ever data is available in the self.dd.
:param strategy: IStrategy = The user defined strategy class
"""
while 1:
time.sleep(1)
for pair in self.config.get("exchange", {}).get("pair_whitelist"):
(_, trained_timestamp, _) = self.dd.get_pair_dict_info(pair)
if self.dd.pair_dict[pair]["priority"] != 1:
continue
dk = FreqaiDataKitchen(self.config, self.live, pair)
dk.set_paths(pair, trained_timestamp)
(
retrain,
new_trained_timerange,
data_load_timerange,
) = dk.check_if_new_training_required(trained_timestamp)
dk.set_paths(pair, new_trained_timerange.stopts)
if retrain:
self.train_model_in_series(
new_trained_timerange, pair, strategy, dk, data_load_timerange
)
self.dd.save_historic_predictions_to_disk()
def start_backtesting(
self, dataframe: DataFrame, metadata: dict, dk: FreqaiDataKitchen
) -> FreqaiDataKitchen:
"""
The main broad execution for backtesting. For backtesting, each pair enters and then gets
trained for each window along the sliding window defined by "train_period_days"
(training window) and "backtest_period_days" (backtest window, i.e. window immediately
following the training window). FreqAI slides the window and sequentially builds
the backtesting results before returning the concatenated results for the full
backtesting period back to the strategy.
:param dataframe: DataFrame = strategy passed dataframe
:param metadata: Dict = pair metadata
:param dk: FreqaiDataKitchen = Data management/analysis tool associated to present pair only
:return:
FreqaiDataKitchen = Data management/analysis tool associated to present pair only
"""
self.pair_it += 1
train_it = 0
# Loop enforcing the sliding window training/backtesting paradigm
# tr_train is the training time range e.g. 1 historical month
# tr_backtest is the backtesting time range e.g. the week directly
# following tr_train. Both of these windows slide through the
# entire backtest
for tr_train, tr_backtest in zip(dk.training_timeranges, dk.backtesting_timeranges):
(_, _, _) = self.dd.get_pair_dict_info(metadata["pair"])
train_it += 1
total_trains = len(dk.backtesting_timeranges)
self.training_timerange = tr_train
dataframe_train = dk.slice_dataframe(tr_train, dataframe)
dataframe_backtest = dk.slice_dataframe(tr_backtest, dataframe)
trained_timestamp = tr_train
tr_train_startts_str = datetime.datetime.utcfromtimestamp(tr_train.startts).strftime(
"%Y-%m-%d %H:%M:%S"
)
tr_train_stopts_str = datetime.datetime.utcfromtimestamp(tr_train.stopts).strftime(
"%Y-%m-%d %H:%M:%S"
)
logger.info(
f"Training {metadata['pair']}, {self.pair_it}/{self.total_pairs} pairs"
f" from {tr_train_startts_str} to {tr_train_stopts_str}, {train_it}/{total_trains} "
"trains"
)
dk.data_path = Path(
dk.full_path
/
f"sub-train-{metadata['pair'].split('/')[0]}_{int(trained_timestamp.stopts)}"
)
if not self.model_exists(
metadata["pair"], dk, trained_timestamp=int(trained_timestamp.stopts)
):
dk.find_features(dataframe_train)
self.model = self.train(dataframe_train, metadata["pair"], dk)
self.dd.pair_dict[metadata["pair"]]["trained_timestamp"] = int(
trained_timestamp.stopts)
dk.set_new_model_names(metadata["pair"], trained_timestamp)
self.dd.save_data(self.model, metadata["pair"], dk)
else:
self.model = self.dd.load_data(metadata["pair"], dk)
self.check_if_feature_list_matches_strategy(dataframe_train, dk)
pred_df, do_preds = self.predict(dataframe_backtest, dk)
dk.append_predictions(pred_df, do_preds)
dk.fill_predictions(dataframe)
return dk
def start_live(
self, dataframe: DataFrame, metadata: dict, strategy: IStrategy, dk: FreqaiDataKitchen
) -> FreqaiDataKitchen:
"""
The main broad execution for dry/live. This function will check if a retraining should be
performed, and if so, retrain and reset the model.
:param dataframe: DataFrame = strategy passed dataframe
:param metadata: Dict = pair metadata
:param strategy: IStrategy = currently employed strategy
dk: FreqaiDataKitchen = Data management/analysis tool associated to present pair only
:returns:
dk: FreqaiDataKitchen = Data management/analysis tool associated to present pair only
"""
# update follower
if self.follow_mode:
self.dd.update_follower_metadata()
# get the model metadata associated with the current pair
(_, trained_timestamp, return_null_array) = self.dd.get_pair_dict_info(metadata["pair"])
# if the metadata doesn't exist, the follower returns null arrays to strategy
if self.follow_mode and return_null_array:
logger.info("Returning null array from follower to strategy")
self.dd.return_null_values_to_strategy(dataframe, dk)
return dk
# append the historic data once per round
if self.dd.historic_data:
self.dd.update_historic_data(strategy, dk)
logger.debug(f'Updating historic data on pair {metadata["pair"]}')
if not self.follow_mode:
(_, new_trained_timerange, data_load_timerange) = dk.check_if_new_training_required(
trained_timestamp
)
dk.set_paths(metadata["pair"], new_trained_timerange.stopts)
# download candle history if it is not already in memory
if not self.dd.historic_data:
logger.info(
"Downloading all training data for all pairs in whitelist and "
"corr_pairlist, this may take a while if you do not have the "
"data saved"
)
dk.download_all_data_for_training(data_load_timerange, strategy.dp)
self.dd.load_all_pair_histories(data_load_timerange, dk)
if not self.scanning:
self.scanning = True
self.start_scanning(strategy)
elif self.follow_mode:
dk.set_paths(metadata["pair"], trained_timestamp)
logger.info(
"FreqAI instance set to follow_mode, finding existing pair "
f"using { self.identifier }"
)
# load the model and associated data into the data kitchen
self.model = self.dd.load_data(metadata["pair"], dk)
with self.analysis_lock:
dataframe = self.dk.use_strategy_to_populate_indicators(
strategy, prediction_dataframe=dataframe, pair=metadata["pair"]
)
if not self.model:
logger.warning(
f"No model ready for {metadata['pair']}, returning null values to strategy."
)
self.dd.return_null_values_to_strategy(dataframe, dk)
return dk
# ensure user is feeding the correct indicators to the model
self.check_if_feature_list_matches_strategy(dataframe, dk)
self.build_strategy_return_arrays(dataframe, dk, metadata["pair"], trained_timestamp)
return dk
def build_strategy_return_arrays(
self, dataframe: DataFrame, dk: FreqaiDataKitchen, pair: str, trained_timestamp: int
) -> None:
# hold the historical predictions in memory so we are sending back
# correct array to strategy
if pair not in self.dd.model_return_values:
# first predictions are made on entire historical candle set coming from strategy. This
# allows FreqUI to show full return values.
pred_df, do_preds = self.predict(dataframe, dk)
if pair not in self.dd.historic_predictions:
self.set_initial_historic_predictions(pred_df, dk, pair)
self.dd.set_initial_return_values(pair, pred_df)
dk.return_dataframe = self.dd.attach_return_values_to_return_dataframe(pair, dataframe)
return
elif self.dk.check_if_model_expired(trained_timestamp):
pred_df = DataFrame(np.zeros((2, len(dk.label_list))), columns=dk.label_list)
do_preds = np.ones(2, dtype=np.int_) * 2
dk.DI_values = np.zeros(2)
logger.warning(
f"Model expired for {pair}, returning null values to strategy. Strategy "
"construction should take care to consider this event with "
"prediction == 0 and do_predict == 2"
)
else:
# remaining predictions are made only on the most recent candles for performance and
# historical accuracy reasons.
pred_df, do_preds = self.predict(dataframe.iloc[-self.CONV_WIDTH:], dk, first=False)
if self.freqai_info.get('fit_live_predictions_candles', 0) and self.live:
self.fit_live_predictions(dk, pair)
self.dd.append_model_predictions(pair, pred_df, do_preds, dk, len(dataframe))
dk.return_dataframe = self.dd.attach_return_values_to_return_dataframe(pair, dataframe)
return
def check_if_feature_list_matches_strategy(
self, dataframe: DataFrame, dk: FreqaiDataKitchen
) -> None:
"""
Ensure user is passing the proper feature set if they are reusing an `identifier` pointing
to a folder holding existing models.
:param dataframe: DataFrame = strategy provided dataframe
:param dk: FreqaiDataKitchen = non-persistent data container/analyzer for
current coin/bot loop
"""
dk.find_features(dataframe)
if "training_features_list_raw" in dk.data:
feature_list = dk.data["training_features_list_raw"]
else:
feature_list = dk.training_features_list
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"
"model"
)
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.
"""
ft_params = self.freqai_info["feature_parameters"]
if ft_params.get(
"principal_component_analysis", False
):
dk.principal_component_analysis()
if ft_params.get("use_SVM_to_remove_outliers", False):
dk.use_SVM_to_remove_outliers(predict=False)
if ft_params.get("DI_threshold", 0):
dk.data["avg_mean_dist"] = dk.compute_distances()
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']
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 self.freqai_info["feature_parameters"].get('noise_standard_deviation', 0):
dk.add_noise_to_training_features()
def data_cleaning_predict(self, dk: FreqaiDataKitchen, dataframe: DataFrame) -> 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"]
if ft_params.get('inlier_metric_window', 0):
dk.compute_inlier_metric(set_='predict')
if ft_params.get(
"principal_component_analysis", False
):
dk.pca_transform(dataframe)
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)
def model_exists(
self,
pair: str,
dk: FreqaiDataKitchen,
trained_timestamp: int = None,
model_filename: str = "",
scanning: bool = False,
) -> bool:
"""
Given a pair and path, check if a model already exists
:param pair: pair e.g. BTC/USD
:param path: path to model
:return:
:boolean: whether the model file exists or not.
"""
coin, _ = pair.split("/")
if not self.live:
dk.model_filename = model_filename = f"cb_{coin.lower()}_{trained_timestamp}"
path_to_modelfile = Path(dk.data_path / f"{model_filename}_model.joblib")
file_exists = path_to_modelfile.is_file()
if file_exists and not scanning:
logger.info("Found model at %s", dk.data_path / dk.model_filename)
elif not scanning:
logger.info("Could not find model at %s", dk.data_path / dk.model_filename)
return file_exists
def set_full_path(self) -> None:
self.full_path = Path(
self.config["user_data_dir"] / "models" / f"{self.freqai_info['identifier']}"
)
self.full_path.mkdir(parents=True, exist_ok=True)
shutil.copy(
self.config["config_files"][0],
Path(self.full_path, Path(self.config["config_files"][0]).name),
)
def train_model_in_series(
self,
new_trained_timerange: TimeRange,
pair: str,
strategy: IStrategy,
dk: FreqaiDataKitchen,
data_load_timerange: TimeRange,
):
"""
Retrieve data and train model in single threaded mode (only used if model directory is empty
upon startup for dry/live )
:param new_trained_timerange: TimeRange = the timerange to train the model on
:param metadata: dict = strategy provided metadata
:param strategy: IStrategy = user defined strategy object
:param dk: FreqaiDataKitchen = non-persistent data container for current coin/loop
:param data_load_timerange: TimeRange = the amount of data to be loaded
for populate_any_indicators
(larger than new_trained_timerange so that
new_trained_timerange does not contain any NaNs)
"""
corr_dataframes, base_dataframes = self.dd.get_base_and_corr_dataframes(
data_load_timerange, pair, dk
)
with self.analysis_lock:
unfiltered_dataframe = dk.use_strategy_to_populate_indicators(
strategy, corr_dataframes, base_dataframes, pair
)
unfiltered_dataframe = dk.slice_dataframe(new_trained_timerange, unfiltered_dataframe)
# find the features indicated by strategy and store in datakitchen
dk.find_features(unfiltered_dataframe)
model = self.train(unfiltered_dataframe, pair, dk)
self.dd.pair_dict[pair]["trained_timestamp"] = new_trained_timerange.stopts
dk.set_new_model_names(pair, new_trained_timerange)
self.dd.pair_dict[pair]["first"] = False
if self.dd.pair_dict[pair]["priority"] == 1 and self.scanning:
self.dd.pair_to_end_of_training_queue(pair)
self.dd.save_data(model, pair, dk)
if self.freqai_info.get("purge_old_models", False):
self.dd.purge_old_models()
def set_initial_historic_predictions(
self, pred_df: DataFrame, dk: FreqaiDataKitchen, pair: str
) -> None:
"""
This function is called only if the datadrawer failed to load an
existing set of historic predictions. In this case, it builds
the structure and sets fake predictions off the first training
data. After that, FreqAI will append new real predictions to the
set of historic predictions.
These values are used to generate live statistics which can be used
in the strategy for adaptive values. E.g. &*_mean/std are quantities
that can computed based on live predictions from the set of historical
predictions. Those values can be used in the user strategy to better
assess prediction rarity, and thus wait for probabilistically favorable
entries relative to the live historical predictions.
If the user reuses an identifier on a subsequent instance,
this function will not be called. In that case, "real" predictions
will be appended to the loaded set of historic predictions.
:param: df: DataFrame = the dataframe containing the training feature data
:param: model: Any = A model which was `fit` using a common library such as
catboost or lightgbm
:param: dk: FreqaiDataKitchen = object containing methods for data analysis
:param: pair: str = current pair
"""
self.dd.historic_predictions[pair] = pred_df
hist_preds_df = self.dd.historic_predictions[pair]
for label in hist_preds_df.columns:
if hist_preds_df[label].dtype == object:
continue
hist_preds_df[f'{label}_mean'] = 0
hist_preds_df[f'{label}_std'] = 0
hist_preds_df['do_predict'] = 0
if self.freqai_info['feature_parameters'].get('DI_threshold', 0) > 0:
hist_preds_df['DI_values'] = 0
for return_str in dk.data['extra_returns_per_train']:
hist_preds_df[return_str] = 0
# # for keras type models, the conv_window needs to be prepended so
# # viewing is correct in frequi
if self.freqai_info.get('keras', False):
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)
self.dd.historic_predictions[pair] = pd.concat(
[zeros_df, hist_preds_df], axis=0, ignore_index=True)
def fit_live_predictions(self, dk: FreqaiDataKitchen, pair: str) -> None:
"""
Fit the labels with a gaussian distribution
"""
import scipy as spy
# add classes from classifier label types if used
full_labels = dk.label_list + dk.unique_class_list
num_candles = self.freqai_info.get("fit_live_predictions_candles", 100)
dk.data["labels_mean"], dk.data["labels_std"] = {}, {}
for label in full_labels:
if self.dd.historic_predictions[dk.pair][label].dtype == object:
continue
f = spy.stats.norm.fit(self.dd.historic_predictions[dk.pair][label].tail(num_candles))
dk.data["labels_mean"][label], dk.data["labels_std"][label] = f[0], f[1]
return
def inference_timer(self, do='start'):
"""
Timer designed to track the cumulative time spent in FreqAI for one pass through
the whitelist. This will check if the time spent is more than 1/4 the time
of a single candle, and if so, it will warn the user of degraded performance
"""
if do == 'start':
self.pair_it += 1
self.begin_time = time.time()
elif do == 'stop':
end = time.time()
self.inference_time += (end - self.begin_time)
if self.pair_it == self.total_pairs:
logger.info(
f'Total time spent inferencing pairlist {self.inference_time:.2f} seconds')
if self.inference_time > 0.25 * self.base_tf_seconds:
logger.warning('Inference took over 25/% of the candle time. Reduce pairlist to'
' avoid blinding open trades and degrading performance.')
self.pair_it = 0
self.inference_time = 0
return
# Following methods which are overridden by user made prediction models.
# See freqai/prediction_models/CatboostPredictionModel.py for an example.
@abstractmethod
def train(self, unfiltered_dataframe: DataFrame, pair: str, dk: FreqaiDataKitchen) -> Any:
"""
Filter the training data and train a model to it. Train makes heavy use of the datahandler
for storing, saving, loading, and analyzing the data.
:param unfiltered_dataframe: Full dataframe for the current training period
:param metadata: pair metadata from strategy.
:return: Trained model which can be used to inference (self.predict)
"""
@abstractmethod
def fit(self, data_dictionary: Dict[str, Any]) -> Any:
"""
Most regressors use the same function names and arguments e.g. user
can drop in LGBMRegressor in place of CatBoostRegressor and all data
management will be properly handled by Freqai.
:param data_dictionary: Dict = the dictionary constructed by DataHandler to hold
all the training and test data/labels.
"""
return
@abstractmethod
def predict(
self, dataframe: DataFrame, dk: FreqaiDataKitchen, first: bool = True
) -> Tuple[DataFrame, NDArray[np.int_]]:
"""
Filter the prediction features data and predict with it.
:param unfiltered_dataframe: Full dataframe for the current backtest period.
:param dk: FreqaiDataKitchen = Data management/analysis tool associated to present pair only
:param first: boolean = whether this is the first prediction or not.
:return:
:predictions: np.array of predictions
: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)
"""

View File

@@ -0,0 +1,99 @@
import logging
from typing import Any, Tuple
import numpy as np
import numpy.typing as npt
import pandas as pd
from pandas import DataFrame
from freqtrade.freqai.data_kitchen import FreqaiDataKitchen
from freqtrade.freqai.freqai_interface import IFreqaiModel
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.
"""
def train(
self, unfiltered_dataframe: DataFrame, pair: str, dk: FreqaiDataKitchen
) -> 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_dataframe: 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("-------------------- Starting training " f"{pair} --------------------")
# filter the features requested by user in the configuration file and elegantly handle NaNs
features_filtered, labels_filtered = dk.filter_features(
unfiltered_dataframe,
dk.training_features_list,
dk.label_list,
training_filter=True,
)
start_date = unfiltered_dataframe["date"].iloc[0].strftime("%Y-%m-%d")
end_date = unfiltered_dataframe["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', 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)
logger.info(f"--------------------done training {pair}--------------------")
return model
def predict(
self, unfiltered_dataframe: DataFrame, dk: FreqaiDataKitchen, first: bool = False
) -> Tuple[DataFrame, npt.NDArray[np.int_]]:
"""
Filter the prediction features data and predict with it.
:param: unfiltered_dataframe: Full dataframe for the current backtest period.
:return:
:pred_df: dataframe containing the predictions
:do_predict: np.array of 1s and 0s to indicate places where freqai needed to remove
data (NaNs) or felt uncertain about data (PCA and DI index)
"""
dk.find_features(unfiltered_dataframe)
filtered_dataframe, _ = dk.filter_features(
unfiltered_dataframe, dk.training_features_list, training_filter=False
)
filtered_dataframe = dk.normalize_data_from_metadata(filtered_dataframe)
dk.data_dictionary["prediction_features"] = filtered_dataframe
self.data_cleaning_predict(dk, filtered_dataframe)
predictions = self.model.predict(dk.data_dictionary["prediction_features"])
pred_df = DataFrame(predictions, columns=dk.label_list)
predictions_prob = self.model.predict_proba(dk.data_dictionary["prediction_features"])
pred_df_prob = DataFrame(predictions_prob, columns=self.model.classes_)
pred_df = pd.concat([pred_df, pred_df_prob], axis=1)
return (pred_df, dk.do_predict)

View File

@@ -0,0 +1,96 @@
import logging
from typing import Any, Tuple
import numpy as np
import numpy.typing as npt
from pandas import DataFrame
from freqtrade.freqai.data_kitchen import FreqaiDataKitchen
from freqtrade.freqai.freqai_interface import IFreqaiModel
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.
"""
def train(
self, unfiltered_dataframe: DataFrame, pair: str, dk: FreqaiDataKitchen
) -> 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_dataframe: 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("-------------------- Starting training " f"{pair} --------------------")
# filter the features requested by user in the configuration file and elegantly handle NaNs
features_filtered, labels_filtered = dk.filter_features(
unfiltered_dataframe,
dk.training_features_list,
dk.label_list,
training_filter=True,
)
start_date = unfiltered_dataframe["date"].iloc[0].strftime("%Y-%m-%d")
end_date = unfiltered_dataframe["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', 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)
logger.info(f"--------------------done training {pair}--------------------")
return model
def predict(
self, unfiltered_dataframe: DataFrame, dk: FreqaiDataKitchen, first: bool = False
) -> Tuple[DataFrame, npt.NDArray[np.int_]]:
"""
Filter the prediction features data and predict with it.
:param: unfiltered_dataframe: Full dataframe for the current backtest period.
:return:
:pred_df: dataframe containing the predictions
:do_predict: np.array of 1s and 0s to indicate places where freqai needed to remove
data (NaNs) or felt uncertain about data (PCA and DI index)
"""
dk.find_features(unfiltered_dataframe)
filtered_dataframe, _ = dk.filter_features(
unfiltered_dataframe, dk.training_features_list, training_filter=False
)
filtered_dataframe = dk.normalize_data_from_metadata(filtered_dataframe)
dk.data_dictionary["prediction_features"] = filtered_dataframe
# optional additional data cleaning/analysis
self.data_cleaning_predict(dk, filtered_dataframe)
predictions = self.model.predict(dk.data_dictionary["prediction_features"])
pred_df = DataFrame(predictions, columns=dk.label_list)
pred_df = dk.denormalize_labels_from_metadata(pred_df)
return (pred_df, dk.do_predict)

View File

@@ -0,0 +1,64 @@
import logging
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_dataframe: DataFrame, pair: str, dk: FreqaiDataKitchen
) -> 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_dataframe: 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("-------------------- Starting training " f"{pair} --------------------")
# filter the features requested by user in the configuration file and elegantly handle NaNs
features_filtered, labels_filtered = dk.filter_features(
unfiltered_dataframe,
dk.training_features_list,
dk.label_list,
training_filter=True,
)
start_date = unfiltered_dataframe["date"].iloc[0].strftime("%Y-%m-%d")
end_date = unfiltered_dataframe["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', 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)
logger.info(f"--------------------done training {pair}--------------------")
return model

View File

@@ -0,0 +1,41 @@
import logging
from typing import Any, Dict
from catboost import CatBoostClassifier, Pool
from freqtrade.freqai.prediction_models.BaseClassifierModel import BaseClassifierModel
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.
"""
def fit(self, data_dictionary: Dict) -> Any:
"""
User sets up the training and test data to fit their desired model here
:params:
:data_dictionary: the dictionary constructed by DataHandler to hold
all the training and test data/labels.
"""
train_data = Pool(
data=data_dictionary["train_features"],
label=data_dictionary["train_labels"],
weight=data_dictionary["train_weights"],
)
cbr = CatBoostClassifier(
allow_writing_files=False,
loss_function='MultiClass',
**self.model_training_parameters,
)
cbr.fit(train_data)
return cbr

View File

@@ -0,0 +1,53 @@
import gc
import logging
from typing import Any, Dict
from catboost import CatBoostRegressor, Pool
from freqtrade.freqai.prediction_models.BaseRegressionModel import BaseRegressionModel
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.
"""
def fit(self, data_dictionary: Dict) -> 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.
"""
train_data = Pool(
data=data_dictionary["train_features"],
label=data_dictionary["train_labels"],
weight=data_dictionary["train_weights"],
)
if self.freqai_info.get('data_split_parameters', {}).get('test_size', 0.1) == 0:
test_data = None
else:
test_data = Pool(
data=data_dictionary["test_features"],
label=data_dictionary["test_labels"],
weight=data_dictionary["test_weights"],
)
model = CatBoostRegressor(
allow_writing_files=False,
**self.model_training_parameters,
)
model.fit(X=train_data, eval_set=test_data)
# some evidence that catboost pools have memory leaks:
# https://github.com/catboost/catboost/issues/1835
del train_data, test_data
gc.collect()
return model

View File

@@ -0,0 +1,44 @@
import logging
from typing import Any, Dict
from catboost import CatBoostRegressor # , Pool
from sklearn.multioutput import MultiOutputRegressor
from freqtrade.freqai.prediction_models.BaseRegressionModel import BaseRegressionModel
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.
"""
def fit(self, data_dictionary: Dict) -> 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.
"""
cbr = CatBoostRegressor(
allow_writing_files=False,
**self.model_training_parameters,
)
X = data_dictionary["train_features"]
y = data_dictionary["train_labels"]
eval_set = (data_dictionary["test_features"], data_dictionary["test_labels"])
sample_weight = data_dictionary["train_weights"]
model = MultiOutputRegressor(estimator=cbr)
model.fit(X=X, y=y, sample_weight=sample_weight) # , eval_set=eval_set)
if self.freqai_info.get('data_split_parameters', {}).get('test_size', 0.1) != 0:
train_score = model.score(X, y)
test_score = model.score(*eval_set)
logger.info(f"Train score {train_score}, Test score {test_score}")
return model

View File

@@ -0,0 +1,43 @@
import logging
from typing import Any, Dict
from lightgbm import LGBMClassifier
from freqtrade.freqai.prediction_models.BaseClassifierModel import BaseClassifierModel
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.
"""
def fit(self, data_dictionary: Dict) -> Any:
"""
User sets up the training and test data to fit their desired model here
:params:
:data_dictionary: the dictionary constructed by DataHandler to hold
all the training and test data/labels.
"""
if self.freqai_info.get('data_split_parameters', {}).get('test_size', 0.1) == 0:
eval_set = None
test_weights = None
else:
eval_set = (data_dictionary["test_features"].to_numpy(),
data_dictionary["test_labels"].to_numpy()[:, 0])
test_weights = data_dictionary["test_weights"]
X = data_dictionary["train_features"].to_numpy()
y = data_dictionary["train_labels"].to_numpy()[:, 0]
train_weights = data_dictionary["train_weights"]
model = LGBMClassifier(**self.model_training_parameters)
model.fit(X=X, y=y, eval_set=eval_set, sample_weight=train_weights,
eval_sample_weight=[test_weights])
return model

View File

@@ -0,0 +1,43 @@
import logging
from typing import Any, Dict
from lightgbm import LGBMRegressor
from freqtrade.freqai.prediction_models.BaseRegressionModel import BaseRegressionModel
logger = logging.getLogger(__name__)
class LightGBMRegressor(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.
"""
def fit(self, data_dictionary: Dict) -> Any:
"""
Most regressors use the same function names and arguments e.g. user
can drop in LGBMRegressor in place of CatBoostRegressor and all data
management will be properly handled by Freqai.
:param data_dictionary: the dictionary constructed by DataHandler to hold
all the training and test data/labels.
"""
if self.freqai_info.get('data_split_parameters', {}).get('test_size', 0.1) == 0:
eval_set = None
eval_weights = None
else:
eval_set = (data_dictionary["test_features"], data_dictionary["test_labels"])
eval_weights = data_dictionary["test_weights"]
X = data_dictionary["train_features"]
y = data_dictionary["train_labels"]
train_weights = data_dictionary["train_weights"]
model = LGBMRegressor(**self.model_training_parameters)
model.fit(X=X, y=y, eval_set=eval_set, sample_weight=train_weights,
eval_sample_weight=[eval_weights])
return model

View File

@@ -0,0 +1,39 @@
import logging
from typing import Any, Dict
from lightgbm import LGBMRegressor
from sklearn.multioutput import MultiOutputRegressor
from freqtrade.freqai.prediction_models.BaseRegressionModel import BaseRegressionModel
logger = logging.getLogger(__name__)
class LightGBMRegressorMultiTarget(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.
"""
def fit(self, data_dictionary: Dict) -> 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.
"""
lgb = LGBMRegressor(**self.model_training_parameters)
X = data_dictionary["train_features"]
y = data_dictionary["train_labels"]
eval_set = (data_dictionary["test_features"], data_dictionary["test_labels"])
sample_weight = data_dictionary["train_weights"]
model = MultiOutputRegressor(estimator=lgb)
model.fit(X=X, y=y, sample_weight=sample_weight) # , eval_set=eval_set)
train_score = model.score(X, y)
test_score = model.score(*eval_set)
logger.info(f"Train score {train_score}, Test score {test_score}")
return model

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +1,20 @@
from decimal import Decimal
from math import ceil
from freqtrade.exceptions import OperationalException
from freqtrade.util import FtPrecise
one = Decimal(1.0)
four = Decimal(4.0)
twenty_four = Decimal(24.0)
one = FtPrecise(1.0)
four = FtPrecise(4.0)
twenty_four = FtPrecise(24.0)
def interest(
exchange_name: str,
borrowed: Decimal,
rate: Decimal,
hours: Decimal
) -> Decimal:
borrowed: FtPrecise,
rate: FtPrecise,
hours: FtPrecise
) -> FtPrecise:
"""
Equation to calculate interest on margin trades
@@ -31,13 +31,13 @@ def interest(
"""
exchange_name = exchange_name.lower()
if exchange_name == "binance":
return borrowed * rate * ceil(hours) / twenty_four
return borrowed * rate * FtPrecise(ceil(hours)) / twenty_four
elif exchange_name == "kraken":
# Rounded based on https://kraken-fees-calculator.github.io/
return borrowed * rate * (one + ceil(hours / four))
return borrowed * rate * (one + FtPrecise(ceil(hours / four)))
elif exchange_name == "ftx":
# As Explained under #Interest rates section in
# https://help.ftx.com/hc/en-us/articles/360053007671-Spot-Margin-Trading-Explainer
return borrowed * rate * ceil(hours) / twenty_four
return borrowed * rate * FtPrecise(ceil(hours)) / twenty_four
else:
raise OperationalException(f"Leverage not available on {exchange_name} with freqtrade")

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