merge develop into tensorboard cleanup
This commit is contained in:
commit
0f6b98b69a
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -20,7 +20,7 @@ Please do not use bug reports to request new features.
|
||||
* Operating system: ____
|
||||
* Python Version: _____ (`python -V`)
|
||||
* CCXT version: _____ (`pip freeze | grep ccxt`)
|
||||
* Freqtrade Version: ____ (`freqtrade -V` or `docker-compose run --rm freqtrade -V` for Freqtrade running in docker)
|
||||
* Freqtrade Version: ____ (`freqtrade -V` or `docker compose run --rm freqtrade -V` for Freqtrade running in docker)
|
||||
|
||||
Note: All issues other than enhancement requests will be closed without further comment if the above template is deleted or not filled out.
|
||||
|
||||
|
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -18,7 +18,7 @@ Have you search for this feature before requesting it? It's highly likely that a
|
||||
* Operating system: ____
|
||||
* Python Version: _____ (`python -V`)
|
||||
* CCXT version: _____ (`pip freeze | grep ccxt`)
|
||||
* Freqtrade Version: ____ (`freqtrade -V` or `docker-compose run --rm freqtrade -V` for Freqtrade running in docker)
|
||||
* Freqtrade Version: ____ (`freqtrade -V` or `docker compose run --rm freqtrade -V` for Freqtrade running in docker)
|
||||
|
||||
|
||||
## Describe the enhancement
|
||||
|
2
.github/ISSUE_TEMPLATE/question.md
vendored
2
.github/ISSUE_TEMPLATE/question.md
vendored
@ -18,7 +18,7 @@ Please do not use the question template to report bugs or to request new feature
|
||||
* Operating system: ____
|
||||
* Python Version: _____ (`python -V`)
|
||||
* CCXT version: _____ (`pip freeze | grep ccxt`)
|
||||
* Freqtrade Version: ____ (`freqtrade -V` or `docker-compose run --rm freqtrade -V` for Freqtrade running in docker)
|
||||
* Freqtrade Version: ____ (`freqtrade -V` or `docker compose run --rm freqtrade -V` for Freqtrade running in docker)
|
||||
|
||||
## Your question
|
||||
|
||||
|
@ -79,9 +79,7 @@
|
||||
"test_size": 0.33,
|
||||
"random_state": 1
|
||||
},
|
||||
"model_training_parameters": {
|
||||
"n_estimators": 1000
|
||||
}
|
||||
"model_training_parameters": {}
|
||||
},
|
||||
"bot_name": "",
|
||||
"force_entry_enable": true,
|
||||
|
@ -5,7 +5,7 @@ You can analyze the results of backtests and trading history easily using Jupyte
|
||||
## Quick start with docker
|
||||
|
||||
Freqtrade provides a docker-compose file which starts up a jupyter lab server.
|
||||
You can run this server using the following command: `docker-compose -f docker/docker-compose-jupyter.yml up`
|
||||
You can run this server using the following command: `docker compose -f docker/docker-compose-jupyter.yml up`
|
||||
|
||||
This will create a dockercontainer running jupyter lab, which will be accessible using `https://127.0.0.1:8888/lab`.
|
||||
Please use the link that's printed in the console after startup for simplified login.
|
||||
|
@ -4,20 +4,22 @@ This page explains how to run the bot with Docker. It is not meant to work out o
|
||||
|
||||
## Install Docker
|
||||
|
||||
Start by downloading and installing Docker CE for your platform:
|
||||
Start by downloading and installing Docker / Docker Desktop for your platform:
|
||||
|
||||
* [Mac](https://docs.docker.com/docker-for-mac/install/)
|
||||
* [Windows](https://docs.docker.com/docker-for-windows/install/)
|
||||
* [Linux](https://docs.docker.com/install/)
|
||||
|
||||
To simplify running freqtrade, [`docker-compose`](https://docs.docker.com/compose/install/) should be installed and available to follow the below [docker quick start guide](#docker-quick-start).
|
||||
!!! Info "Docker compose install"
|
||||
Freqtrade documentation assumes the use of Docker desktop (or the docker compose plugin).
|
||||
While the docker-compose standalone installation still works, it will require changing all `docker compose` commands from `docker compose` to `docker-compose` to work (e.g. `docker compose up -d` will become `docker-compose up -d`).
|
||||
|
||||
## Freqtrade with docker-compose
|
||||
## Freqtrade with docker
|
||||
|
||||
Freqtrade provides an official Docker image on [Dockerhub](https://hub.docker.com/r/freqtradeorg/freqtrade/), as well as a [docker-compose file](https://github.com/freqtrade/freqtrade/blob/stable/docker-compose.yml) ready for usage.
|
||||
Freqtrade provides an official Docker image on [Dockerhub](https://hub.docker.com/r/freqtradeorg/freqtrade/), as well as a [docker compose file](https://github.com/freqtrade/freqtrade/blob/stable/docker-compose.yml) ready for usage.
|
||||
|
||||
!!! Note
|
||||
- The following section assumes that `docker` and `docker-compose` are installed and available to the logged in user.
|
||||
- The following section assumes that `docker` is installed and available to the logged in user.
|
||||
- All below commands use relative directories and will have to be executed from the directory containing the `docker-compose.yml` file.
|
||||
|
||||
### Docker quick start
|
||||
@ -31,13 +33,13 @@ cd ft_userdata/
|
||||
curl https://raw.githubusercontent.com/freqtrade/freqtrade/stable/docker-compose.yml -o docker-compose.yml
|
||||
|
||||
# Pull the freqtrade image
|
||||
docker-compose pull
|
||||
docker compose pull
|
||||
|
||||
# Create user directory structure
|
||||
docker-compose run --rm freqtrade create-userdir --userdir user_data
|
||||
docker compose run --rm freqtrade create-userdir --userdir user_data
|
||||
|
||||
# Create configuration - Requires answering interactive questions
|
||||
docker-compose run --rm freqtrade new-config --config user_data/config.json
|
||||
docker compose run --rm freqtrade new-config --config user_data/config.json
|
||||
```
|
||||
|
||||
The above snippet creates a new directory called `ft_userdata`, downloads the latest compose file and pulls the freqtrade image.
|
||||
@ -64,7 +66,7 @@ The `SampleStrategy` is run by default.
|
||||
Once this is done, you're ready to launch the bot in trading mode (Dry-run or Live-trading, depending on your answer to the corresponding question you made above).
|
||||
|
||||
``` bash
|
||||
docker-compose up -d
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
!!! Warning "Default configuration"
|
||||
@ -84,27 +86,27 @@ You can now access the UI by typing localhost:8080 in your browser.
|
||||
|
||||
#### Monitoring the bot
|
||||
|
||||
You can check for running instances with `docker-compose ps`.
|
||||
You can check for running instances with `docker compose ps`.
|
||||
This should list the service `freqtrade` as `running`. If that's not the case, best check the logs (see next point).
|
||||
|
||||
#### Docker-compose logs
|
||||
#### Docker compose logs
|
||||
|
||||
Logs will be written to: `user_data/logs/freqtrade.log`.
|
||||
You can also check the latest log with the command `docker-compose logs -f`.
|
||||
You can also check the latest log with the command `docker compose logs -f`.
|
||||
|
||||
#### Database
|
||||
|
||||
The database will be located at: `user_data/tradesv3.sqlite`
|
||||
|
||||
#### Updating freqtrade with docker-compose
|
||||
#### Updating freqtrade with docker
|
||||
|
||||
Updating freqtrade when using `docker-compose` is as simple as running the following 2 commands:
|
||||
Updating freqtrade when using `docker` is as simple as running the following 2 commands:
|
||||
|
||||
``` bash
|
||||
# Download the latest image
|
||||
docker-compose pull
|
||||
docker compose pull
|
||||
# Restart the image
|
||||
docker-compose up -d
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
This will first pull the latest image, and will then restart the container with the just pulled version.
|
||||
@ -116,43 +118,43 @@ This will first pull the latest image, and will then restart the container with
|
||||
|
||||
Advanced users may edit the docker-compose file further to include all possible options or arguments.
|
||||
|
||||
All freqtrade arguments will be available by running `docker-compose run --rm freqtrade <command> <optional arguments>`.
|
||||
All freqtrade arguments will be available by running `docker compose run --rm freqtrade <command> <optional arguments>`.
|
||||
|
||||
!!! Warning "`docker-compose` for trade commands"
|
||||
Trade commands (`freqtrade trade <...>`) should not be ran via `docker-compose run` - but should use `docker-compose up -d` instead.
|
||||
!!! Warning "`docker compose` for trade commands"
|
||||
Trade commands (`freqtrade trade <...>`) should not be ran via `docker compose run` - but should use `docker compose up -d` instead.
|
||||
This makes sure that the container is properly started (including port forwardings) and will make sure that the container will restart after a system reboot.
|
||||
If you intend to use freqUI, please also ensure to adjust the [configuration accordingly](rest-api.md#configuration-with-docker), otherwise the UI will not be available.
|
||||
|
||||
!!! Note "`docker-compose run --rm`"
|
||||
!!! Note "`docker compose run --rm`"
|
||||
Including `--rm` will remove the container after completion, and is highly recommended for all modes except trading mode (running with `freqtrade trade` command).
|
||||
|
||||
??? Note "Using docker without docker-compose"
|
||||
"`docker-compose run --rm`" will require a compose file to be provided.
|
||||
??? Note "Using docker without docker"
|
||||
"`docker compose run --rm`" will require a compose file to be provided.
|
||||
Some freqtrade commands that don't require authentication such as `list-pairs` can be run with "`docker run --rm`" instead.
|
||||
For example `docker run --rm freqtradeorg/freqtrade:stable list-pairs --exchange binance --quote BTC --print-json`.
|
||||
This can be useful for fetching exchange information to add to your `config.json` without affecting your running containers.
|
||||
|
||||
#### Example: Download data with docker-compose
|
||||
#### Example: Download data with docker
|
||||
|
||||
Download backtesting data for 5 days for the pair ETH/BTC and 1h timeframe from Binance. The data will be stored in the directory `user_data/data/` on the host.
|
||||
|
||||
``` bash
|
||||
docker-compose run --rm freqtrade download-data --pairs ETH/BTC --exchange binance --days 5 -t 1h
|
||||
docker compose run --rm freqtrade download-data --pairs ETH/BTC --exchange binance --days 5 -t 1h
|
||||
```
|
||||
|
||||
Head over to the [Data Downloading Documentation](data-download.md) for more details on downloading data.
|
||||
|
||||
#### Example: Backtest with docker-compose
|
||||
#### Example: Backtest with docker
|
||||
|
||||
Run backtesting in docker-containers for SampleStrategy and specified timerange of historical data, on 5m timeframe:
|
||||
|
||||
``` bash
|
||||
docker-compose run --rm freqtrade backtesting --config user_data/config.json --strategy SampleStrategy --timerange 20190801-20191001 -i 5m
|
||||
docker compose run --rm freqtrade backtesting --config user_data/config.json --strategy SampleStrategy --timerange 20190801-20191001 -i 5m
|
||||
```
|
||||
|
||||
Head over to the [Backtesting Documentation](backtesting.md) to learn more.
|
||||
|
||||
### Additional dependencies with docker-compose
|
||||
### Additional dependencies with docker
|
||||
|
||||
If your strategy requires dependencies not included in the default image - it will be necessary to build the image on your host.
|
||||
For this, please create a Dockerfile containing installation steps for the additional dependencies (have a look at [docker/Dockerfile.custom](https://github.com/freqtrade/freqtrade/blob/develop/docker/Dockerfile.custom) for an example).
|
||||
@ -166,15 +168,15 @@ You'll then also need to modify the `docker-compose.yml` file and uncomment the
|
||||
dockerfile: "./Dockerfile.<yourextension>"
|
||||
```
|
||||
|
||||
You can then run `docker-compose build --pull` to build the docker image, and run it using the commands described above.
|
||||
You can then run `docker compose build --pull` to build the docker image, and run it using the commands described above.
|
||||
|
||||
### Plotting with docker-compose
|
||||
### Plotting with docker
|
||||
|
||||
Commands `freqtrade plot-profit` and `freqtrade plot-dataframe` ([Documentation](plotting.md)) are available by changing the image to `*_plot` in your docker-compose.yml file.
|
||||
You can then use these commands as follows:
|
||||
|
||||
``` bash
|
||||
docker-compose run --rm freqtrade plot-dataframe --strategy AwesomeStrategy -p BTC/ETH --timerange=20180801-20180805
|
||||
docker compose run --rm freqtrade plot-dataframe --strategy AwesomeStrategy -p BTC/ETH --timerange=20180801-20180805
|
||||
```
|
||||
|
||||
The output will be stored in the `user_data/plot` directory, and can be opened with any modern browser.
|
||||
@ -185,7 +187,7 @@ Freqtrade provides a docker-compose file which starts up a jupyter lab server.
|
||||
You can run this server using the following command:
|
||||
|
||||
``` bash
|
||||
docker-compose -f docker/docker-compose-jupyter.yml up
|
||||
docker compose -f docker/docker-compose-jupyter.yml up
|
||||
```
|
||||
|
||||
This will create a docker-container running jupyter lab, which will be accessible using `https://127.0.0.1:8888/lab`.
|
||||
@ -194,7 +196,7 @@ Please use the link that's printed in the console after startup for simplified l
|
||||
Since part of this image is built on your machine, it is recommended to rebuild the image from time to time to keep freqtrade (and dependencies) up-to-date.
|
||||
|
||||
``` bash
|
||||
docker-compose -f docker/docker-compose-jupyter.yml build --no-cache
|
||||
docker compose -f docker/docker-compose-jupyter.yml build --no-cache
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
@ -26,10 +26,7 @@ FreqAI is configured through the typical [Freqtrade config file](configuration.m
|
||||
},
|
||||
"data_split_parameters" : {
|
||||
"test_size": 0.25
|
||||
},
|
||||
"model_training_parameters" : {
|
||||
"n_estimators": 100
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -13,12 +13,12 @@ Feel free to use a visual Database editor like SqliteBrowser if you feel more co
|
||||
sudo apt-get install sqlite3
|
||||
```
|
||||
|
||||
### Using sqlite3 via docker-compose
|
||||
### Using sqlite3 via docker
|
||||
|
||||
The freqtrade docker image does contain sqlite3, so you can edit the database without having to install anything on the host system.
|
||||
|
||||
``` bash
|
||||
docker-compose exec freqtrade /bin/bash
|
||||
docker compose exec freqtrade /bin/bash
|
||||
sqlite3 <database-file>.sqlite
|
||||
```
|
||||
|
||||
|
@ -2,12 +2,37 @@
|
||||
|
||||
Debugging a strategy can be time-consuming. Freqtrade offers helper functions to visualize raw data.
|
||||
The following assumes you work with SampleStrategy, data for 5m timeframe from Binance and have downloaded them into the data directory in the default location.
|
||||
Please follow the [documentation](https://www.freqtrade.io/en/stable/data-download/) for more details.
|
||||
|
||||
## Setup
|
||||
|
||||
### Change Working directory to repository root
|
||||
|
||||
|
||||
```python
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
# Change directory
|
||||
# Modify this cell to insure that the output shows the correct path.
|
||||
# Define all paths relative to the project root shown in the cell output
|
||||
project_root = "somedir/freqtrade"
|
||||
i=0
|
||||
try:
|
||||
os.chdirdir(project_root)
|
||||
assert Path('LICENSE').is_file()
|
||||
except:
|
||||
while i<4 and (not Path('LICENSE').is_file()):
|
||||
os.chdir(Path(Path.cwd(), '../'))
|
||||
i+=1
|
||||
project_root = Path.cwd()
|
||||
print(Path.cwd())
|
||||
```
|
||||
|
||||
### Configure Freqtrade environment
|
||||
|
||||
|
||||
```python
|
||||
from freqtrade.configuration import Configuration
|
||||
|
||||
# Customize these according to your needs.
|
||||
@ -15,14 +40,14 @@ from freqtrade.configuration import Configuration
|
||||
# Initialize empty configuration object
|
||||
config = Configuration.from_files([])
|
||||
# Optionally (recommended), use existing configuration file
|
||||
# config = Configuration.from_files(["config.json"])
|
||||
# config = Configuration.from_files(["user_data/config.json"])
|
||||
|
||||
# Define some constants
|
||||
config["timeframe"] = "5m"
|
||||
# Name of the strategy class
|
||||
config["strategy"] = "SampleStrategy"
|
||||
# Location of the data
|
||||
data_location = config['datadir']
|
||||
data_location = config["datadir"]
|
||||
# Pair to analyze - Only use one pair here
|
||||
pair = "BTC/USDT"
|
||||
```
|
||||
@ -36,12 +61,12 @@ from freqtrade.enums import CandleType
|
||||
candles = load_pair_history(datadir=data_location,
|
||||
timeframe=config["timeframe"],
|
||||
pair=pair,
|
||||
data_format = "hdf5",
|
||||
data_format = "json", # Make sure to update this to your data
|
||||
candle_type=CandleType.SPOT,
|
||||
)
|
||||
|
||||
# Confirm success
|
||||
print("Loaded " + str(len(candles)) + f" rows of data for {pair} from {data_location}")
|
||||
print(f"Loaded {len(candles)} rows of data for {pair} from {data_location}")
|
||||
candles.head()
|
||||
```
|
||||
|
||||
|
@ -6,14 +6,14 @@ To update your freqtrade installation, please use one of the below methods, corr
|
||||
Breaking changes / changed behavior will be documented in the changelog that is posted alongside every release.
|
||||
For the develop branch, please follow PR's to avoid being surprised by changes.
|
||||
|
||||
## docker-compose
|
||||
## docker
|
||||
|
||||
!!! Note "Legacy installations using the `master` image"
|
||||
We're switching from master to stable for the release Images - please adjust your docker-file and replace `freqtradeorg/freqtrade:master` with `freqtradeorg/freqtrade:stable`
|
||||
|
||||
``` bash
|
||||
docker-compose pull
|
||||
docker-compose up -d
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Installation via setup script
|
||||
|
@ -652,7 +652,7 @@ Common arguments:
|
||||
|
||||
You can also use webserver mode via docker.
|
||||
Starting a one-off container requires the configuration of the port explicitly, as ports are not exposed by default.
|
||||
You can use `docker-compose run --rm -p 127.0.0.1:8080:8080 freqtrade webserver` to start a one-off container that'll be removed once you stop it. This assumes that port 8080 is still available and no other bot is running on that port.
|
||||
You can use `docker compose run --rm -p 127.0.0.1:8080:8080 freqtrade webserver` to start a one-off container that'll be removed once you stop it. This assumes that port 8080 is still available and no other bot is running on that port.
|
||||
|
||||
Alternatively, you can reconfigure the docker-compose file to have the command updated:
|
||||
|
||||
@ -662,7 +662,7 @@ Alternatively, you can reconfigure the docker-compose file to have the command u
|
||||
--config /freqtrade/user_data/config.json
|
||||
```
|
||||
|
||||
You can now use `docker-compose up` to start the webserver.
|
||||
You can now use `docker compose up` to start the webserver.
|
||||
This assumes that the configuration has a webserver enabled and configured for docker (listening port = `0.0.0.0`).
|
||||
|
||||
!!! Tip
|
||||
|
@ -355,6 +355,13 @@ def _validate_freqai_include_timeframes(conf: Dict[str, Any]) -> None:
|
||||
f"Main timeframe of {main_tf} must be smaller or equal to FreqAI "
|
||||
f"`include_timeframes`.Offending include-timeframes: {', '.join(offending_lines)}")
|
||||
|
||||
# Ensure that the base timeframe is included in the include_timeframes list
|
||||
if main_tf not in freqai_include_timeframes:
|
||||
feature_parameters = conf.get('freqai', {}).get('feature_parameters', {})
|
||||
include_timeframes = [main_tf] + freqai_include_timeframes
|
||||
conf.get('freqai', {}).get('feature_parameters', {}) \
|
||||
.update({**feature_parameters, 'include_timeframes': include_timeframes})
|
||||
|
||||
|
||||
def _validate_freqai_backtest(conf: Dict[str, Any]) -> None:
|
||||
if conf.get('runmode', RunMode.OTHER) == RunMode.BACKTEST:
|
||||
|
@ -608,9 +608,8 @@ CONF_SCHEMA = {
|
||||
"backtest_period_days",
|
||||
"identifier",
|
||||
"feature_parameters",
|
||||
"data_split_parameters",
|
||||
"model_training_parameters"
|
||||
]
|
||||
"data_split_parameters"
|
||||
]
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ from gym.utils import seeding
|
||||
from pandas import DataFrame
|
||||
|
||||
from freqtrade.data.dataprovider import DataProvider
|
||||
from freqtrade.enums import RunMode
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -78,6 +79,12 @@ class BaseEnvironment(gym.Env):
|
||||
# set here to default 5Ac, but all children envs can override this
|
||||
self.actions: Type[Enum] = BaseActions
|
||||
self.tensorboard_metrics: dict = {}
|
||||
self.live: bool = False
|
||||
if dp:
|
||||
self.live = dp.runmode in (RunMode.DRY_RUN, RunMode.LIVE)
|
||||
if not self.live and self.add_state_info:
|
||||
self.add_state_info = False
|
||||
logger.warning("add_state_info is not available in backtesting. Deactivating.")
|
||||
|
||||
def reset_env(self, df: DataFrame, prices: DataFrame, window_size: int,
|
||||
reward_kwargs: dict, starting_point=True):
|
||||
@ -205,7 +212,7 @@ class BaseEnvironment(gym.Env):
|
||||
"""
|
||||
features_window = self.signal_features[(
|
||||
self._current_tick - self.window_size):self._current_tick]
|
||||
if self.add_state_info:
|
||||
if self.add_state_info and self.live:
|
||||
features_and_state = DataFrame(np.zeros((len(features_window), 3)),
|
||||
columns=['current_profit_pct',
|
||||
'position',
|
||||
|
@ -61,7 +61,7 @@ class ReinforcementLearner(BaseReinforcementLearningModel):
|
||||
model = self.MODELCLASS(self.policy_type, self.train_env, policy_kwargs=policy_kwargs,
|
||||
tensorboard_log=Path(
|
||||
dk.full_path / "tensorboard" / dk.pair.split('/')[0]),
|
||||
**self.freqai_info['model_training_parameters']
|
||||
**self.freqai_info.get('model_training_parameters', {})
|
||||
)
|
||||
else:
|
||||
logger.info('Continual training activated - starting training from previously '
|
||||
|
@ -218,7 +218,7 @@ class VolumePairList(IPairList):
|
||||
else:
|
||||
filtered_tickers[i]['quoteVolume'] = 0
|
||||
else:
|
||||
# Tickers mode - filter based on incomming pairlist.
|
||||
# Tickers mode - filter based on incoming pairlist.
|
||||
filtered_tickers = [v for k, v in tickers.items() if k in pairlist]
|
||||
|
||||
if self._min_value > 0:
|
||||
|
@ -7,14 +7,17 @@
|
||||
"# Strategy analysis example\n",
|
||||
"\n",
|
||||
"Debugging a strategy can be time-consuming. Freqtrade offers helper functions to visualize raw data.\n",
|
||||
"The following assumes you work with SampleStrategy, data for 5m timeframe from Binance and have downloaded them into the data directory in the default location."
|
||||
"The following assumes you work with SampleStrategy, data for 5m timeframe from Binance and have downloaded them into the data directory in the default location.\n",
|
||||
"Please follow the [documentation](https://www.freqtrade.io/en/stable/data-download/) for more details."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Setup"
|
||||
"## Setup\n",
|
||||
"\n",
|
||||
"### Change Working directory to repository root"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -23,7 +26,38 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"from pathlib import Path\n",
|
||||
"\n",
|
||||
"# Change directory\n",
|
||||
"# Modify this cell to insure that the output shows the correct path.\n",
|
||||
"# Define all paths relative to the project root shown in the cell output\n",
|
||||
"project_root = \"somedir/freqtrade\"\n",
|
||||
"i=0\n",
|
||||
"try:\n",
|
||||
" os.chdirdir(project_root)\n",
|
||||
" assert Path('LICENSE').is_file()\n",
|
||||
"except:\n",
|
||||
" while i<4 and (not Path('LICENSE').is_file()):\n",
|
||||
" os.chdir(Path(Path.cwd(), '../'))\n",
|
||||
" i+=1\n",
|
||||
" project_root = Path.cwd()\n",
|
||||
"print(Path.cwd())"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Configure Freqtrade environment"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from freqtrade.configuration import Configuration\n",
|
||||
"\n",
|
||||
"# Customize these according to your needs.\n",
|
||||
@ -31,14 +65,14 @@
|
||||
"# Initialize empty configuration object\n",
|
||||
"config = Configuration.from_files([])\n",
|
||||
"# Optionally (recommended), use existing configuration file\n",
|
||||
"# config = Configuration.from_files([\"config.json\"])\n",
|
||||
"# config = Configuration.from_files([\"user_data/config.json\"])\n",
|
||||
"\n",
|
||||
"# Define some constants\n",
|
||||
"config[\"timeframe\"] = \"5m\"\n",
|
||||
"# Name of the strategy class\n",
|
||||
"config[\"strategy\"] = \"SampleStrategy\"\n",
|
||||
"# Location of the data\n",
|
||||
"data_location = config['datadir']\n",
|
||||
"data_location = config[\"datadir\"]\n",
|
||||
"# Pair to analyze - Only use one pair here\n",
|
||||
"pair = \"BTC/USDT\""
|
||||
]
|
||||
@ -56,12 +90,12 @@
|
||||
"candles = load_pair_history(datadir=data_location,\n",
|
||||
" timeframe=config[\"timeframe\"],\n",
|
||||
" pair=pair,\n",
|
||||
" data_format = \"hdf5\",\n",
|
||||
" data_format = \"json\", # Make sure to update this to your data\n",
|
||||
" candle_type=CandleType.SPOT,\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"# Confirm success\n",
|
||||
"print(\"Loaded \" + str(len(candles)) + f\" rows of data for {pair} from {data_location}\")\n",
|
||||
"print(f\"Loaded {len(candles)} rows of data for {pair} from {data_location}\")\n",
|
||||
"candles.head()"
|
||||
]
|
||||
},
|
||||
@ -365,7 +399,7 @@
|
||||
"metadata": {
|
||||
"file_extension": ".py",
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.9.7 64-bit ('trade_397')",
|
||||
"display_name": "Python 3.9.7 64-bit",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
|
@ -224,8 +224,13 @@ class TestCCXTExchange():
|
||||
for val in [1, 2, 5, 25, 100]:
|
||||
l2 = exchange.fetch_l2_order_book(pair, val)
|
||||
if not l2_limit_range or val in l2_limit_range:
|
||||
assert len(l2['asks']) == val
|
||||
assert len(l2['bids']) == val
|
||||
if val > 50:
|
||||
# Orderbooks are not always this deep.
|
||||
assert val - 5 < len(l2['asks']) <= val
|
||||
assert val - 5 < len(l2['bids']) <= val
|
||||
else:
|
||||
assert len(l2['asks']) == val
|
||||
assert len(l2['bids']) == val
|
||||
else:
|
||||
next_limit = exchange.get_next_limit_in_list(
|
||||
val, l2_limit_range, l2_limit_range_required)
|
||||
|
@ -12,6 +12,7 @@ from unittest.mock import ANY, MagicMock
|
||||
|
||||
import arrow
|
||||
import pytest
|
||||
import time_machine
|
||||
from pandas import DataFrame
|
||||
from telegram import Chat, Message, ReplyKeyboardMarkup, Update
|
||||
from telegram.error import BadRequest, NetworkError, TelegramError
|
||||
@ -1906,119 +1907,120 @@ def test_send_msg_entry_fill_notification(default_conf, mocker, message_type, en
|
||||
|
||||
def test_send_msg_sell_notification(default_conf, mocker) -> None:
|
||||
|
||||
telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf)
|
||||
with time_machine.travel("2022-09-01 05:00:00 +00:00", tick=False):
|
||||
telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf)
|
||||
|
||||
old_convamount = telegram._rpc._fiat_converter.convert_amount
|
||||
telegram._rpc._fiat_converter.convert_amount = lambda a, b, c: -24.812
|
||||
telegram.send_msg({
|
||||
'type': RPCMessageType.EXIT,
|
||||
'trade_id': 1,
|
||||
'exchange': 'Binance',
|
||||
'pair': 'KEY/ETH',
|
||||
'leverage': 1.0,
|
||||
'direction': 'Long',
|
||||
'gain': 'loss',
|
||||
'order_rate': 3.201e-05,
|
||||
'amount': 1333.3333333333335,
|
||||
'order_type': 'market',
|
||||
'open_rate': 7.5e-05,
|
||||
'current_rate': 3.201e-05,
|
||||
'profit_amount': -0.05746268,
|
||||
'profit_ratio': -0.57405275,
|
||||
'stake_currency': 'ETH',
|
||||
'fiat_currency': 'USD',
|
||||
'enter_tag': 'buy_signal1',
|
||||
'exit_reason': ExitType.STOP_LOSS.value,
|
||||
'open_date': arrow.utcnow().shift(hours=-1),
|
||||
'close_date': arrow.utcnow(),
|
||||
})
|
||||
assert msg_mock.call_args[0][0] == (
|
||||
'\N{WARNING SIGN} *Binance (dry):* Exiting KEY/ETH (#1)\n'
|
||||
'*Unrealized Profit:* `-57.41% (loss: -0.05746268 ETH / -24.812 USD)`\n'
|
||||
'*Enter Tag:* `buy_signal1`\n'
|
||||
'*Exit Reason:* `stop_loss`\n'
|
||||
'*Direction:* `Long`\n'
|
||||
'*Amount:* `1333.33333333`\n'
|
||||
'*Open Rate:* `0.00007500`\n'
|
||||
'*Current Rate:* `0.00003201`\n'
|
||||
'*Exit Rate:* `0.00003201`\n'
|
||||
'*Duration:* `1:00:00 (60.0 min)`'
|
||||
)
|
||||
|
||||
msg_mock.reset_mock()
|
||||
telegram.send_msg({
|
||||
'type': RPCMessageType.EXIT,
|
||||
'trade_id': 1,
|
||||
'exchange': 'Binance',
|
||||
'pair': 'KEY/ETH',
|
||||
'direction': 'Long',
|
||||
'gain': 'loss',
|
||||
'order_rate': 3.201e-05,
|
||||
'amount': 1333.3333333333335,
|
||||
'order_type': 'market',
|
||||
'open_rate': 7.5e-05,
|
||||
'current_rate': 3.201e-05,
|
||||
'cumulative_profit': -0.15746268,
|
||||
'profit_amount': -0.05746268,
|
||||
'profit_ratio': -0.57405275,
|
||||
'stake_currency': 'ETH',
|
||||
'fiat_currency': 'USD',
|
||||
'enter_tag': 'buy_signal1',
|
||||
'exit_reason': ExitType.STOP_LOSS.value,
|
||||
'open_date': arrow.utcnow().shift(days=-1, hours=-2, minutes=-30),
|
||||
'close_date': arrow.utcnow(),
|
||||
'stake_amount': 0.01,
|
||||
'sub_trade': True,
|
||||
})
|
||||
assert msg_mock.call_args[0][0] == (
|
||||
'\N{WARNING SIGN} *Binance (dry):* Exiting KEY/ETH (#1)\n'
|
||||
'*Unrealized Sub Profit:* `-57.41% (loss: -0.05746268 ETH / -24.812 USD)`\n'
|
||||
'*Cumulative Profit:* (`-0.15746268 ETH / -24.812 USD`)\n'
|
||||
'*Enter Tag:* `buy_signal1`\n'
|
||||
'*Exit Reason:* `stop_loss`\n'
|
||||
'*Direction:* `Long`\n'
|
||||
'*Amount:* `1333.33333333`\n'
|
||||
'*Open Rate:* `0.00007500`\n'
|
||||
'*Current Rate:* `0.00003201`\n'
|
||||
'*Exit Rate:* `0.00003201`\n'
|
||||
'*Remaining:* `(0.01 ETH, -24.812 USD)`'
|
||||
old_convamount = telegram._rpc._fiat_converter.convert_amount
|
||||
telegram._rpc._fiat_converter.convert_amount = lambda a, b, c: -24.812
|
||||
telegram.send_msg({
|
||||
'type': RPCMessageType.EXIT,
|
||||
'trade_id': 1,
|
||||
'exchange': 'Binance',
|
||||
'pair': 'KEY/ETH',
|
||||
'leverage': 1.0,
|
||||
'direction': 'Long',
|
||||
'gain': 'loss',
|
||||
'order_rate': 3.201e-05,
|
||||
'amount': 1333.3333333333335,
|
||||
'order_type': 'market',
|
||||
'open_rate': 7.5e-05,
|
||||
'current_rate': 3.201e-05,
|
||||
'profit_amount': -0.05746268,
|
||||
'profit_ratio': -0.57405275,
|
||||
'stake_currency': 'ETH',
|
||||
'fiat_currency': 'USD',
|
||||
'enter_tag': 'buy_signal1',
|
||||
'exit_reason': ExitType.STOP_LOSS.value,
|
||||
'open_date': arrow.utcnow().shift(hours=-1),
|
||||
'close_date': arrow.utcnow(),
|
||||
})
|
||||
assert msg_mock.call_args[0][0] == (
|
||||
'\N{WARNING SIGN} *Binance (dry):* Exiting KEY/ETH (#1)\n'
|
||||
'*Unrealized Profit:* `-57.41% (loss: -0.05746268 ETH / -24.812 USD)`\n'
|
||||
'*Enter Tag:* `buy_signal1`\n'
|
||||
'*Exit Reason:* `stop_loss`\n'
|
||||
'*Direction:* `Long`\n'
|
||||
'*Amount:* `1333.33333333`\n'
|
||||
'*Open Rate:* `0.00007500`\n'
|
||||
'*Current Rate:* `0.00003201`\n'
|
||||
'*Exit Rate:* `0.00003201`\n'
|
||||
'*Duration:* `1:00:00 (60.0 min)`'
|
||||
)
|
||||
|
||||
msg_mock.reset_mock()
|
||||
telegram.send_msg({
|
||||
'type': RPCMessageType.EXIT,
|
||||
'trade_id': 1,
|
||||
'exchange': 'Binance',
|
||||
'pair': 'KEY/ETH',
|
||||
'direction': 'Long',
|
||||
'gain': 'loss',
|
||||
'order_rate': 3.201e-05,
|
||||
'amount': 1333.3333333333335,
|
||||
'order_type': 'market',
|
||||
'open_rate': 7.5e-05,
|
||||
'current_rate': 3.201e-05,
|
||||
'profit_amount': -0.05746268,
|
||||
'profit_ratio': -0.57405275,
|
||||
'stake_currency': 'ETH',
|
||||
'enter_tag': 'buy_signal1',
|
||||
'exit_reason': ExitType.STOP_LOSS.value,
|
||||
'open_date': arrow.utcnow().shift(days=-1, hours=-2, minutes=-30),
|
||||
'close_date': arrow.utcnow(),
|
||||
})
|
||||
assert msg_mock.call_args[0][0] == (
|
||||
'\N{WARNING SIGN} *Binance (dry):* Exiting KEY/ETH (#1)\n'
|
||||
'*Unrealized Profit:* `-57.41% (loss: -0.05746268 ETH)`\n'
|
||||
'*Enter Tag:* `buy_signal1`\n'
|
||||
'*Exit Reason:* `stop_loss`\n'
|
||||
'*Direction:* `Long`\n'
|
||||
'*Amount:* `1333.33333333`\n'
|
||||
'*Open Rate:* `0.00007500`\n'
|
||||
'*Current Rate:* `0.00003201`\n'
|
||||
'*Exit Rate:* `0.00003201`\n'
|
||||
'*Duration:* `1 day, 2:30:00 (1590.0 min)`'
|
||||
)
|
||||
# Reset singleton function to avoid random breaks
|
||||
telegram._rpc._fiat_converter.convert_amount = old_convamount
|
||||
msg_mock.reset_mock()
|
||||
telegram.send_msg({
|
||||
'type': RPCMessageType.EXIT,
|
||||
'trade_id': 1,
|
||||
'exchange': 'Binance',
|
||||
'pair': 'KEY/ETH',
|
||||
'direction': 'Long',
|
||||
'gain': 'loss',
|
||||
'order_rate': 3.201e-05,
|
||||
'amount': 1333.3333333333335,
|
||||
'order_type': 'market',
|
||||
'open_rate': 7.5e-05,
|
||||
'current_rate': 3.201e-05,
|
||||
'cumulative_profit': -0.15746268,
|
||||
'profit_amount': -0.05746268,
|
||||
'profit_ratio': -0.57405275,
|
||||
'stake_currency': 'ETH',
|
||||
'fiat_currency': 'USD',
|
||||
'enter_tag': 'buy_signal1',
|
||||
'exit_reason': ExitType.STOP_LOSS.value,
|
||||
'open_date': arrow.utcnow().shift(days=-1, hours=-2, minutes=-30),
|
||||
'close_date': arrow.utcnow(),
|
||||
'stake_amount': 0.01,
|
||||
'sub_trade': True,
|
||||
})
|
||||
assert msg_mock.call_args[0][0] == (
|
||||
'\N{WARNING SIGN} *Binance (dry):* Exiting KEY/ETH (#1)\n'
|
||||
'*Unrealized Sub Profit:* `-57.41% (loss: -0.05746268 ETH / -24.812 USD)`\n'
|
||||
'*Cumulative Profit:* (`-0.15746268 ETH / -24.812 USD`)\n'
|
||||
'*Enter Tag:* `buy_signal1`\n'
|
||||
'*Exit Reason:* `stop_loss`\n'
|
||||
'*Direction:* `Long`\n'
|
||||
'*Amount:* `1333.33333333`\n'
|
||||
'*Open Rate:* `0.00007500`\n'
|
||||
'*Current Rate:* `0.00003201`\n'
|
||||
'*Exit Rate:* `0.00003201`\n'
|
||||
'*Remaining:* `(0.01 ETH, -24.812 USD)`'
|
||||
)
|
||||
|
||||
msg_mock.reset_mock()
|
||||
telegram.send_msg({
|
||||
'type': RPCMessageType.EXIT,
|
||||
'trade_id': 1,
|
||||
'exchange': 'Binance',
|
||||
'pair': 'KEY/ETH',
|
||||
'direction': 'Long',
|
||||
'gain': 'loss',
|
||||
'order_rate': 3.201e-05,
|
||||
'amount': 1333.3333333333335,
|
||||
'order_type': 'market',
|
||||
'open_rate': 7.5e-05,
|
||||
'current_rate': 3.201e-05,
|
||||
'profit_amount': -0.05746268,
|
||||
'profit_ratio': -0.57405275,
|
||||
'stake_currency': 'ETH',
|
||||
'enter_tag': 'buy_signal1',
|
||||
'exit_reason': ExitType.STOP_LOSS.value,
|
||||
'open_date': arrow.utcnow().shift(days=-1, hours=-2, minutes=-30),
|
||||
'close_date': arrow.utcnow(),
|
||||
})
|
||||
assert msg_mock.call_args[0][0] == (
|
||||
'\N{WARNING SIGN} *Binance (dry):* Exiting KEY/ETH (#1)\n'
|
||||
'*Unrealized Profit:* `-57.41% (loss: -0.05746268 ETH)`\n'
|
||||
'*Enter Tag:* `buy_signal1`\n'
|
||||
'*Exit Reason:* `stop_loss`\n'
|
||||
'*Direction:* `Long`\n'
|
||||
'*Amount:* `1333.33333333`\n'
|
||||
'*Open Rate:* `0.00007500`\n'
|
||||
'*Current Rate:* `0.00003201`\n'
|
||||
'*Exit Rate:* `0.00003201`\n'
|
||||
'*Duration:* `1 day, 2:30:00 (1590.0 min)`'
|
||||
)
|
||||
# Reset singleton function to avoid random breaks
|
||||
telegram._rpc._fiat_converter.convert_amount = old_convamount
|
||||
|
||||
|
||||
def test_send_msg_sell_cancel_notification(default_conf, mocker) -> None:
|
||||
@ -2065,41 +2067,42 @@ def test_send_msg_sell_fill_notification(default_conf, mocker, direction,
|
||||
default_conf['telegram']['notification_settings']['exit_fill'] = 'on'
|
||||
telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf)
|
||||
|
||||
telegram.send_msg({
|
||||
'type': RPCMessageType.EXIT_FILL,
|
||||
'trade_id': 1,
|
||||
'exchange': 'Binance',
|
||||
'pair': 'KEY/ETH',
|
||||
'leverage': leverage,
|
||||
'direction': direction,
|
||||
'gain': 'loss',
|
||||
'limit': 3.201e-05,
|
||||
'amount': 1333.3333333333335,
|
||||
'order_type': 'market',
|
||||
'open_rate': 7.5e-05,
|
||||
'close_rate': 3.201e-05,
|
||||
'profit_amount': -0.05746268,
|
||||
'profit_ratio': -0.57405275,
|
||||
'stake_currency': 'ETH',
|
||||
'enter_tag': enter_signal,
|
||||
'exit_reason': ExitType.STOP_LOSS.value,
|
||||
'open_date': arrow.utcnow().shift(days=-1, hours=-2, minutes=-30),
|
||||
'close_date': arrow.utcnow(),
|
||||
})
|
||||
with time_machine.travel("2022-09-01 05:00:00 +00:00", tick=False):
|
||||
telegram.send_msg({
|
||||
'type': RPCMessageType.EXIT_FILL,
|
||||
'trade_id': 1,
|
||||
'exchange': 'Binance',
|
||||
'pair': 'KEY/ETH',
|
||||
'leverage': leverage,
|
||||
'direction': direction,
|
||||
'gain': 'loss',
|
||||
'limit': 3.201e-05,
|
||||
'amount': 1333.3333333333335,
|
||||
'order_type': 'market',
|
||||
'open_rate': 7.5e-05,
|
||||
'close_rate': 3.201e-05,
|
||||
'profit_amount': -0.05746268,
|
||||
'profit_ratio': -0.57405275,
|
||||
'stake_currency': 'ETH',
|
||||
'enter_tag': enter_signal,
|
||||
'exit_reason': ExitType.STOP_LOSS.value,
|
||||
'open_date': arrow.utcnow().shift(days=-1, hours=-2, minutes=-30),
|
||||
'close_date': arrow.utcnow(),
|
||||
})
|
||||
|
||||
leverage_text = f'*Leverage:* `{leverage}`\n' if leverage and leverage != 1.0 else ''
|
||||
assert msg_mock.call_args[0][0] == (
|
||||
'\N{WARNING SIGN} *Binance (dry):* Exited KEY/ETH (#1)\n'
|
||||
'*Profit:* `-57.41% (loss: -0.05746268 ETH)`\n'
|
||||
f'*Enter Tag:* `{enter_signal}`\n'
|
||||
'*Exit Reason:* `stop_loss`\n'
|
||||
f"*Direction:* `{direction}`\n"
|
||||
f"{leverage_text}"
|
||||
'*Amount:* `1333.33333333`\n'
|
||||
'*Open Rate:* `0.00007500`\n'
|
||||
'*Exit Rate:* `0.00003201`\n'
|
||||
'*Duration:* `1 day, 2:30:00 (1590.0 min)`'
|
||||
)
|
||||
leverage_text = f'*Leverage:* `{leverage}`\n' if leverage and leverage != 1.0 else ''
|
||||
assert msg_mock.call_args[0][0] == (
|
||||
'\N{WARNING SIGN} *Binance (dry):* Exited KEY/ETH (#1)\n'
|
||||
'*Profit:* `-57.41% (loss: -0.05746268 ETH)`\n'
|
||||
f'*Enter Tag:* `{enter_signal}`\n'
|
||||
'*Exit Reason:* `stop_loss`\n'
|
||||
f"*Direction:* `{direction}`\n"
|
||||
f"{leverage_text}"
|
||||
'*Amount:* `1333.33333333`\n'
|
||||
'*Open Rate:* `0.00007500`\n'
|
||||
'*Exit Rate:* `0.00003201`\n'
|
||||
'*Duration:* `1 day, 2:30:00 (1590.0 min)`'
|
||||
)
|
||||
|
||||
|
||||
def test_send_msg_status_notification(default_conf, mocker) -> None:
|
||||
|
@ -1046,8 +1046,13 @@ def test__validate_freqai_include_timeframes(default_conf, caplog) -> None:
|
||||
# Validation pass
|
||||
conf.update({'timeframe': '1m'})
|
||||
validate_config_consistency(conf)
|
||||
conf.update({'analyze_per_epoch': True})
|
||||
|
||||
# Ensure base timeframe is in include_timeframes
|
||||
conf['freqai']['feature_parameters']['include_timeframes'] = ["5m", "15m"]
|
||||
validate_config_consistency(conf)
|
||||
assert conf['freqai']['feature_parameters']['include_timeframes'] == ["1m", "5m", "15m"]
|
||||
|
||||
conf.update({'analyze_per_epoch': True})
|
||||
with pytest.raises(OperationalException,
|
||||
match=r"Using analyze-per-epoch .* not supported with a FreqAI strategy."):
|
||||
validate_config_consistency(conf)
|
||||
|
Loading…
Reference in New Issue
Block a user