Merge branch 'develop' into feat/short
This commit is contained in:
commit
3fffc315ac
@ -52,6 +52,71 @@ freqtrade trade -c MyConfigUSDT.json -s MyCustomStrategy --db-url sqlite:///user
|
|||||||
|
|
||||||
For more information regarding usage of the sqlite databases, for example to manually enter or remove trades, please refer to the [SQL Cheatsheet](sql_cheatsheet.md).
|
For more information regarding usage of the sqlite databases, for example to manually enter or remove trades, please refer to the [SQL Cheatsheet](sql_cheatsheet.md).
|
||||||
|
|
||||||
|
### Multiple instances using docker
|
||||||
|
|
||||||
|
To run multiple instances of freqtrade using docker you will need to edit the docker-compose.yml file and add all the instances you want as separate services. Remember, you can separate your configuration into multiple files, so it's a good idea to think about making them modular, then if you need to edit something common to all bots, you can do that in a single config file.
|
||||||
|
``` yml
|
||||||
|
---
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
freqtrade1:
|
||||||
|
image: freqtradeorg/freqtrade:stable
|
||||||
|
# image: freqtradeorg/freqtrade:develop
|
||||||
|
# Use plotting image
|
||||||
|
# image: freqtradeorg/freqtrade:develop_plot
|
||||||
|
# Build step - only needed when additional dependencies are needed
|
||||||
|
# build:
|
||||||
|
# context: .
|
||||||
|
# dockerfile: "./docker/Dockerfile.custom"
|
||||||
|
restart: always
|
||||||
|
container_name: freqtrade1
|
||||||
|
volumes:
|
||||||
|
- "./user_data:/freqtrade/user_data"
|
||||||
|
# Expose api on port 8080 (localhost only)
|
||||||
|
# Please read the https://www.freqtrade.io/en/latest/rest-api/ documentation
|
||||||
|
# before enabling this.
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:8080:8080"
|
||||||
|
# Default command used when running `docker compose up`
|
||||||
|
command: >
|
||||||
|
trade
|
||||||
|
--logfile /freqtrade/user_data/logs/freqtrade1.log
|
||||||
|
--db-url sqlite:////freqtrade/user_data/tradesv3_freqtrade1.sqlite
|
||||||
|
--config /freqtrade/user_data/config.json
|
||||||
|
--config /freqtrade/user_data/config.freqtrade1.json
|
||||||
|
--strategy SampleStrategy
|
||||||
|
|
||||||
|
freqtrade2:
|
||||||
|
image: freqtradeorg/freqtrade:stable
|
||||||
|
# image: freqtradeorg/freqtrade:develop
|
||||||
|
# Use plotting image
|
||||||
|
# image: freqtradeorg/freqtrade:develop_plot
|
||||||
|
# Build step - only needed when additional dependencies are needed
|
||||||
|
# build:
|
||||||
|
# context: .
|
||||||
|
# dockerfile: "./docker/Dockerfile.custom"
|
||||||
|
restart: always
|
||||||
|
container_name: freqtrade2
|
||||||
|
volumes:
|
||||||
|
- "./user_data:/freqtrade/user_data"
|
||||||
|
# Expose api on port 8080 (localhost only)
|
||||||
|
# Please read the https://www.freqtrade.io/en/latest/rest-api/ documentation
|
||||||
|
# before enabling this.
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:8081:8080"
|
||||||
|
# Default command used when running `docker compose up`
|
||||||
|
command: >
|
||||||
|
trade
|
||||||
|
--logfile /freqtrade/user_data/logs/freqtrade2.log
|
||||||
|
--db-url sqlite:////freqtrade/user_data/tradesv3_freqtrade2.sqlite
|
||||||
|
--config /freqtrade/user_data/config.json
|
||||||
|
--config /freqtrade/user_data/config.freqtrade2.json
|
||||||
|
--strategy SampleStrategy
|
||||||
|
|
||||||
|
```
|
||||||
|
You can use whatever naming convention you want, freqtrade1 and 2 are arbitrary. Note, that you will need to use different database files, port mappings and telegram configurations for each instance, as mentioned above.
|
||||||
|
|
||||||
|
|
||||||
## Configure the bot running as a systemd service
|
## Configure the bot running as a systemd service
|
||||||
|
|
||||||
Copy the `freqtrade.service` file to your systemd user directory (usually `~/.config/systemd/user`) and update `WorkingDirectory` and `ExecStart` to match your setup.
|
Copy the `freqtrade.service` file to your systemd user directory (usually `~/.config/systemd/user`) and update `WorkingDirectory` and `ExecStart` to match your setup.
|
||||||
|
@ -22,6 +22,7 @@ usage: freqtrade download-data [-h] [-v] [--logfile FILE] [-V] [-c PATH]
|
|||||||
[-d PATH] [--userdir PATH]
|
[-d PATH] [--userdir PATH]
|
||||||
[-p PAIRS [PAIRS ...]] [--pairs-file FILE]
|
[-p PAIRS [PAIRS ...]] [--pairs-file FILE]
|
||||||
[--days INT] [--new-pairs-days INT]
|
[--days INT] [--new-pairs-days INT]
|
||||||
|
[--include-inactive-pairs]
|
||||||
[--timerange TIMERANGE] [--dl-trades]
|
[--timerange TIMERANGE] [--dl-trades]
|
||||||
[--exchange EXCHANGE]
|
[--exchange EXCHANGE]
|
||||||
[-t {1m,3m,5m,15m,30m,1h,2h,4h,6h,8h,12h,1d,3d,1w,2w,1M,1y} [{1m,3m,5m,15m,30m,1h,2h,4h,6h,8h,12h,1d,3d,1w,2w,1M,1y} ...]]
|
[-t {1m,3m,5m,15m,30m,1h,2h,4h,6h,8h,12h,1d,3d,1w,2w,1M,1y} [{1m,3m,5m,15m,30m,1h,2h,4h,6h,8h,12h,1d,3d,1w,2w,1M,1y} ...]]
|
||||||
@ -38,6 +39,8 @@ optional arguments:
|
|||||||
--days INT Download data for given number of days.
|
--days INT Download data for given number of days.
|
||||||
--new-pairs-days INT Download data of new pairs for given number of days.
|
--new-pairs-days INT Download data of new pairs for given number of days.
|
||||||
Default: `None`.
|
Default: `None`.
|
||||||
|
--include-inactive-pairs
|
||||||
|
Also download data from inactive pairs.
|
||||||
--timerange TIMERANGE
|
--timerange TIMERANGE
|
||||||
Specify what timerange of data to use.
|
Specify what timerange of data to use.
|
||||||
--dl-trades Download trades instead of OHLCV data. The bot will
|
--dl-trades Download trades instead of OHLCV data. The bot will
|
||||||
@ -52,10 +55,10 @@ optional arguments:
|
|||||||
exchange/pairs/timeframes.
|
exchange/pairs/timeframes.
|
||||||
--data-format-ohlcv {json,jsongz,hdf5}
|
--data-format-ohlcv {json,jsongz,hdf5}
|
||||||
Storage format for downloaded candle (OHLCV) data.
|
Storage format for downloaded candle (OHLCV) data.
|
||||||
(default: `None`).
|
(default: `json`).
|
||||||
--data-format-trades {json,jsongz,hdf5}
|
--data-format-trades {json,jsongz,hdf5}
|
||||||
Storage format for downloaded trades data. (default:
|
Storage format for downloaded trades data. (default:
|
||||||
`None`).
|
`jsongz`).
|
||||||
|
|
||||||
Common arguments:
|
Common arguments:
|
||||||
-v, --verbose Verbose mode (-vv for more, -vvv to get all messages).
|
-v, --verbose Verbose mode (-vv for more, -vvv to get all messages).
|
||||||
@ -80,6 +83,82 @@ Common arguments:
|
|||||||
|
|
||||||
For that reason, `download-data` does not care about the "startup-period" defined in a strategy. It's up to the user to download additional days if the backtest should start at a specific point in time (while respecting startup period).
|
For that reason, `download-data` does not care about the "startup-period" defined in a strategy. It's up to the user to download additional days if the backtest should start at a specific point in time (while respecting startup period).
|
||||||
|
|
||||||
|
### Pairs file
|
||||||
|
|
||||||
|
In alternative to the whitelist from `config.json`, a `pairs.json` file can be used.
|
||||||
|
If you are using Binance for example:
|
||||||
|
|
||||||
|
- create a directory `user_data/data/binance` and copy or create the `pairs.json` file in that directory.
|
||||||
|
- update the `pairs.json` file to contain the currency pairs you are interested in.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p user_data/data/binance
|
||||||
|
touch user_data/data/binance/pairs.json
|
||||||
|
```
|
||||||
|
|
||||||
|
The format of the `pairs.json` file is a simple json list.
|
||||||
|
Mixing different stake-currencies is allowed for this file, since it's only used for downloading.
|
||||||
|
|
||||||
|
``` json
|
||||||
|
[
|
||||||
|
"ETH/BTC",
|
||||||
|
"ETH/USDT",
|
||||||
|
"BTC/USDT",
|
||||||
|
"XRP/ETH"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! Tip "Downloading all data for one quote currency"
|
||||||
|
Often, you'll want to download data for all pairs of a specific quote-currency. In such cases, you can use the following shorthand:
|
||||||
|
`freqtrade download-data --exchange binance --pairs .*/USDT <...>`. The provided "pairs" string will be expanded to contain all active pairs on the exchange.
|
||||||
|
To also download data for inactive (delisted) pairs, add `--include-inactive-pairs` to the command.
|
||||||
|
|
||||||
|
??? Note "Permission denied errors"
|
||||||
|
If your configuration directory `user_data` was made by docker, you may get the following error:
|
||||||
|
|
||||||
|
```
|
||||||
|
cp: cannot create regular file 'user_data/data/binance/pairs.json': Permission denied
|
||||||
|
```
|
||||||
|
|
||||||
|
You can fix the permissions of your user-data directory as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo chown -R $UID:$GID user_data
|
||||||
|
```
|
||||||
|
|
||||||
|
### Start download
|
||||||
|
|
||||||
|
Then run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
freqtrade download-data --exchange binance
|
||||||
|
```
|
||||||
|
|
||||||
|
This will download historical candle (OHLCV) data for all the currency pairs you defined in `pairs.json`.
|
||||||
|
|
||||||
|
Alternatively, specify the pairs directly
|
||||||
|
|
||||||
|
```bash
|
||||||
|
freqtrade download-data --exchange binance --pairs ETH/USDT XRP/USDT BTC/USDT
|
||||||
|
```
|
||||||
|
|
||||||
|
or as regex (to download all active USDT pairs)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
freqtrade download-data --exchange binance --pairs .*/USDT
|
||||||
|
```
|
||||||
|
|
||||||
|
### Other Notes
|
||||||
|
|
||||||
|
- To use a different directory than the exchange specific default, use `--datadir user_data/data/some_directory`.
|
||||||
|
- To change the exchange used to download the historical data from, please use a different configuration file (you'll probably need to adjust rate limits etc.)
|
||||||
|
- To use `pairs.json` from some other directory, use `--pairs-file some_other_dir/pairs.json`.
|
||||||
|
- To download historical candle (OHLCV) data for only 10 days, use `--days 10` (defaults to 30 days).
|
||||||
|
- To download historical candle (OHLCV) data from a fixed starting point, use `--timerange 20200101-` - which will download all data from January 1st, 2020. Eventually set end dates are ignored.
|
||||||
|
- 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.
|
||||||
|
|
||||||
|
|
||||||
### Data format
|
### Data format
|
||||||
|
|
||||||
Freqtrade currently supports 3 data-formats for both OHLCV and trades data:
|
Freqtrade currently supports 3 data-formats for both OHLCV and trades data:
|
||||||
@ -312,64 +391,6 @@ ETH/BTC 5m, 15m, 30m, 1h, 2h, 4h, 6h, 12h, 1d
|
|||||||
ETH/USDT 5m, 15m, 30m, 1h, 2h, 4h
|
ETH/USDT 5m, 15m, 30m, 1h, 2h, 4h
|
||||||
```
|
```
|
||||||
|
|
||||||
### Pairs file
|
|
||||||
|
|
||||||
In alternative to the whitelist from `config.json`, a `pairs.json` file can be used.
|
|
||||||
|
|
||||||
If you are using Binance for example:
|
|
||||||
|
|
||||||
- create a directory `user_data/data/binance` and copy or create the `pairs.json` file in that directory.
|
|
||||||
- update the `pairs.json` file to contain the currency pairs you are interested in.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mkdir -p user_data/data/binance
|
|
||||||
cp tests/testdata/pairs.json user_data/data/binance
|
|
||||||
```
|
|
||||||
|
|
||||||
If your configuration directory `user_data` was made by docker, you may get the following error:
|
|
||||||
|
|
||||||
```
|
|
||||||
cp: cannot create regular file 'user_data/data/binance/pairs.json': Permission denied
|
|
||||||
```
|
|
||||||
|
|
||||||
You can fix the permissions of your user-data directory as follows:
|
|
||||||
|
|
||||||
```
|
|
||||||
sudo chown -R $UID:$GID user_data
|
|
||||||
```
|
|
||||||
|
|
||||||
The format of the `pairs.json` file is a simple json list.
|
|
||||||
Mixing different stake-currencies is allowed for this file, since it's only used for downloading.
|
|
||||||
|
|
||||||
``` json
|
|
||||||
[
|
|
||||||
"ETH/BTC",
|
|
||||||
"ETH/USDT",
|
|
||||||
"BTC/USDT",
|
|
||||||
"XRP/ETH"
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Start download
|
|
||||||
|
|
||||||
Then run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
freqtrade download-data --exchange binance
|
|
||||||
```
|
|
||||||
|
|
||||||
This will download historical candle (OHLCV) data for all the currency pairs you defined in `pairs.json`.
|
|
||||||
|
|
||||||
### Other Notes
|
|
||||||
|
|
||||||
- To use a different directory than the exchange specific default, use `--datadir user_data/data/some_directory`.
|
|
||||||
- To change the exchange used to download the historical data from, please use a different configuration file (you'll probably need to adjust rate limits etc.)
|
|
||||||
- To use `pairs.json` from some other directory, use `--pairs-file some_other_dir/pairs.json`.
|
|
||||||
- To download historical candle (OHLCV) data for only 10 days, use `--days 10` (defaults to 30 days).
|
|
||||||
- To download historical candle (OHLCV) data from a fixed starting point, use `--timerange 20200101-` - which will download all data from January 1st, 2020. Eventually set end dates are ignored.
|
|
||||||
- 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.
|
|
||||||
|
|
||||||
### Trades (tick) data
|
### Trades (tick) data
|
||||||
|
|
||||||
By default, `download-data` sub-command downloads Candles (OHLCV) data. Some exchanges also provide historic trade-data via their API.
|
By default, `download-data` sub-command downloads Candles (OHLCV) data. Some exchanges also provide historic trade-data via their API.
|
||||||
|
@ -8,7 +8,7 @@ All contributions, bug reports, bug fixes, documentation improvements, enhanceme
|
|||||||
|
|
||||||
Documentation is available at [https://freqtrade.io](https://www.freqtrade.io/) and needs to be provided with every new feature PR.
|
Documentation is available at [https://freqtrade.io](https://www.freqtrade.io/) and needs to be provided with every new feature PR.
|
||||||
|
|
||||||
Special fields for the documentation (like Note boxes, ...) can be found [here](https://squidfunk.github.io/mkdocs-material/extensions/admonition/).
|
Special fields for the documentation (like Note boxes, ...) can be found [here](https://squidfunk.github.io/mkdocs-material/reference/admonitions/).
|
||||||
|
|
||||||
To test the documentation locally use the following commands.
|
To test the documentation locally use the following commands.
|
||||||
|
|
||||||
|
@ -52,6 +52,8 @@ To skip pair validation against active markets, set `"allow_inactive": true` wit
|
|||||||
This can be useful for backtesting expired pairs (like quarterly spot-markets).
|
This can be useful for backtesting expired pairs (like quarterly spot-markets).
|
||||||
This option must be configured along with `exchange.skip_pair_validation` in the exchange configuration.
|
This option must be configured along with `exchange.skip_pair_validation` in the exchange configuration.
|
||||||
|
|
||||||
|
When used in a "follow-up" position (e.g. after VolumePairlist), all pairs in `'pair_whitelist'` will be added to the end of the pairlist.
|
||||||
|
|
||||||
#### Volume Pair List
|
#### Volume Pair List
|
||||||
|
|
||||||
`VolumePairList` employs sorting/filtering of pairs by their trading volume. It selects `number_assets` top pairs with sorting based on the `sort_key` (which can only be `quoteVolume`).
|
`VolumePairList` employs sorting/filtering of pairs by their trading volume. It selects `number_assets` top pairs with sorting based on the `sort_key` (which can only be `quoteVolume`).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
mkdocs==1.2.2
|
mkdocs==1.2.3
|
||||||
mkdocs-material==7.3.2
|
mkdocs-material==7.3.4
|
||||||
mdx_truly_sane_lists==1.2
|
mdx_truly_sane_lists==1.2
|
||||||
pymdown-extensions==9.0
|
pymdown-extensions==9.0
|
||||||
|
@ -281,7 +281,7 @@ bitmax True missing opt: fetchMyTrades
|
|||||||
bitmex False Various reasons.
|
bitmex False Various reasons.
|
||||||
bitpanda True
|
bitpanda True
|
||||||
bitso False missing: fetchOHLCV
|
bitso False missing: fetchOHLCV
|
||||||
bitstamp False Does not provide history. Details in https://github.com/freqtrade/freqtrade/issues/1983
|
bitstamp True missing opt: fetchTickers
|
||||||
bitstamp1 False missing: fetchOrder, fetchOHLCV
|
bitstamp1 False missing: fetchOrder, fetchOHLCV
|
||||||
bittrex True
|
bittrex True
|
||||||
bitvavo True
|
bitvavo True
|
||||||
|
@ -16,7 +16,6 @@ dependencies:
|
|||||||
- cachetools
|
- cachetools
|
||||||
- requests
|
- requests
|
||||||
- urllib3
|
- urllib3
|
||||||
- wrapt
|
|
||||||
- jsonschema
|
- jsonschema
|
||||||
- TA-Lib
|
- TA-Lib
|
||||||
- tabulate
|
- tabulate
|
||||||
@ -64,7 +63,6 @@ dependencies:
|
|||||||
- py_find_1st
|
- py_find_1st
|
||||||
- tables
|
- tables
|
||||||
- pytest-random-order
|
- pytest-random-order
|
||||||
- flake8-type-annotations
|
|
||||||
- ccxt
|
- ccxt
|
||||||
- flake8-tidy-imports
|
- flake8-tidy-imports
|
||||||
- -e .
|
- -e .
|
||||||
|
@ -63,9 +63,9 @@ ARGS_CONVERT_TRADES = ["pairs", "timeframes", "exchange", "dataformat_ohlcv", "d
|
|||||||
|
|
||||||
ARGS_LIST_DATA = ["exchange", "dataformat_ohlcv", "pairs"]
|
ARGS_LIST_DATA = ["exchange", "dataformat_ohlcv", "pairs"]
|
||||||
|
|
||||||
ARGS_DOWNLOAD_DATA = ["pairs", "pairs_file", "days", "new_pairs_days", "timerange",
|
ARGS_DOWNLOAD_DATA = ["pairs", "pairs_file", "days", "new_pairs_days", "include_inactive",
|
||||||
"download_trades", "exchange", "timeframes", "erase", "dataformat_ohlcv",
|
"timerange", "download_trades", "exchange", "timeframes",
|
||||||
"dataformat_trades"]
|
"erase", "dataformat_ohlcv", "dataformat_trades"]
|
||||||
|
|
||||||
ARGS_PLOT_DATAFRAME = ["pairs", "indicators1", "indicators2", "plot_limit",
|
ARGS_PLOT_DATAFRAME = ["pairs", "indicators1", "indicators2", "plot_limit",
|
||||||
"db_url", "trade_source", "export", "exportfilename",
|
"db_url", "trade_source", "export", "exportfilename",
|
||||||
|
@ -355,6 +355,11 @@ AVAILABLE_CLI_OPTIONS = {
|
|||||||
type=check_int_positive,
|
type=check_int_positive,
|
||||||
metavar='INT',
|
metavar='INT',
|
||||||
),
|
),
|
||||||
|
"include_inactive": Arg(
|
||||||
|
'--include-inactive-pairs',
|
||||||
|
help='Also download data from inactive pairs.',
|
||||||
|
action='store_true',
|
||||||
|
),
|
||||||
"new_pairs_days": Arg(
|
"new_pairs_days": Arg(
|
||||||
'--new-pairs-days',
|
'--new-pairs-days',
|
||||||
help='Download data of new pairs for given number of days. Default: `%(default)s`.',
|
help='Download data of new pairs for given number of days. Default: `%(default)s`.',
|
||||||
|
@ -11,6 +11,7 @@ from freqtrade.data.history import (convert_trades_to_ohlcv, refresh_backtest_oh
|
|||||||
from freqtrade.enums import RunMode
|
from freqtrade.enums import RunMode
|
||||||
from freqtrade.exceptions import OperationalException
|
from freqtrade.exceptions import OperationalException
|
||||||
from freqtrade.exchange import timeframe_to_minutes
|
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 expand_pairlist
|
||||||
from freqtrade.resolvers import ExchangeResolver
|
from freqtrade.resolvers import ExchangeResolver
|
||||||
|
|
||||||
@ -47,11 +48,13 @@ def start_download_data(args: Dict[str, Any]) -> None:
|
|||||||
|
|
||||||
# Init exchange
|
# Init exchange
|
||||||
exchange = ExchangeResolver.load_exchange(config['exchange']['name'], config, validate=False)
|
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)
|
||||||
|
|
||||||
# Manual validations of relevant settings
|
# Manual validations of relevant settings
|
||||||
if not config['exchange'].get('skip_pair_validation', False):
|
if not config['exchange'].get('skip_pair_validation', False):
|
||||||
exchange.validate_pairs(config['pairs'])
|
exchange.validate_pairs(expanded_pairs)
|
||||||
expanded_pairs = expand_pairlist(config['pairs'], list(exchange.markets))
|
|
||||||
|
|
||||||
logger.info(f"About to download pairs: {expanded_pairs}, "
|
logger.info(f"About to download pairs: {expanded_pairs}, "
|
||||||
f"intervals: {config['timeframes']} to {config['datadir']}")
|
f"intervals: {config['timeframes']} to {config['datadir']}")
|
||||||
|
|
||||||
|
@ -407,6 +407,9 @@ class Configuration:
|
|||||||
self._args_to_config(config, argname='days',
|
self._args_to_config(config, argname='days',
|
||||||
logstring='Detected --days: {}')
|
logstring='Detected --days: {}')
|
||||||
|
|
||||||
|
self._args_to_config(config, argname='include_inactive',
|
||||||
|
logstring='Detected --include-inactive-pairs: {}')
|
||||||
|
|
||||||
self._args_to_config(config, argname='download_trades',
|
self._args_to_config(config, argname='download_trades',
|
||||||
logstring='Detected --dl-trades: {}')
|
logstring='Detected --dl-trades: {}')
|
||||||
|
|
||||||
|
@ -16,8 +16,6 @@ API_FETCH_ORDER_RETRY_COUNT = 5
|
|||||||
|
|
||||||
BAD_EXCHANGES = {
|
BAD_EXCHANGES = {
|
||||||
"bitmex": "Various reasons.",
|
"bitmex": "Various reasons.",
|
||||||
"bitstamp": "Does not provide history. "
|
|
||||||
"Details in https://github.com/freqtrade/freqtrade/issues/1983",
|
|
||||||
"phemex": "Does not provide history. ",
|
"phemex": "Does not provide history. ",
|
||||||
"poloniex": "Does not provide fetch_order endpoint to fetch both open and closed orders.",
|
"poloniex": "Does not provide fetch_order endpoint to fetch both open and closed orders.",
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ progressbar.streams.wrap_stdout()
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
INITIAL_POINTS = 5
|
INITIAL_POINTS = 30
|
||||||
|
|
||||||
# Keep no more than SKOPT_MODEL_QUEUE_SIZE models
|
# Keep no more than SKOPT_MODEL_QUEUE_SIZE models
|
||||||
# in the skopt model queue, to optimize memory consumption
|
# in the skopt model queue, to optimize memory consumption
|
||||||
|
@ -4,9 +4,9 @@ Static Pair List provider
|
|||||||
Provides pair white list as it configured in config
|
Provides pair white list as it configured in config
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
|
from copy import deepcopy
|
||||||
from typing import Any, Dict, List
|
from typing import Any, Dict, List
|
||||||
|
|
||||||
from freqtrade.exceptions import OperationalException
|
|
||||||
from freqtrade.plugins.pairlist.IPairList import IPairList
|
from freqtrade.plugins.pairlist.IPairList import IPairList
|
||||||
|
|
||||||
|
|
||||||
@ -20,10 +20,6 @@ class StaticPairList(IPairList):
|
|||||||
pairlist_pos: int) -> None:
|
pairlist_pos: int) -> None:
|
||||||
super().__init__(exchange, pairlistmanager, config, pairlistconfig, pairlist_pos)
|
super().__init__(exchange, pairlistmanager, config, pairlistconfig, pairlist_pos)
|
||||||
|
|
||||||
if self._pairlist_pos != 0:
|
|
||||||
raise OperationalException(f"{self.name} can only be used in the first position "
|
|
||||||
"in the list of Pairlist Handlers.")
|
|
||||||
|
|
||||||
self._allow_inactive = self._pairlistconfig.get('allow_inactive', False)
|
self._allow_inactive = self._pairlistconfig.get('allow_inactive', False)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -64,4 +60,8 @@ class StaticPairList(IPairList):
|
|||||||
:param tickers: Tickers (from exchange.get_tickers()). May be cached.
|
:param tickers: Tickers (from exchange.get_tickers()). May be cached.
|
||||||
:return: new whitelist
|
:return: new whitelist
|
||||||
"""
|
"""
|
||||||
return pairlist
|
pairlist_ = deepcopy(pairlist)
|
||||||
|
for pair in self._config['exchange']['pair_whitelist']:
|
||||||
|
if pair not in pairlist_:
|
||||||
|
pairlist_.append(pair)
|
||||||
|
return pairlist_
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from typing import Any, Dict, Optional
|
from typing import Any, Dict, Iterator, Optional
|
||||||
|
|
||||||
from freqtrade.persistence import Trade
|
from freqtrade.persistence import Trade
|
||||||
from freqtrade.rpc.rpc import RPC, RPCException
|
from freqtrade.rpc.rpc import RPC, RPCException
|
||||||
@ -12,11 +12,12 @@ def get_rpc_optional() -> Optional[RPC]:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_rpc() -> Optional[RPC]:
|
def get_rpc() -> Optional[Iterator[RPC]]:
|
||||||
_rpc = get_rpc_optional()
|
_rpc = get_rpc_optional()
|
||||||
if _rpc:
|
if _rpc:
|
||||||
Trade.query.session.rollback()
|
Trade.query.session.rollback()
|
||||||
return _rpc
|
yield _rpc
|
||||||
|
Trade.query.session.rollback()
|
||||||
else:
|
else:
|
||||||
raise RPCException('Bot is not in the correct state')
|
raise RPCException('Bot is not in the correct state')
|
||||||
|
|
||||||
|
10
freqtrade/vendor/qtpylib/indicators.py
vendored
10
freqtrade/vendor/qtpylib/indicators.py
vendored
@ -339,11 +339,13 @@ def vwap(bars):
|
|||||||
(input can be pandas series or numpy array)
|
(input can be pandas series or numpy array)
|
||||||
bars are usually mid [ (h+l)/2 ] or typical [ (h+l+c)/3 ]
|
bars are usually mid [ (h+l)/2 ] or typical [ (h+l+c)/3 ]
|
||||||
"""
|
"""
|
||||||
typical = ((bars['high'] + bars['low'] + bars['close']) / 3).values
|
raise ValueError("using `qtpylib.vwap` facilitates lookahead bias. Please use "
|
||||||
volume = bars['volume'].values
|
"`qtpylib.rolling_vwap` instead, which calculates vwap in a rolling manner.")
|
||||||
|
# typical = ((bars['high'] + bars['low'] + bars['close']) / 3).values
|
||||||
|
# volume = bars['volume'].values
|
||||||
|
|
||||||
return pd.Series(index=bars.index,
|
# return pd.Series(index=bars.index,
|
||||||
data=np.cumsum(volume * typical) / np.cumsum(volume))
|
# data=np.cumsum(volume * typical) / np.cumsum(volume))
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------
|
# ---------------------------------------------
|
||||||
|
@ -4,11 +4,11 @@
|
|||||||
-r requirements-hyperopt.txt
|
-r requirements-hyperopt.txt
|
||||||
|
|
||||||
coveralls==3.2.0
|
coveralls==3.2.0
|
||||||
flake8==4.0.0
|
flake8==4.0.1
|
||||||
flake8-tidy-imports==4.5.0
|
flake8-tidy-imports==4.5.0
|
||||||
mypy==0.910
|
mypy==0.910
|
||||||
pytest==6.2.5
|
pytest==6.2.5
|
||||||
pytest-asyncio==0.15.1
|
pytest-asyncio==0.16.0
|
||||||
pytest-cov==3.0.0
|
pytest-cov==3.0.0
|
||||||
pytest-mock==3.6.1
|
pytest-mock==3.6.1
|
||||||
pytest-random-order==1.0.4
|
pytest-random-order==1.0.4
|
||||||
@ -20,7 +20,7 @@ time-machine==2.4.0
|
|||||||
nbconvert==6.2.0
|
nbconvert==6.2.0
|
||||||
|
|
||||||
# mypy types
|
# mypy types
|
||||||
types-cachetools==4.2.2
|
types-cachetools==4.2.4
|
||||||
types-filelock==3.2.0
|
types-filelock==3.2.1
|
||||||
types-requests==2.25.9
|
types-requests==2.25.11
|
||||||
types-tabulate==0.8.2
|
types-tabulate==0.8.3
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
scipy==1.7.1
|
scipy==1.7.1
|
||||||
scikit-learn==1.0
|
scikit-learn==1.0
|
||||||
scikit-optimize==0.9.0
|
scikit-optimize==0.9.0
|
||||||
filelock==3.3.0
|
filelock==3.3.1
|
||||||
joblib==1.1.0
|
joblib==1.1.0
|
||||||
psutil==5.8.0
|
psutil==5.8.0
|
||||||
progressbar2==3.53.3
|
progressbar2==3.55.0
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
numpy==1.21.2
|
numpy==1.21.2
|
||||||
pandas==1.3.3
|
pandas==1.3.4
|
||||||
pandas-ta==0.3.14b
|
pandas-ta==0.3.14b
|
||||||
|
|
||||||
ccxt==1.57.94
|
ccxt==1.58.47
|
||||||
# Pin cryptography for now due to rust build errors with piwheels
|
# Pin cryptography for now due to rust build errors with piwheels
|
||||||
cryptography==35.0.0
|
cryptography==35.0.0
|
||||||
aiohttp==3.7.4.post0
|
aiohttp==3.7.4.post0
|
||||||
@ -12,7 +12,6 @@ arrow==1.2.0
|
|||||||
cachetools==4.2.2
|
cachetools==4.2.2
|
||||||
requests==2.26.0
|
requests==2.26.0
|
||||||
urllib3==1.26.7
|
urllib3==1.26.7
|
||||||
wrapt==1.13.1
|
|
||||||
jsonschema==4.1.0
|
jsonschema==4.1.0
|
||||||
TA-Lib==0.4.21
|
TA-Lib==0.4.21
|
||||||
technical==1.3.0
|
technical==1.3.0
|
||||||
@ -26,15 +25,15 @@ blosc==1.10.6
|
|||||||
py_find_1st==1.1.5
|
py_find_1st==1.1.5
|
||||||
|
|
||||||
# Load ticker files 30% faster
|
# Load ticker files 30% faster
|
||||||
python-rapidjson==1.4
|
python-rapidjson==1.5
|
||||||
|
|
||||||
# Notify systemd
|
# Notify systemd
|
||||||
sdnotify==0.3.2
|
sdnotify==0.3.2
|
||||||
|
|
||||||
# API Server
|
# API Server
|
||||||
fastapi==0.68.1
|
fastapi==0.70.0
|
||||||
uvicorn==0.15.0
|
uvicorn==0.15.0
|
||||||
pyjwt==2.2.0
|
pyjwt==2.3.0
|
||||||
aiofiles==0.7.0
|
aiofiles==0.7.0
|
||||||
psutil==5.8.0
|
psutil==5.8.0
|
||||||
|
|
||||||
|
2
setup.py
2
setup.py
@ -16,7 +16,6 @@ hyperopt = [
|
|||||||
develop = [
|
develop = [
|
||||||
'coveralls',
|
'coveralls',
|
||||||
'flake8',
|
'flake8',
|
||||||
'flake8-type-annotations',
|
|
||||||
'flake8-tidy-imports',
|
'flake8-tidy-imports',
|
||||||
'mypy',
|
'mypy',
|
||||||
'pytest',
|
'pytest',
|
||||||
@ -51,7 +50,6 @@ setup(
|
|||||||
'cachetools',
|
'cachetools',
|
||||||
'requests',
|
'requests',
|
||||||
'urllib3',
|
'urllib3',
|
||||||
'wrapt',
|
|
||||||
'jsonschema',
|
'jsonschema',
|
||||||
'TA-Lib',
|
'TA-Lib',
|
||||||
'pandas-ta',
|
'pandas-ta',
|
||||||
|
20
setup.sh
20
setup.sh
@ -30,7 +30,7 @@ function check_installed_python() {
|
|||||||
check_installed_pip
|
check_installed_pip
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "No usable python found. Please make sure to have python3.7 or newer installed"
|
echo "No usable python found. Please make sure to have python3.7 or newer installed"
|
||||||
exit 1
|
exit 1
|
||||||
@ -95,11 +95,19 @@ function install_talib() {
|
|||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd build_helpers && ./install_ta-lib.sh && cd ..
|
cd build_helpers && ./install_ta-lib.sh
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Quitting. Please fix the above error before continuing."
|
||||||
|
cd ..
|
||||||
|
exit 1
|
||||||
|
fi;
|
||||||
|
|
||||||
|
cd ..
|
||||||
}
|
}
|
||||||
|
|
||||||
function install_mac_newer_python_dependencies() {
|
function install_mac_newer_python_dependencies() {
|
||||||
|
|
||||||
if [ ! $(brew --prefix --installed hdf5 2>/dev/null) ]
|
if [ ! $(brew --prefix --installed hdf5 2>/dev/null) ]
|
||||||
then
|
then
|
||||||
echo "-------------------------"
|
echo "-------------------------"
|
||||||
@ -115,7 +123,7 @@ function install_mac_newer_python_dependencies() {
|
|||||||
echo "Installing c-blosc"
|
echo "Installing c-blosc"
|
||||||
echo "-------------------------"
|
echo "-------------------------"
|
||||||
brew install c-blosc
|
brew install c-blosc
|
||||||
fi
|
fi
|
||||||
export CBLOSC_DIR=$(brew --prefix)
|
export CBLOSC_DIR=$(brew --prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +138,7 @@ function install_macos() {
|
|||||||
fi
|
fi
|
||||||
#Gets number after decimal in python version
|
#Gets number after decimal in python version
|
||||||
version=$(egrep -o 3.\[0-9\]+ <<< $PYTHON | sed 's/3.//g')
|
version=$(egrep -o 3.\[0-9\]+ <<< $PYTHON | sed 's/3.//g')
|
||||||
|
|
||||||
if [[ $version -ge 9 ]]; then #Checks if python version >= 3.9
|
if [[ $version -ge 9 ]]; then #Checks if python version >= 3.9
|
||||||
install_mac_newer_python_dependencies
|
install_mac_newer_python_dependencies
|
||||||
fi
|
fi
|
||||||
|
@ -754,6 +754,46 @@ def test_download_data_no_pairs(mocker, caplog):
|
|||||||
start_download_data(pargs)
|
start_download_data(pargs)
|
||||||
|
|
||||||
|
|
||||||
|
def test_download_data_all_pairs(mocker, markets):
|
||||||
|
|
||||||
|
mocker.patch.object(Path, "exists", MagicMock(return_value=False))
|
||||||
|
|
||||||
|
dl_mock = mocker.patch('freqtrade.commands.data_commands.refresh_backtest_ohlcv_data',
|
||||||
|
MagicMock(return_value=["ETH/BTC", "XRP/BTC"]))
|
||||||
|
patch_exchange(mocker)
|
||||||
|
mocker.patch(
|
||||||
|
'freqtrade.exchange.Exchange.markets', PropertyMock(return_value=markets)
|
||||||
|
)
|
||||||
|
args = [
|
||||||
|
"download-data",
|
||||||
|
"--exchange",
|
||||||
|
"binance",
|
||||||
|
"--pairs",
|
||||||
|
".*/USDT"
|
||||||
|
]
|
||||||
|
pargs = get_args(args)
|
||||||
|
pargs['config'] = None
|
||||||
|
start_download_data(pargs)
|
||||||
|
expected = set(['ETH/USDT', 'XRP/USDT', 'NEO/USDT', 'TKN/USDT'])
|
||||||
|
assert set(dl_mock.call_args_list[0][1]['pairs']) == expected
|
||||||
|
assert dl_mock.call_count == 1
|
||||||
|
|
||||||
|
dl_mock.reset_mock()
|
||||||
|
args = [
|
||||||
|
"download-data",
|
||||||
|
"--exchange",
|
||||||
|
"binance",
|
||||||
|
"--pairs",
|
||||||
|
".*/USDT",
|
||||||
|
"--include-inactive-pairs",
|
||||||
|
]
|
||||||
|
pargs = get_args(args)
|
||||||
|
pargs['config'] = None
|
||||||
|
start_download_data(pargs)
|
||||||
|
expected = set(['ETH/USDT', 'LTC/USDT', 'XRP/USDT', 'NEO/USDT', 'TKN/USDT'])
|
||||||
|
assert set(dl_mock.call_args_list[0][1]['pairs']) == expected
|
||||||
|
|
||||||
|
|
||||||
def test_download_data_trades(mocker, caplog):
|
def test_download_data_trades(mocker, caplog):
|
||||||
dl_mock = mocker.patch('freqtrade.commands.data_commands.refresh_backtest_trades_data',
|
dl_mock = mocker.patch('freqtrade.commands.data_commands.refresh_backtest_trades_data',
|
||||||
MagicMock(return_value=[]))
|
MagicMock(return_value=[]))
|
||||||
|
@ -278,7 +278,6 @@ def create_mock_trades(fee, is_short: bool, use_db: bool = True):
|
|||||||
|
|
||||||
if use_db:
|
if use_db:
|
||||||
Trade.commit()
|
Trade.commit()
|
||||||
Trade.query.session.flush()
|
|
||||||
|
|
||||||
|
|
||||||
def create_mock_trades_with_leverage(fee, use_db: bool = True):
|
def create_mock_trades_with_leverage(fee, use_db: bool = True):
|
||||||
@ -351,7 +350,6 @@ def create_mock_trades_usdt(fee, use_db: bool = True):
|
|||||||
|
|
||||||
if use_db:
|
if use_db:
|
||||||
Trade.commit()
|
Trade.commit()
|
||||||
Trade.query.session.flush()
|
|
||||||
|
|
||||||
|
|
||||||
def get_sides(is_short: bool) -> Tuple[str, str]:
|
def get_sides(is_short: bool) -> Tuple[str, str]:
|
||||||
|
@ -415,10 +415,10 @@ def test_VolumePairList_refresh_empty(mocker, markets_empty, whitelist_conf):
|
|||||||
# SpreadFilter only
|
# SpreadFilter only
|
||||||
([{"method": "SpreadFilter", "max_spread_ratio": 0.005}],
|
([{"method": "SpreadFilter", "max_spread_ratio": 0.005}],
|
||||||
"BTC", 'filter_at_the_beginning'), # OperationalException expected
|
"BTC", 'filter_at_the_beginning'), # OperationalException expected
|
||||||
# Static Pairlist after VolumePairList, on a non-first position
|
# Static Pairlist after VolumePairList, on a non-first position (appends pairs)
|
||||||
([{"method": "VolumePairList", "number_assets": 5, "sort_key": "quoteVolume"},
|
([{"method": "VolumePairList", "number_assets": 2, "sort_key": "quoteVolume"},
|
||||||
{"method": "StaticPairList"}],
|
{"method": "StaticPairList"}],
|
||||||
"BTC", 'static_in_the_middle'),
|
"BTC", ['ETH/BTC', 'TKN/BTC', 'TRST/BTC', 'SWT/BTC', 'BCC/BTC', 'HOT/BTC']),
|
||||||
([{"method": "VolumePairList", "number_assets": 20, "sort_key": "quoteVolume"},
|
([{"method": "VolumePairList", "number_assets": 20, "sort_key": "quoteVolume"},
|
||||||
{"method": "PriceFilter", "low_price_ratio": 0.02}],
|
{"method": "PriceFilter", "low_price_ratio": 0.02}],
|
||||||
"USDT", ['ETH/USDT', 'NANO/USDT']),
|
"USDT", ['ETH/USDT', 'NANO/USDT']),
|
||||||
@ -469,13 +469,6 @@ def test_VolumePairList_whitelist_gen(mocker, whitelist_conf, shitcoinmarkets, t
|
|||||||
|
|
||||||
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
|
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
|
||||||
|
|
||||||
if whitelist_result == 'static_in_the_middle':
|
|
||||||
with pytest.raises(OperationalException,
|
|
||||||
match=r"StaticPairList can only be used in the first position "
|
|
||||||
r"in the list of Pairlist Handlers."):
|
|
||||||
freqtrade = get_patched_freqtradebot(mocker, whitelist_conf)
|
|
||||||
return
|
|
||||||
|
|
||||||
freqtrade = get_patched_freqtradebot(mocker, whitelist_conf)
|
freqtrade = get_patched_freqtradebot(mocker, whitelist_conf)
|
||||||
mocker.patch.multiple('freqtrade.exchange.Exchange',
|
mocker.patch.multiple('freqtrade.exchange.Exchange',
|
||||||
get_tickers=tickers,
|
get_tickers=tickers,
|
||||||
|
@ -698,7 +698,6 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets):
|
|||||||
assert rc.json() == {"error": "Error querying /api/v1/edge: Edge is not enabled."}
|
assert rc.json() == {"error": "Error querying /api/v1/edge: Edge is not enabled."}
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("init_persistence")
|
|
||||||
# TODO-lev: @pytest.mark.parametrize('is_short', [True, False])
|
# TODO-lev: @pytest.mark.parametrize('is_short', [True, False])
|
||||||
def test_api_profit(botclient, mocker, ticker, fee, markets):
|
def test_api_profit(botclient, mocker, ticker, fee, markets):
|
||||||
ftbot, client = botclient
|
ftbot, client = botclient
|
||||||
@ -750,9 +749,8 @@ def test_api_profit(botclient, mocker, ticker, fee, markets):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("init_persistence")
|
|
||||||
# TODO-lev: @pytest.mark.parametrize('is_short', [True, False])
|
# TODO-lev: @pytest.mark.parametrize('is_short', [True, False])
|
||||||
def test_api_stats(botclient, mocker, ticker, fee, markets):
|
def test_api_stats(botclient, mocker, ticker, fee, markets,):
|
||||||
ftbot, client = botclient
|
ftbot, client = botclient
|
||||||
patch_get_signal(ftbot)
|
patch_get_signal(ftbot)
|
||||||
mocker.patch.multiple(
|
mocker.patch.multiple(
|
||||||
@ -817,7 +815,7 @@ def test_api_performance(botclient, fee):
|
|||||||
trade.close_profit_abs = trade.calc_profit()
|
trade.close_profit_abs = trade.calc_profit()
|
||||||
|
|
||||||
Trade.query.session.add(trade)
|
Trade.query.session.add(trade)
|
||||||
Trade.query.session.flush()
|
Trade.commit()
|
||||||
|
|
||||||
rc = client_get(client, f"{BASE_URI}/performance")
|
rc = client_get(client, f"{BASE_URI}/performance")
|
||||||
assert_response(rc)
|
assert_response(rc)
|
||||||
|
Loading…
Reference in New Issue
Block a user