Compare commits
3 Commits
2024.7
...
feat/freqa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
755041c134 | ||
|
|
98c62dad91 | ||
|
|
52ee7fc981 |
21
.devcontainer/Dockerfile
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
FROM freqtradeorg/freqtrade:develop
|
||||||
|
|
||||||
|
USER root
|
||||||
|
# Install dependencies
|
||||||
|
COPY requirements-dev.txt /freqtrade/
|
||||||
|
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get -y install git mercurial sudo vim build-essential \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& mkdir -p /home/ftuser/.vscode-server /home/ftuser/.vscode-server-insiders /home/ftuser/commandhistory \
|
||||||
|
&& echo "export PROMPT_COMMAND='history -a'" >> /home/ftuser/.bashrc \
|
||||||
|
&& echo "export HISTFILE=~/commandhistory/.bash_history" >> /home/ftuser/.bashrc \
|
||||||
|
&& chown ftuser:ftuser -R /home/ftuser/.local/ \
|
||||||
|
&& chown ftuser: -R /home/ftuser/
|
||||||
|
|
||||||
|
USER ftuser
|
||||||
|
|
||||||
|
RUN pip install --user autopep8 -r docs/requirements-docs.txt -r requirements-dev.txt --no-cache-dir
|
||||||
|
|
||||||
|
# Empty the ENTRYPOINT to allow all commands
|
||||||
|
ENTRYPOINT []
|
||||||
@@ -1,44 +1,39 @@
|
|||||||
{
|
{
|
||||||
"name": "freqtrade Develop",
|
"name": "freqtrade Develop",
|
||||||
"image": "ghcr.io/freqtrade/freqtrade-devcontainer:latest",
|
"build": {
|
||||||
|
"dockerfile": "Dockerfile",
|
||||||
|
"context": ".."
|
||||||
|
},
|
||||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||||
"forwardPorts": [
|
"forwardPorts": [
|
||||||
8080
|
8080
|
||||||
],
|
],
|
||||||
"workspaceMount": "source=${localWorkspaceFolder},target=/workspaces/freqtrade,type=bind,consistency=cached",
|
"mounts": [
|
||||||
|
"source=freqtrade-bashhistory,target=/home/ftuser/commandhistory,type=volume"
|
||||||
|
],
|
||||||
// Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root.
|
// Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root.
|
||||||
"remoteUser": "ftuser",
|
"remoteUser": "ftuser",
|
||||||
"onCreateCommand": "pip install --user -e .",
|
|
||||||
"postCreateCommand": "freqtrade create-userdir --userdir user_data/",
|
"postCreateCommand": "freqtrade create-userdir --userdir user_data/",
|
||||||
"workspaceFolder": "/workspaces/freqtrade",
|
|
||||||
"customizations": {
|
"workspaceFolder": "/freqtrade/",
|
||||||
"vscode": {
|
|
||||||
"settings": {
|
"settings": {
|
||||||
"terminal.integrated.shell.linux": "/bin/bash",
|
"terminal.integrated.shell.linux": "/bin/bash",
|
||||||
"editor.insertSpaces": true,
|
"editor.insertSpaces": true,
|
||||||
"files.trimTrailingWhitespace": true,
|
"files.trimTrailingWhitespace": true,
|
||||||
"[markdown]": {
|
"[markdown]": {
|
||||||
"files.trimTrailingWhitespace": false
|
"files.trimTrailingWhitespace": false,
|
||||||
},
|
},
|
||||||
"python.pythonPath": "/usr/local/bin/python",
|
"python.pythonPath": "/usr/local/bin/python",
|
||||||
"[python]": {
|
},
|
||||||
"editor.codeActionsOnSave": {
|
|
||||||
"source.organizeImports": "explicit"
|
// Add the IDs of extensions you want installed when the container is created.
|
||||||
},
|
"extensions": [
|
||||||
"editor.formatOnSave": true,
|
"ms-python.python",
|
||||||
"editor.defaultFormatter": "charliermarsh.ruff"
|
"ms-python.vscode-pylance",
|
||||||
}
|
"davidanson.vscode-markdownlint",
|
||||||
},
|
"ms-azuretools.vscode-docker",
|
||||||
// Add the IDs of extensions you want installed when the container is created.
|
"vscode-icons-team.vscode-icons",
|
||||||
"extensions": [
|
],
|
||||||
"ms-python.python",
|
|
||||||
"ms-python.vscode-pylance",
|
|
||||||
"charliermarsh.ruff",
|
|
||||||
"davidanson.vscode-markdownlint",
|
|
||||||
"ms-azuretools.vscode-docker",
|
|
||||||
"vscode-icons-team.vscode-icons",
|
|
||||||
"github.vscode-github-actions",
|
|
||||||
],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
21
.github/.devcontainer/Dockerfile
vendored
@@ -1,21 +0,0 @@
|
|||||||
FROM freqtradeorg/freqtrade:develop_freqairl
|
|
||||||
|
|
||||||
USER root
|
|
||||||
# Install dependencies
|
|
||||||
COPY requirements-dev.txt /freqtrade/
|
|
||||||
|
|
||||||
ARG USERNAME=ftuser
|
|
||||||
|
|
||||||
RUN apt-get update \
|
|
||||||
&& apt-get -y install --no-install-recommends apt-utils dialog git ssh vim build-essential zsh \
|
|
||||||
&& apt-get clean \
|
|
||||||
&& mkdir -p /home/${USERNAME}/.vscode-server /home/${USERNAME}/.vscode-server-insiders /home/${USERNAME}/commandhistory \
|
|
||||||
&& chown ${USERNAME}:${USERNAME} -R /home/${USERNAME}/.local/ \
|
|
||||||
&& chown ${USERNAME}: -R /home/${USERNAME}/
|
|
||||||
|
|
||||||
USER ftuser
|
|
||||||
|
|
||||||
RUN pip install --user autopep8 -r docs/requirements-docs.txt -r requirements-dev.txt --no-cache-dir
|
|
||||||
|
|
||||||
# Empty the ENTRYPOINT to allow all commands
|
|
||||||
ENTRYPOINT []
|
|
||||||
12
.github/.devcontainer/devcontainer.json
vendored
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "freqtrade Dev container image builder",
|
|
||||||
"build": {
|
|
||||||
"dockerfile": "Dockerfile",
|
|
||||||
"context": "../../"
|
|
||||||
},
|
|
||||||
"features": {
|
|
||||||
"ghcr.io/devcontainers/features/common-utils:2": {
|
|
||||||
},
|
|
||||||
"ghcr.io/stuartleeks/dev-container-features/shell-history:0.0.3": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -20,7 +20,7 @@ Please do not use bug reports to request new features.
|
|||||||
* Operating system: ____
|
* Operating system: ____
|
||||||
* Python Version: _____ (`python -V`)
|
* Python Version: _____ (`python -V`)
|
||||||
* CCXT version: _____ (`pip freeze | grep ccxt`)
|
* 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.
|
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
@@ -18,7 +18,7 @@ Have you search for this feature before requesting it? It's highly likely that a
|
|||||||
* Operating system: ____
|
* Operating system: ____
|
||||||
* Python Version: _____ (`python -V`)
|
* Python Version: _____ (`python -V`)
|
||||||
* CCXT version: _____ (`pip freeze | grep ccxt`)
|
* 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
|
## Describe the enhancement
|
||||||
|
|||||||
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: ____
|
* Operating system: ____
|
||||||
* Python Version: _____ (`python -V`)
|
* Python Version: _____ (`python -V`)
|
||||||
* CCXT version: _____ (`pip freeze | grep ccxt`)
|
* 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
|
## Your question
|
||||||
|
|
||||||
|
|||||||
14
.github/dependabot.yml
vendored
@@ -10,20 +10,8 @@ updates:
|
|||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: weekly
|
interval: weekly
|
||||||
time: "03:00"
|
open-pull-requests-limit: 10
|
||||||
timezone: "Etc/UTC"
|
|
||||||
open-pull-requests-limit: 15
|
|
||||||
target-branch: develop
|
target-branch: develop
|
||||||
groups:
|
|
||||||
types:
|
|
||||||
patterns:
|
|
||||||
- "types-*"
|
|
||||||
pytest:
|
|
||||||
patterns:
|
|
||||||
- "pytest*"
|
|
||||||
mkdocs:
|
|
||||||
patterns:
|
|
||||||
- "mkdocs*"
|
|
||||||
|
|
||||||
- package-ecosystem: "github-actions"
|
- package-ecosystem: "github-actions"
|
||||||
directory: "/"
|
directory: "/"
|
||||||
|
|||||||
47
.github/workflows/binance-lev-tier-update.yml
vendored
@@ -1,47 +0,0 @@
|
|||||||
name: Binance Leverage tiers update
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "0 3 * * 4"
|
|
||||||
# on demand
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
auto-update:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
environment:
|
|
||||||
name: develop
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: "3.12"
|
|
||||||
|
|
||||||
- name: Install ccxt
|
|
||||||
run: pip install ccxt
|
|
||||||
|
|
||||||
- name: Run leverage tier update
|
|
||||||
env:
|
|
||||||
CI_WEB_PROXY: ${{ secrets.CI_WEB_PROXY }}
|
|
||||||
FREQTRADE__EXCHANGE__KEY: ${{ secrets.BINANCE_EXCHANGE_KEY }}
|
|
||||||
FREQTRADE__EXCHANGE__SECRET: ${{ secrets.BINANCE_EXCHANGE_SECRET }}
|
|
||||||
run: python build_helpers/binance_update_lev_tiers.py
|
|
||||||
|
|
||||||
|
|
||||||
- uses: peter-evans/create-pull-request@v6
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.REPO_SCOPED_TOKEN }}
|
|
||||||
add-paths: freqtrade/exchange/binance_leverage_tiers.json
|
|
||||||
labels: |
|
|
||||||
Tech maintenance
|
|
||||||
Dependencies
|
|
||||||
branch: update/binance-leverage-tiers
|
|
||||||
title: Update Binance Leverage Tiers
|
|
||||||
commit-message: "chore: update pre-commit hooks"
|
|
||||||
committer: Freqtrade Bot <noreply@github.com>
|
|
||||||
body: Update binance leverage tiers.
|
|
||||||
delete-branch: true
|
|
||||||
450
.github/workflows/ci.yml
vendored
@@ -11,39 +11,39 @@ on:
|
|||||||
types: [published]
|
types: [published]
|
||||||
pull_request:
|
pull_request:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 3 * * 4'
|
- cron: '0 5 * * 4'
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: "${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}"
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
permissions:
|
|
||||||
repository-projects: read
|
|
||||||
jobs:
|
jobs:
|
||||||
build-linux:
|
build_linux:
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ "ubuntu-20.04", "ubuntu-22.04", "ubuntu-24.04" ]
|
os: [ ubuntu-18.04, ubuntu-20.04, ubuntu-22.04 ]
|
||||||
python-version: ["3.9", "3.10", "3.11", "3.12"]
|
python-version: ["3.8", "3.9", "3.10"]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
|
|
||||||
- name: Cache_dependencies
|
- name: Cache_dependencies
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v3
|
||||||
id: cache
|
id: cache
|
||||||
with:
|
with:
|
||||||
path: ~/dependencies/
|
path: ~/dependencies/
|
||||||
key: ${{ runner.os }}-dependencies
|
key: ${{ runner.os }}-dependencies
|
||||||
|
|
||||||
- name: pip cache (linux)
|
- name: pip cache (linux)
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v3
|
||||||
|
if: runner.os == 'Linux'
|
||||||
with:
|
with:
|
||||||
path: ~/.cache/pip
|
path: ~/.cache/pip
|
||||||
key: test-${{ matrix.os }}-${{ matrix.python-version }}-pip
|
key: test-${{ matrix.os }}-${{ matrix.python-version }}-pip
|
||||||
@@ -54,25 +54,27 @@ jobs:
|
|||||||
cd build_helpers && ./install_ta-lib.sh ${HOME}/dependencies/; cd ..
|
cd build_helpers && ./install_ta-lib.sh ${HOME}/dependencies/; cd ..
|
||||||
|
|
||||||
- name: Installation - *nix
|
- name: Installation - *nix
|
||||||
|
if: runner.os == 'Linux'
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade "pip<=24.0" wheel
|
python -m pip install --upgrade pip wheel
|
||||||
export LD_LIBRARY_PATH=${HOME}/dependencies/lib:$LD_LIBRARY_PATH
|
export LD_LIBRARY_PATH=${HOME}/dependencies/lib:$LD_LIBRARY_PATH
|
||||||
export TA_LIBRARY_PATH=${HOME}/dependencies/lib
|
export TA_LIBRARY_PATH=${HOME}/dependencies/lib
|
||||||
export TA_INCLUDE_PATH=${HOME}/dependencies/include
|
export TA_INCLUDE_PATH=${HOME}/dependencies/include
|
||||||
pip install -r requirements-dev.txt
|
pip install -r requirements-dev.txt
|
||||||
pip install -e ft_client/
|
|
||||||
pip install -e .
|
pip install -e .
|
||||||
|
|
||||||
- name: Check for version alignment
|
|
||||||
run: |
|
|
||||||
python build_helpers/freqtrade_client_version_align.py
|
|
||||||
|
|
||||||
- name: Tests
|
- name: Tests
|
||||||
run: |
|
run: |
|
||||||
pytest --random-order --cov=freqtrade --cov=freqtrade_client --cov-config=.coveragerc
|
pytest --random-order --cov=freqtrade --cov-config=.coveragerc
|
||||||
|
if: matrix.python-version != '3.9' || matrix.os != 'ubuntu-22.04'
|
||||||
|
|
||||||
|
- name: Tests incl. ccxt compatibility tests
|
||||||
|
run: |
|
||||||
|
pytest --random-order --cov=freqtrade --cov-config=.coveragerc --longrun
|
||||||
|
if: matrix.python-version == '3.9' && matrix.os == 'ubuntu-22.04'
|
||||||
|
|
||||||
- name: Coveralls
|
- name: Coveralls
|
||||||
if: (runner.os == 'Linux' && matrix.python-version == '3.10' && matrix.os == 'ubuntu-22.04')
|
if: (runner.os == 'Linux' && matrix.python-version == '3.9')
|
||||||
env:
|
env:
|
||||||
# Coveralls token. Not used as secret due to github not providing secrets to forked repositories
|
# Coveralls token. Not used as secret due to github not providing secrets to forked repositories
|
||||||
COVERALLS_REPO_TOKEN: 6D1m0xupS3FgutfuGao8keFf9Hc0FpIXu
|
COVERALLS_REPO_TOKEN: 6D1m0xupS3FgutfuGao8keFf9Hc0FpIXu
|
||||||
@@ -80,25 +82,9 @@ jobs:
|
|||||||
# Allow failure for coveralls
|
# Allow failure for coveralls
|
||||||
coveralls || true
|
coveralls || true
|
||||||
|
|
||||||
- name: Run json schema extract
|
|
||||||
# This should be kept before the repository check to ensure that the schema is up-to-date
|
|
||||||
run: |
|
|
||||||
python build_helpers/extract_config_json_schema.py
|
|
||||||
|
|
||||||
- name: Check for repository changes
|
|
||||||
run: |
|
|
||||||
if [ -n "$(git status --porcelain)" ]; then
|
|
||||||
echo "Repository is dirty, changes detected:"
|
|
||||||
git status
|
|
||||||
git diff
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo "Repository is clean, no changes detected."
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Backtesting (multi)
|
- name: Backtesting (multi)
|
||||||
run: |
|
run: |
|
||||||
cp tests/testdata/config.tests.json config.json
|
cp config_examples/config_bittrex.example.json config.json
|
||||||
freqtrade create-userdir --userdir user_data
|
freqtrade create-userdir --userdir user_data
|
||||||
freqtrade new-strategy -s AwesomeStrategy
|
freqtrade new-strategy -s AwesomeStrategy
|
||||||
freqtrade new-strategy -s AwesomeStrategyMin --template minimal
|
freqtrade new-strategy -s AwesomeStrategyMin --template minimal
|
||||||
@@ -106,22 +92,18 @@ jobs:
|
|||||||
|
|
||||||
- name: Hyperopt
|
- name: Hyperopt
|
||||||
run: |
|
run: |
|
||||||
cp tests/testdata/config.tests.json config.json
|
cp config_examples/config_bittrex.example.json config.json
|
||||||
freqtrade create-userdir --userdir user_data
|
freqtrade create-userdir --userdir user_data
|
||||||
freqtrade hyperopt --datadir tests/testdata -e 6 --strategy SampleStrategy --hyperopt-loss SharpeHyperOptLossDaily --print-all
|
freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt-loss SharpeHyperOptLossDaily --print-all
|
||||||
|
|
||||||
|
- name: Flake8
|
||||||
|
run: |
|
||||||
|
flake8
|
||||||
|
|
||||||
- name: Sort imports (isort)
|
- name: Sort imports (isort)
|
||||||
run: |
|
run: |
|
||||||
isort --check .
|
isort --check .
|
||||||
|
|
||||||
- name: Run Ruff
|
|
||||||
run: |
|
|
||||||
ruff check --output-format=github
|
|
||||||
|
|
||||||
- name: Run Ruff format check
|
|
||||||
run: |
|
|
||||||
ruff format --check
|
|
||||||
|
|
||||||
- name: Mypy
|
- name: Mypy
|
||||||
run: |
|
run: |
|
||||||
mypy freqtrade scripts tests
|
mypy freqtrade scripts tests
|
||||||
@@ -134,117 +116,77 @@ jobs:
|
|||||||
details: Freqtrade CI failed on ${{ matrix.os }}
|
details: Freqtrade CI failed on ${{ matrix.os }}
|
||||||
webhookUrl: ${{ secrets.DISCORD_WEBHOOK }}
|
webhookUrl: ${{ secrets.DISCORD_WEBHOOK }}
|
||||||
|
|
||||||
build-macos:
|
build_macos:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ "macos-12", "macos-13", "macos-14" ]
|
os: [ macos-latest ]
|
||||||
python-version: ["3.9", "3.10", "3.11", "3.12"]
|
python-version: ["3.8", "3.9", "3.10"]
|
||||||
exclude:
|
|
||||||
- os: "macos-14"
|
|
||||||
python-version: "3.9"
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
check-latest: true
|
|
||||||
|
|
||||||
- name: Cache_dependencies
|
- name: Cache_dependencies
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v3
|
||||||
id: cache
|
id: cache
|
||||||
with:
|
with:
|
||||||
path: ~/dependencies/
|
path: ~/dependencies/
|
||||||
key: ${{ matrix.os }}-dependencies
|
key: ${{ runner.os }}-dependencies
|
||||||
|
|
||||||
- name: pip cache (macOS)
|
- name: pip cache (macOS)
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v3
|
||||||
|
if: runner.os == 'macOS'
|
||||||
with:
|
with:
|
||||||
path: ~/Library/Caches/pip
|
path: ~/Library/Caches/pip
|
||||||
key: ${{ matrix.os }}-${{ matrix.python-version }}-pip
|
key: test-${{ matrix.os }}-${{ matrix.python-version }}-pip
|
||||||
|
|
||||||
- name: TA binary *nix
|
- name: TA binary *nix
|
||||||
if: steps.cache.outputs.cache-hit != 'true'
|
if: steps.cache.outputs.cache-hit != 'true'
|
||||||
run: |
|
run: |
|
||||||
cd build_helpers && ./install_ta-lib.sh ${HOME}/dependencies/; cd ..
|
cd build_helpers && ./install_ta-lib.sh ${HOME}/dependencies/; cd ..
|
||||||
|
|
||||||
- name: Installation - macOS (Brew)
|
- name: Installation - macOS
|
||||||
|
if: runner.os == 'macOS'
|
||||||
run: |
|
run: |
|
||||||
# brew update
|
brew update
|
||||||
# TODO: Should be the brew upgrade
|
brew install hdf5 c-blosc
|
||||||
# homebrew fails to update python due to unlinking failures
|
python -m pip install --upgrade pip wheel
|
||||||
# https://github.com/actions/runner-images/issues/6817
|
|
||||||
rm /usr/local/bin/2to3 || true
|
|
||||||
rm /usr/local/bin/2to3-3.11 || true
|
|
||||||
rm /usr/local/bin/2to3-3.12 || true
|
|
||||||
rm /usr/local/bin/idle3 || true
|
|
||||||
rm /usr/local/bin/idle3.11 || true
|
|
||||||
rm /usr/local/bin/idle3.12 || true
|
|
||||||
rm /usr/local/bin/pydoc3 || true
|
|
||||||
rm /usr/local/bin/pydoc3.11 || true
|
|
||||||
rm /usr/local/bin/pydoc3.12 || true
|
|
||||||
rm /usr/local/bin/python3 || true
|
|
||||||
rm /usr/local/bin/python3.11 || true
|
|
||||||
rm /usr/local/bin/python3.12 || true
|
|
||||||
rm /usr/local/bin/python3-config || true
|
|
||||||
rm /usr/local/bin/python3.11-config || true
|
|
||||||
rm /usr/local/bin/python3.12-config || true
|
|
||||||
|
|
||||||
brew install hdf5 c-blosc libomp
|
|
||||||
|
|
||||||
- name: Installation (python)
|
|
||||||
run: |
|
|
||||||
python -m pip install --upgrade "pip<=24.0" wheel
|
|
||||||
export LD_LIBRARY_PATH=${HOME}/dependencies/lib:$LD_LIBRARY_PATH
|
export LD_LIBRARY_PATH=${HOME}/dependencies/lib:$LD_LIBRARY_PATH
|
||||||
export TA_LIBRARY_PATH=${HOME}/dependencies/lib
|
export TA_LIBRARY_PATH=${HOME}/dependencies/lib
|
||||||
export TA_INCLUDE_PATH=${HOME}/dependencies/include
|
export TA_INCLUDE_PATH=${HOME}/dependencies/include
|
||||||
pip install -r requirements-dev.txt
|
pip install -r requirements-dev.txt
|
||||||
pip install -e ft_client/
|
|
||||||
pip install -e .
|
pip install -e .
|
||||||
|
|
||||||
- name: Tests
|
- name: Tests
|
||||||
run: |
|
run: |
|
||||||
pytest --random-order
|
pytest --random-order
|
||||||
|
|
||||||
- name: Check for repository changes
|
|
||||||
run: |
|
|
||||||
if [ -n "$(git status --porcelain)" ]; then
|
|
||||||
echo "Repository is dirty, changes detected:"
|
|
||||||
git status
|
|
||||||
git diff
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo "Repository is clean, no changes detected."
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Backtesting
|
- name: Backtesting
|
||||||
run: |
|
run: |
|
||||||
cp tests/testdata/config.tests.json config.json
|
cp config_examples/config_bittrex.example.json config.json
|
||||||
freqtrade create-userdir --userdir user_data
|
freqtrade create-userdir --userdir user_data
|
||||||
freqtrade new-strategy -s AwesomeStrategyAdv --template advanced
|
freqtrade new-strategy -s AwesomeStrategyAdv --template advanced
|
||||||
freqtrade backtesting --datadir tests/testdata --strategy AwesomeStrategyAdv
|
freqtrade backtesting --datadir tests/testdata --strategy AwesomeStrategyAdv
|
||||||
|
|
||||||
- name: Hyperopt
|
- name: Hyperopt
|
||||||
run: |
|
run: |
|
||||||
cp tests/testdata/config.tests.json config.json
|
cp config_examples/config_bittrex.example.json config.json
|
||||||
freqtrade create-userdir --userdir user_data
|
freqtrade create-userdir --userdir user_data
|
||||||
freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt-loss SharpeHyperOptLossDaily --print-all
|
freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt-loss SharpeHyperOptLossDaily --print-all
|
||||||
|
|
||||||
|
- name: Flake8
|
||||||
|
run: |
|
||||||
|
flake8
|
||||||
|
|
||||||
- name: Sort imports (isort)
|
- name: Sort imports (isort)
|
||||||
run: |
|
run: |
|
||||||
isort --check .
|
isort --check .
|
||||||
|
|
||||||
- name: Run Ruff
|
|
||||||
run: |
|
|
||||||
ruff check --output-format=github
|
|
||||||
|
|
||||||
- name: Run Ruff format check
|
|
||||||
run: |
|
|
||||||
ruff format --check
|
|
||||||
|
|
||||||
- name: Mypy
|
- name: Mypy
|
||||||
run: |
|
run: |
|
||||||
mypy freqtrade scripts
|
mypy freqtrade scripts
|
||||||
@@ -257,24 +199,24 @@ jobs:
|
|||||||
details: Test Succeeded!
|
details: Test Succeeded!
|
||||||
webhookUrl: ${{ secrets.DISCORD_WEBHOOK }}
|
webhookUrl: ${{ secrets.DISCORD_WEBHOOK }}
|
||||||
|
|
||||||
build-windows:
|
build_windows:
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ windows-latest ]
|
os: [ windows-latest ]
|
||||||
python-version: ["3.9", "3.10", "3.11", "3.12"]
|
python-version: ["3.8", "3.9", "3.10"]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
|
|
||||||
- name: Pip cache (Windows)
|
- name: Pip cache (Windows)
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ~\AppData\Local\pip\Cache
|
path: ~\AppData\Local\pip\Cache
|
||||||
key: ${{ matrix.os }}-${{ matrix.python-version }}-pip
|
key: ${{ matrix.os }}-${{ matrix.python-version }}-pip
|
||||||
@@ -287,53 +229,26 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
pytest --random-order
|
pytest --random-order
|
||||||
|
|
||||||
- name: Check for repository changes
|
|
||||||
run: |
|
|
||||||
if (git status --porcelain) {
|
|
||||||
Write-Host "Repository is dirty, changes detected:"
|
|
||||||
git status
|
|
||||||
git diff
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Write-Host "Repository is clean, no changes detected."
|
|
||||||
}
|
|
||||||
|
|
||||||
- name: Backtesting
|
- name: Backtesting
|
||||||
run: |
|
run: |
|
||||||
cp tests/testdata/config.tests.json config.json
|
cp config_examples/config_bittrex.example.json config.json
|
||||||
freqtrade create-userdir --userdir user_data
|
freqtrade create-userdir --userdir user_data
|
||||||
freqtrade backtesting --datadir tests/testdata --strategy SampleStrategy
|
freqtrade backtesting --datadir tests/testdata --strategy SampleStrategy
|
||||||
|
|
||||||
- name: Hyperopt
|
- name: Hyperopt
|
||||||
run: |
|
run: |
|
||||||
cp tests/testdata/config.tests.json config.json
|
cp config_examples/config_bittrex.example.json config.json
|
||||||
freqtrade create-userdir --userdir user_data
|
freqtrade create-userdir --userdir user_data
|
||||||
freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt-loss SharpeHyperOptLossDaily --print-all
|
freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt-loss SharpeHyperOptLossDaily --print-all
|
||||||
|
|
||||||
- name: Run Ruff
|
- name: Flake8
|
||||||
run: |
|
run: |
|
||||||
ruff check --output-format=github
|
flake8
|
||||||
|
|
||||||
- name: Run Ruff format check
|
|
||||||
run: |
|
|
||||||
ruff format --check
|
|
||||||
|
|
||||||
- name: Mypy
|
- name: Mypy
|
||||||
run: |
|
run: |
|
||||||
mypy freqtrade scripts tests
|
mypy freqtrade scripts tests
|
||||||
|
|
||||||
- name: Run Pester tests (PowerShell)
|
|
||||||
run: |
|
|
||||||
$PSVersionTable
|
|
||||||
Set-PSRepository psgallery -InstallationPolicy trusted
|
|
||||||
Install-Module -Name Pester -RequiredVersion 5.3.1 -Confirm:$false -Force -SkipPublisherCheck
|
|
||||||
$Error.clear()
|
|
||||||
Invoke-Pester -Path "tests" -CI
|
|
||||||
if ($Error.Length -gt 0) {exit 1}
|
|
||||||
|
|
||||||
shell: powershell
|
|
||||||
|
|
||||||
- name: Discord notification
|
- name: Discord notification
|
||||||
uses: rjstone/discord-webhook-notify@v1
|
uses: rjstone/discord-webhook-notify@v1
|
||||||
if: failure() && ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false)
|
if: failure() && ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false)
|
||||||
@@ -342,44 +257,34 @@ jobs:
|
|||||||
details: Test Failed
|
details: Test Failed
|
||||||
webhookUrl: ${{ secrets.DISCORD_WEBHOOK }}
|
webhookUrl: ${{ secrets.DISCORD_WEBHOOK }}
|
||||||
|
|
||||||
mypy-version-check:
|
mypy_version_check:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: "3.12"
|
python-version: "3.10"
|
||||||
|
|
||||||
- name: pre-commit dependencies
|
- name: pre-commit dependencies
|
||||||
run: |
|
run: |
|
||||||
pip install pyaml
|
pip install pyaml
|
||||||
python build_helpers/pre_commit_update.py
|
python build_helpers/pre_commit_update.py
|
||||||
|
|
||||||
pre-commit:
|
docs_check:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: "3.12"
|
|
||||||
- uses: pre-commit/action@v3.0.1
|
|
||||||
|
|
||||||
docs-check:
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Documentation syntax
|
- name: Documentation syntax
|
||||||
run: |
|
run: |
|
||||||
./tests/test_docs.sh
|
./tests/test_docs.sh
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: "3.12"
|
python-version: "3.10"
|
||||||
|
|
||||||
- name: Documentation build
|
- name: Documentation build
|
||||||
run: |
|
run: |
|
||||||
@@ -395,67 +300,12 @@ jobs:
|
|||||||
details: Freqtrade doc test failed!
|
details: Freqtrade doc test failed!
|
||||||
webhookUrl: ${{ secrets.DISCORD_WEBHOOK }}
|
webhookUrl: ${{ secrets.DISCORD_WEBHOOK }}
|
||||||
|
|
||||||
|
# Notify only once - when CI completes (and after deploy) in case it's successfull
|
||||||
build-linux-online:
|
|
||||||
# Run pytest with "live" checks
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: "3.12"
|
|
||||||
|
|
||||||
- name: Cache_dependencies
|
|
||||||
uses: actions/cache@v4
|
|
||||||
id: cache
|
|
||||||
with:
|
|
||||||
path: ~/dependencies/
|
|
||||||
key: ${{ runner.os }}-dependencies
|
|
||||||
|
|
||||||
- name: pip cache (linux)
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: ~/.cache/pip
|
|
||||||
key: test-${{ matrix.os }}-${{ matrix.python-version }}-pip
|
|
||||||
|
|
||||||
- name: TA binary *nix
|
|
||||||
if: steps.cache.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
cd build_helpers && ./install_ta-lib.sh ${HOME}/dependencies/; cd ..
|
|
||||||
|
|
||||||
- name: Installation - *nix
|
|
||||||
run: |
|
|
||||||
python -m pip install --upgrade "pip<=24.0" wheel
|
|
||||||
export LD_LIBRARY_PATH=${HOME}/dependencies/lib:$LD_LIBRARY_PATH
|
|
||||||
export TA_LIBRARY_PATH=${HOME}/dependencies/lib
|
|
||||||
export TA_INCLUDE_PATH=${HOME}/dependencies/include
|
|
||||||
pip install -r requirements-dev.txt
|
|
||||||
pip install -e ft_client/
|
|
||||||
pip install -e .
|
|
||||||
|
|
||||||
- name: Tests incl. ccxt compatibility tests
|
|
||||||
env:
|
|
||||||
CI_WEB_PROXY: http://152.67.78.211:13128
|
|
||||||
run: |
|
|
||||||
pytest --random-order --longrun --durations 20 -n auto
|
|
||||||
|
|
||||||
|
|
||||||
# Notify only once - when CI completes (and after deploy) in case it's successful
|
|
||||||
notify-complete:
|
notify-complete:
|
||||||
needs: [
|
needs: [ build_linux, build_macos, build_windows, docs_check, mypy_version_check ]
|
||||||
build-linux,
|
runs-on: ubuntu-20.04
|
||||||
build-macos,
|
|
||||||
build-windows,
|
|
||||||
docs-check,
|
|
||||||
mypy-version-check,
|
|
||||||
pre-commit,
|
|
||||||
build-linux-online
|
|
||||||
]
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
# Discord notification can't handle schedule events
|
# Discord notification can't handle schedule events
|
||||||
if: github.event_name != 'schedule' && github.repository == 'freqtrade/freqtrade'
|
if: (github.event_name != 'schedule')
|
||||||
permissions:
|
permissions:
|
||||||
repository-projects: read
|
repository-projects: read
|
||||||
steps:
|
steps:
|
||||||
@@ -476,95 +326,44 @@ jobs:
|
|||||||
details: Test Completed!
|
details: Test Completed!
|
||||||
webhookUrl: ${{ secrets.DISCORD_WEBHOOK }}
|
webhookUrl: ${{ secrets.DISCORD_WEBHOOK }}
|
||||||
|
|
||||||
build:
|
deploy:
|
||||||
name: "Build"
|
needs: [ build_linux, build_macos, build_windows, docs_check, mypy_version_check ]
|
||||||
needs: [ build-linux, build-macos, build-windows, docs-check, mypy-version-check, pre-commit ]
|
runs-on: ubuntu-20.04
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: "3.12"
|
|
||||||
|
|
||||||
- name: Build distribution
|
|
||||||
run: |
|
|
||||||
pip install -U build
|
|
||||||
python -m build --sdist --wheel
|
|
||||||
|
|
||||||
- name: Upload artifacts 📦
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: freqtrade-build
|
|
||||||
path: |
|
|
||||||
dist
|
|
||||||
retention-days: 10
|
|
||||||
|
|
||||||
- name: Build Client distribution
|
|
||||||
run: |
|
|
||||||
pip install -U build
|
|
||||||
python -m build --sdist --wheel ft_client
|
|
||||||
|
|
||||||
- name: Upload artifacts 📦
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: freqtrade-client-build
|
|
||||||
path: |
|
|
||||||
ft_client/dist
|
|
||||||
retention-days: 10
|
|
||||||
|
|
||||||
deploy-pypi:
|
|
||||||
name: "Deploy to PyPI"
|
|
||||||
needs: [ build ]
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
if: (github.event_name == 'release')
|
|
||||||
environment:
|
|
||||||
name: release
|
|
||||||
url: https://pypi.org/p/freqtrade
|
|
||||||
permissions:
|
|
||||||
id-token: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Download artifact 📦
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
pattern: freqtrade*-build
|
|
||||||
path: dist
|
|
||||||
merge-multiple: true
|
|
||||||
|
|
||||||
|
|
||||||
- name: Publish to PyPI (Test)
|
|
||||||
uses: pypa/gh-action-pypi-publish@v1.9.0
|
|
||||||
with:
|
|
||||||
repository-url: https://test.pypi.org/legacy/
|
|
||||||
|
|
||||||
- name: Publish to PyPI
|
|
||||||
uses: pypa/gh-action-pypi-publish@v1.9.0
|
|
||||||
|
|
||||||
|
|
||||||
deploy-docker:
|
|
||||||
needs: [ build-linux, build-macos, build-windows, docs-check, mypy-version-check, pre-commit ]
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
|
|
||||||
if: (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'release') && github.repository == 'freqtrade/freqtrade'
|
if: (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'release') && github.repository == 'freqtrade/freqtrade'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: "3.12"
|
python-version: "3.9"
|
||||||
|
|
||||||
- name: Extract branch name
|
- name: Extract branch name
|
||||||
id: extract-branch
|
shell: bash
|
||||||
|
run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF##*/})"
|
||||||
|
id: extract_branch
|
||||||
|
|
||||||
|
- name: Build distribution
|
||||||
run: |
|
run: |
|
||||||
echo "GITHUB_REF='${GITHUB_REF}'"
|
pip install -U setuptools wheel
|
||||||
echo "branch=${GITHUB_REF##*/}" >> "$GITHUB_OUTPUT"
|
python setup.py sdist bdist_wheel
|
||||||
|
|
||||||
|
- name: Publish to PyPI (Test)
|
||||||
|
uses: pypa/gh-action-pypi-publish@v1.5.1
|
||||||
|
if: (github.event_name == 'release')
|
||||||
|
with:
|
||||||
|
user: __token__
|
||||||
|
password: ${{ secrets.pypi_test_password }}
|
||||||
|
repository_url: https://test.pypi.org/legacy/
|
||||||
|
|
||||||
|
- name: Publish to PyPI
|
||||||
|
uses: pypa/gh-action-pypi-publish@v1.5.1
|
||||||
|
if: (github.event_name == 'release')
|
||||||
|
with:
|
||||||
|
user: __token__
|
||||||
|
password: ${{ secrets.pypi_password }}
|
||||||
|
|
||||||
- name: Dockerhub login
|
- name: Dockerhub login
|
||||||
env:
|
env:
|
||||||
@@ -581,39 +380,45 @@ jobs:
|
|||||||
sudo systemctl restart docker
|
sudo systemctl restart docker
|
||||||
docker version -f '{{.Server.Experimental}}'
|
docker version -f '{{.Server.Experimental}}'
|
||||||
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
id: buildx
|
id: buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: crazy-max/ghaction-docker-buildx@v3.3.1
|
||||||
|
with:
|
||||||
|
buildx-version: latest
|
||||||
|
qemu-version: latest
|
||||||
|
|
||||||
- name: Available platforms
|
- name: Available platforms
|
||||||
run: echo ${{ steps.buildx.outputs.platforms }}
|
run: echo ${{ steps.buildx.outputs.platforms }}
|
||||||
|
|
||||||
- name: Build and test and push docker images
|
- name: Build and test and push docker images
|
||||||
env:
|
env:
|
||||||
BRANCH_NAME: ${{ steps.extract-branch.outputs.branch }}
|
IMAGE_NAME: freqtradeorg/freqtrade
|
||||||
|
BRANCH_NAME: ${{ steps.extract_branch.outputs.branch }}
|
||||||
run: |
|
run: |
|
||||||
build_helpers/publish_docker_multi.sh
|
build_helpers/publish_docker_multi.sh
|
||||||
|
|
||||||
deploy-arm:
|
- name: Discord notification
|
||||||
name: "Deploy Docker"
|
uses: rjstone/discord-webhook-notify@v1
|
||||||
permissions:
|
if: always() && ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false) && (github.event_name != 'schedule')
|
||||||
packages: write
|
with:
|
||||||
needs: [ deploy-docker ]
|
severity: info
|
||||||
|
details: Deploy Succeeded!
|
||||||
|
webhookUrl: ${{ secrets.DISCORD_WEBHOOK }}
|
||||||
|
|
||||||
|
|
||||||
|
deploy_arm:
|
||||||
|
needs: [ deploy ]
|
||||||
# Only run on 64bit machines
|
# Only run on 64bit machines
|
||||||
runs-on: [self-hosted, linux, ARM64]
|
runs-on: [self-hosted, linux, ARM64]
|
||||||
if: (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'release') && github.repository == 'freqtrade/freqtrade'
|
if: (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'release') && github.repository == 'freqtrade/freqtrade'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Extract branch name
|
- name: Extract branch name
|
||||||
id: extract-branch
|
shell: bash
|
||||||
run: |
|
run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF##*/})"
|
||||||
echo "GITHUB_REF='${GITHUB_REF}'"
|
id: extract_branch
|
||||||
echo "branch=${GITHUB_REF##*/}" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
- name: Dockerhub login
|
- name: Dockerhub login
|
||||||
env:
|
env:
|
||||||
@@ -624,16 +429,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Build and test and push docker images
|
- name: Build and test and push docker images
|
||||||
env:
|
env:
|
||||||
BRANCH_NAME: ${{ steps.extract-branch.outputs.branch }}
|
IMAGE_NAME: freqtradeorg/freqtrade
|
||||||
GHCR_USERNAME: ${{ github.actor }}
|
BRANCH_NAME: ${{ steps.extract_branch.outputs.branch }}
|
||||||
GHCR_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
run: |
|
||||||
build_helpers/publish_docker_arm64.sh
|
build_helpers/publish_docker_arm64.sh
|
||||||
|
|
||||||
- name: Discord notification
|
|
||||||
uses: rjstone/discord-webhook-notify@v1
|
|
||||||
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!
|
|
||||||
webhookUrl: ${{ secrets.DISCORD_WEBHOOK }}
|
|
||||||
|
|||||||
45
.github/workflows/devcontainer-build.yml
vendored
@@ -1,45 +0,0 @@
|
|||||||
name: Devcontainer Pre-Build
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: "0 3 * * 0"
|
|
||||||
# push:
|
|
||||||
# branches:
|
|
||||||
# - "master"
|
|
||||||
# tags:
|
|
||||||
# - "v*.*.*"
|
|
||||||
# pull_requests:
|
|
||||||
# branches:
|
|
||||||
# - "master"
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: "${{ github.workflow }}"
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
packages: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-push:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Checkout
|
|
||||||
id: checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
-
|
|
||||||
name: Login to GitHub Container Registry
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
-
|
|
||||||
name: Pre-build dev container image
|
|
||||||
uses: devcontainers/ci@v0.3
|
|
||||||
with:
|
|
||||||
subFolder: .github
|
|
||||||
imageName: ghcr.io/${{ github.repository }}-devcontainer
|
|
||||||
cacheFrom: ghcr.io/${{ github.repository }}-devcontainer
|
|
||||||
push: always
|
|
||||||
18
.github/workflows/docker-update-readme.yml
vendored
@@ -1,18 +0,0 @@
|
|||||||
name: Update Docker Hub Description
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- stable
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
dockerHubDescription:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Docker Hub Description
|
|
||||||
uses: peter-evans/dockerhub-description@v4
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
|
||||||
repository: freqtradeorg/freqtrade
|
|
||||||
17
.github/workflows/docker_update_readme.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
name: Update Docker Hub Description
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- stable
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
dockerHubDescription:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Docker Hub Description
|
||||||
|
uses: peter-evans/dockerhub-description@v3
|
||||||
|
env:
|
||||||
|
DOCKERHUB_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
DOCKERHUB_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
DOCKERHUB_REPOSITORY: freqtradeorg/freqtrade
|
||||||
41
.github/workflows/pre-commit-update.yml
vendored
@@ -1,41 +0,0 @@
|
|||||||
name: Pre-commit auto-update
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "0 3 * * 2"
|
|
||||||
# on demand
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
auto-update:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: "3.12"
|
|
||||||
|
|
||||||
|
|
||||||
- name: Install pre-commit
|
|
||||||
run: pip install pre-commit
|
|
||||||
|
|
||||||
- name: Run auto-update
|
|
||||||
run: pre-commit autoupdate
|
|
||||||
|
|
||||||
- uses: peter-evans/create-pull-request@v6
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.REPO_SCOPED_TOKEN }}
|
|
||||||
add-paths: .pre-commit-config.yaml
|
|
||||||
labels: |
|
|
||||||
Tech maintenance
|
|
||||||
Dependencies
|
|
||||||
branch: update/pre-commit-hooks
|
|
||||||
title: Update pre-commit hooks
|
|
||||||
commit-message: "chore: update pre-commit hooks"
|
|
||||||
committer: Freqtrade Bot <noreply@github.com>
|
|
||||||
body: Update versions of pre-commit hooks to latest version.
|
|
||||||
delete-branch: true
|
|
||||||
5
.gitignore
vendored
@@ -83,9 +83,6 @@ instance/
|
|||||||
# Scrapy stuff:
|
# Scrapy stuff:
|
||||||
.scrapy
|
.scrapy
|
||||||
|
|
||||||
# memray
|
|
||||||
memray-*
|
|
||||||
|
|
||||||
# Sphinx documentation
|
# Sphinx documentation
|
||||||
docs/_build/
|
docs/_build/
|
||||||
# Mkdocs documentation
|
# Mkdocs documentation
|
||||||
@@ -111,6 +108,8 @@ target/
|
|||||||
#exceptions
|
#exceptions
|
||||||
!*.gitkeep
|
!*.gitkeep
|
||||||
!config_examples/config_binance.example.json
|
!config_examples/config_binance.example.json
|
||||||
|
!config_examples/config_bittrex.example.json
|
||||||
|
!config_examples/config_ftx.example.json
|
||||||
!config_examples/config_full.example.json
|
!config_examples/config_full.example.json
|
||||||
!config_examples/config_kraken.example.json
|
!config_examples/config_kraken.example.json
|
||||||
!config_examples/config_freqai.example.json
|
!config_examples/config_freqai.example.json
|
||||||
|
|||||||
@@ -2,49 +2,39 @@
|
|||||||
# See https://pre-commit.com/hooks.html for more hooks
|
# See https://pre-commit.com/hooks.html for more hooks
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/pycqa/flake8
|
- repo: https://github.com/pycqa/flake8
|
||||||
rev: "7.1.0"
|
rev: "4.0.1"
|
||||||
hooks:
|
hooks:
|
||||||
- id: flake8
|
- id: flake8
|
||||||
additional_dependencies: [Flake8-pyproject]
|
|
||||||
# stages: [push]
|
# stages: [push]
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||||
rev: "v1.11.0"
|
rev: "v0.942"
|
||||||
hooks:
|
hooks:
|
||||||
- id: mypy
|
- id: mypy
|
||||||
exclude: build_helpers
|
exclude: build_helpers
|
||||||
additional_dependencies:
|
additional_dependencies:
|
||||||
- types-cachetools==5.4.0.20240717
|
- types-cachetools==5.2.1
|
||||||
- types-filelock==3.2.7
|
- types-filelock==3.2.7
|
||||||
- types-requests==2.32.0.20240712
|
- types-requests==2.28.8
|
||||||
- types-tabulate==0.9.0.20240106
|
- types-tabulate==0.8.11
|
||||||
- types-python-dateutil==2.9.0.20240316
|
- types-python-dateutil==2.8.19
|
||||||
- SQLAlchemy==2.0.31
|
|
||||||
# stages: [push]
|
# stages: [push]
|
||||||
|
|
||||||
- repo: https://github.com/pycqa/isort
|
- repo: https://github.com/pycqa/isort
|
||||||
rev: "5.13.2"
|
rev: "5.10.1"
|
||||||
hooks:
|
hooks:
|
||||||
- id: isort
|
- id: isort
|
||||||
name: isort (python)
|
name: isort (python)
|
||||||
# stages: [push]
|
# stages: [push]
|
||||||
|
|
||||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
|
||||||
# Ruff version.
|
|
||||||
rev: 'v0.5.4'
|
|
||||||
hooks:
|
|
||||||
- id: ruff
|
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.6.0
|
rev: v2.4.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
exclude: |
|
exclude: |
|
||||||
(?x)^(
|
(?x)^(
|
||||||
tests/.*|
|
tests/.*|
|
||||||
.*\.svg|
|
.*\.svg
|
||||||
.*\.yml|
|
|
||||||
.*\.json
|
|
||||||
)$
|
)$
|
||||||
- id: mixed-line-ending
|
- id: mixed-line-ending
|
||||||
- id: debug-statements
|
- id: debug-statements
|
||||||
@@ -54,10 +44,3 @@ repos:
|
|||||||
(?x)^(
|
(?x)^(
|
||||||
.*\.md
|
.*\.md
|
||||||
)$
|
)$
|
||||||
|
|
||||||
- repo: https://github.com/codespell-project/codespell
|
|
||||||
rev: v2.3.0
|
|
||||||
hooks:
|
|
||||||
- id: codespell
|
|
||||||
additional_dependencies:
|
|
||||||
- tomli
|
|
||||||
|
|||||||
@@ -1,14 +1,8 @@
|
|||||||
# .readthedocs.yml
|
# .readthedocs.yml
|
||||||
version: 2
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
os: "ubuntu-22.04"
|
image: latest
|
||||||
tools:
|
|
||||||
python: "3.11"
|
|
||||||
|
|
||||||
python:
|
python:
|
||||||
install:
|
version: 3.8
|
||||||
- requirements: docs/requirements-docs.txt
|
setup_py_install: false
|
||||||
|
|
||||||
mkdocs:
|
|
||||||
configuration: mkdocs.yml
|
|
||||||
|
|||||||
11
.vscode/extensions.json
vendored
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"recommendations": [
|
|
||||||
"ms-python.python",
|
|
||||||
"ms-python.vscode-pylance",
|
|
||||||
"charliermarsh.ruff",
|
|
||||||
"davidanson.vscode-markdownlint",
|
|
||||||
"ms-azuretools.vscode-docker",
|
|
||||||
"vscode-icons-team.vscode-icons",
|
|
||||||
"github.vscode-github-actions",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -45,17 +45,16 @@ pytest tests/test_<file_name>.py::test_<method_name>
|
|||||||
|
|
||||||
### 2. Test if your code is PEP8 compliant
|
### 2. Test if your code is PEP8 compliant
|
||||||
|
|
||||||
#### Run Ruff
|
#### Run Flake8
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ruff check .
|
flake8 freqtrade tests scripts
|
||||||
```
|
```
|
||||||
|
|
||||||
We receive a lot of code that fails the `ruff` checks.
|
We receive a lot of code that fails the `flake8` checks.
|
||||||
To help with that, we encourage you to install the git pre-commit
|
To help with that, we encourage you to install the git pre-commit
|
||||||
hook that will warn you when you try to commit code that fails these checks.
|
hook that will warn you when you try to commit code that fails these checks.
|
||||||
|
Guide for installing them is [here](http://flake8.pycqa.org/en/latest/user/using-hooks.html).
|
||||||
you can manually run pre-commit with `pre-commit run -a`.
|
|
||||||
|
|
||||||
##### Additional styles applied
|
##### Additional styles applied
|
||||||
|
|
||||||
@@ -72,12 +71,12 @@ you can manually run pre-commit with `pre-commit run -a`.
|
|||||||
mypy freqtrade
|
mypy freqtrade
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Ensure formatting is correct
|
### 4. Ensure all imports are correct
|
||||||
|
|
||||||
#### Run ruff
|
#### Run isort
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
ruff format .
|
isort .
|
||||||
```
|
```
|
||||||
|
|
||||||
## (Core)-Committer Guide
|
## (Core)-Committer Guide
|
||||||
@@ -125,7 +124,7 @@ Exceptions:
|
|||||||
|
|
||||||
Contributors may be given commit privileges. Preference will be given to those with:
|
Contributors may be given commit privileges. Preference will be given to those with:
|
||||||
|
|
||||||
1. Past contributions to Freqtrade and other related open-source projects. Contributions to Freqtrade include both code (both accepted and pending) and friendly participation in the issue tracker and Pull request reviews. Both quantity and quality are considered.
|
1. Past contributions to Freqtrade and other related open-source projects. Contributions to Freqtrade include both code (both accepted and pending) and friendly participation in the issue tracker and Pull request reviews. Quantity and quality are considered.
|
||||||
1. A coding style that the other core committers find simple, minimal, and clean.
|
1. A coding style that the other core committers find simple, minimal, and clean.
|
||||||
1. Access to resources for cross-platform development and testing.
|
1. Access to resources for cross-platform development and testing.
|
||||||
1. Time to devote to the project regularly.
|
1. Time to devote to the project regularly.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM python:3.12.4-slim-bookworm as base
|
FROM python:3.10.6-slim-bullseye as base
|
||||||
|
|
||||||
# Setup env
|
# Setup env
|
||||||
ENV LANG C.UTF-8
|
ENV LANG C.UTF-8
|
||||||
@@ -11,7 +11,7 @@ ENV FT_APP_ENV="docker"
|
|||||||
# Prepare environment
|
# Prepare environment
|
||||||
RUN mkdir /freqtrade \
|
RUN mkdir /freqtrade \
|
||||||
&& apt-get update \
|
&& apt-get update \
|
||||||
&& apt-get -y install sudo libatlas3-base curl sqlite3 libhdf5-serial-dev libgomp1 \
|
&& apt-get -y install sudo libatlas3-base curl sqlite3 libhdf5-serial-dev \
|
||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
&& useradd -u 1000 -G sudo -U -m -s /bin/bash ftuser \
|
&& useradd -u 1000 -G sudo -U -m -s /bin/bash ftuser \
|
||||||
&& chown ftuser:ftuser /freqtrade \
|
&& chown ftuser:ftuser /freqtrade \
|
||||||
@@ -25,7 +25,7 @@ FROM base as python-deps
|
|||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get -y install build-essential libssl-dev git libffi-dev libgfortran5 pkg-config cmake gcc \
|
&& apt-get -y install build-essential libssl-dev git libffi-dev libgfortran5 pkg-config cmake gcc \
|
||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
&& pip install --upgrade "pip<=24.0" wheel
|
&& pip install --upgrade pip
|
||||||
|
|
||||||
# Install TA-lib
|
# Install TA-lib
|
||||||
COPY build_helpers/* /tmp/
|
COPY build_helpers/* /tmp/
|
||||||
@@ -35,7 +35,7 @@ ENV LD_LIBRARY_PATH /usr/local/lib
|
|||||||
# Install dependencies
|
# Install dependencies
|
||||||
COPY --chown=ftuser:ftuser requirements.txt requirements-hyperopt.txt /freqtrade/
|
COPY --chown=ftuser:ftuser requirements.txt requirements-hyperopt.txt /freqtrade/
|
||||||
USER ftuser
|
USER ftuser
|
||||||
RUN pip install --user --no-cache-dir "numpy<2.0" \
|
RUN pip install --user --no-cache-dir numpy \
|
||||||
&& pip install --user --no-cache-dir -r requirements-hyperopt.txt
|
&& pip install --user --no-cache-dir -r requirements-hyperopt.txt
|
||||||
|
|
||||||
# Copy dependencies to runtime-image
|
# Copy dependencies to runtime-image
|
||||||
|
|||||||
@@ -5,5 +5,3 @@ recursive-include freqtrade/templates/ *.j2 *.ipynb
|
|||||||
include freqtrade/exchange/binance_leverage_tiers.json
|
include freqtrade/exchange/binance_leverage_tiers.json
|
||||||
include freqtrade/rpc/api_server/ui/fallback_file.html
|
include freqtrade/rpc/api_server/ui/fallback_file.html
|
||||||
include freqtrade/rpc/api_server/ui/favicon.ico
|
include freqtrade/rpc/api_server/ui/favicon.ico
|
||||||
|
|
||||||
prune tests
|
|
||||||
|
|||||||
22
README.md
@@ -1,7 +1,6 @@
|
|||||||
# 
|
# 
|
||||||
|
|
||||||
[](https://github.com/freqtrade/freqtrade/actions/)
|
[](https://github.com/freqtrade/freqtrade/actions/)
|
||||||
[](https://doi.org/10.21105/joss.04864)
|
|
||||||
[](https://coveralls.io/github/freqtrade/freqtrade?branch=develop)
|
[](https://coveralls.io/github/freqtrade/freqtrade?branch=develop)
|
||||||
[](https://www.freqtrade.io)
|
[](https://www.freqtrade.io)
|
||||||
[](https://codeclimate.com/github/freqtrade/freqtrade/maintainability)
|
[](https://codeclimate.com/github/freqtrade/freqtrade/maintainability)
|
||||||
@@ -28,10 +27,10 @@ hesitate to read the source code and understand the mechanism of this bot.
|
|||||||
Please read the [exchange specific notes](docs/exchanges.md) to learn about eventual, special configurations needed for each exchange.
|
Please read the [exchange specific notes](docs/exchanges.md) to learn about eventual, special configurations needed for each exchange.
|
||||||
|
|
||||||
- [X] [Binance](https://www.binance.com/)
|
- [X] [Binance](https://www.binance.com/)
|
||||||
- [X] [Bitmart](https://bitmart.com/)
|
- [X] [Bittrex](https://bittrex.com/)
|
||||||
- [X] [BingX](https://bingx.com/invite/0EM9RX)
|
- [X] [FTX](https://ftx.com/#a=2258149)
|
||||||
- [X] [Gate.io](https://www.gate.io/ref/6266643)
|
- [X] [Gate.io](https://www.gate.io/ref/6266643)
|
||||||
- [X] [HTX](https://www.htx.com/) (Former Huobi)
|
- [X] [Huobi](http://huobi.com/)
|
||||||
- [X] [Kraken](https://kraken.com/)
|
- [X] [Kraken](https://kraken.com/)
|
||||||
- [X] [OKX](https://okx.com/) (Former OKEX)
|
- [X] [OKX](https://okx.com/) (Former OKEX)
|
||||||
- [ ] [potentially many others](https://github.com/ccxt/ccxt/). _(We cannot guarantee they will work)_
|
- [ ] [potentially many others](https://github.com/ccxt/ccxt/). _(We cannot guarantee they will work)_
|
||||||
@@ -40,8 +39,7 @@ Please read the [exchange specific notes](docs/exchanges.md) to learn about even
|
|||||||
|
|
||||||
- [X] [Binance](https://www.binance.com/)
|
- [X] [Binance](https://www.binance.com/)
|
||||||
- [X] [Gate.io](https://www.gate.io/ref/6266643)
|
- [X] [Gate.io](https://www.gate.io/ref/6266643)
|
||||||
- [X] [OKX](https://okx.com/)
|
- [X] [OKX](https://okx.com/).
|
||||||
- [X] [Bybit](https://bybit.com/)
|
|
||||||
|
|
||||||
Please make sure to read the [exchange specific notes](docs/exchanges.md), as well as the [trading with leverage](docs/leverage.md) documentation before diving in.
|
Please make sure to read the [exchange specific notes](docs/exchanges.md), as well as the [trading with leverage](docs/leverage.md) documentation before diving in.
|
||||||
|
|
||||||
@@ -60,7 +58,7 @@ Please find the complete documentation on the [freqtrade website](https://www.fr
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- [x] **Based on Python 3.9+**: For botting on any operating system - Windows, macOS and Linux.
|
- [x] **Based on Python 3.8+**: For botting on any operating system - Windows, macOS and Linux.
|
||||||
- [x] **Persistence**: Persistence is achieved through sqlite.
|
- [x] **Persistence**: Persistence is achieved through sqlite.
|
||||||
- [x] **Dry-run**: Run the bot without paying money.
|
- [x] **Dry-run**: Run the bot without paying money.
|
||||||
- [x] **Backtesting**: Run a simulation of your buy/sell strategy.
|
- [x] **Backtesting**: Run a simulation of your buy/sell strategy.
|
||||||
@@ -132,7 +130,7 @@ Telegram is not mandatory. However, this is a great way to control your bot. Mor
|
|||||||
|
|
||||||
- `/start`: Starts the trader.
|
- `/start`: Starts the trader.
|
||||||
- `/stop`: Stops the trader.
|
- `/stop`: Stops the trader.
|
||||||
- `/stopentry`: Stop entering new trades.
|
- `/stopbuy`: Stop entering new trades.
|
||||||
- `/status <trade_id>|[table]`: Lists all or specific open trades.
|
- `/status <trade_id>|[table]`: Lists all or specific open trades.
|
||||||
- `/profit [<n>]`: Lists cumulative profit from all finished trades, over the last n days.
|
- `/profit [<n>]`: Lists cumulative profit from all finished trades, over the last n days.
|
||||||
- `/forceexit <trade_id>|all`: Instantly exits the given trade (Ignoring `minimum_roi`).
|
- `/forceexit <trade_id>|all`: Instantly exits the given trade (Ignoring `minimum_roi`).
|
||||||
@@ -166,10 +164,6 @@ first. If it hasn't been reported, please
|
|||||||
ensure you follow the template guide so that the team can assist you as
|
ensure you follow the template guide so that the team can assist you as
|
||||||
quickly as possible.
|
quickly as possible.
|
||||||
|
|
||||||
For every [issue](https://github.com/freqtrade/freqtrade/issues/new/choose) created, kindly follow up and mark satisfaction or reminder to close issue when equilibrium ground is reached.
|
|
||||||
|
|
||||||
--Maintain github's [community policy](https://docs.github.com/en/site-policy/github-terms/github-community-code-of-conduct)--
|
|
||||||
|
|
||||||
### [Feature Requests](https://github.com/freqtrade/freqtrade/labels/enhancement)
|
### [Feature Requests](https://github.com/freqtrade/freqtrade/labels/enhancement)
|
||||||
|
|
||||||
Have you a great idea to improve the bot you want to share? Please,
|
Have you a great idea to improve the bot you want to share? Please,
|
||||||
@@ -208,9 +202,9 @@ To run this bot we recommend you a cloud instance with a minimum of:
|
|||||||
|
|
||||||
### Software requirements
|
### Software requirements
|
||||||
|
|
||||||
- [Python >= 3.9](http://docs.python-guide.org/en/latest/starting/installation/)
|
- [Python >= 3.8](http://docs.python-guide.org/en/latest/starting/installation/)
|
||||||
- [pip](https://pip.pypa.io/en/stable/installing/)
|
- [pip](https://pip.pypa.io/en/stable/installing/)
|
||||||
- [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
|
- [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
|
||||||
- [TA-Lib](https://ta-lib.github.io/ta-lib-python/)
|
- [TA-Lib](https://mrjbq7.github.io/ta-lib/install.html)
|
||||||
- [virtualenv](https://virtualenv.pypa.io/en/stable/installation.html) (Recommended)
|
- [virtualenv](https://virtualenv.pypa.io/en/stable/installation.html) (Recommended)
|
||||||
- [Docker](https://www.docker.com/products/docker) (Recommended)
|
- [Docker](https://www.docker.com/products/docker) (Recommended)
|
||||||
|
|||||||
BIN
build_helpers/TA_Lib-0.4.24-cp310-cp310-win_amd64.whl
Normal file
BIN
build_helpers/TA_Lib-0.4.24-cp38-cp38-win_amd64.whl
Normal file
BIN
build_helpers/TA_Lib-0.4.24-cp39-cp39-win_amd64.whl
Normal file
@@ -1,23 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
import ccxt
|
|
||||||
|
|
||||||
|
|
||||||
key = os.environ.get("FREQTRADE__EXCHANGE__KEY")
|
|
||||||
secret = os.environ.get("FREQTRADE__EXCHANGE__SECRET")
|
|
||||||
|
|
||||||
proxy = os.environ.get("CI_WEB_PROXY")
|
|
||||||
|
|
||||||
exchange = ccxt.binance(
|
|
||||||
{"apiKey": key, "secret": secret, "httpsProxy": proxy, "options": {"defaultType": "swap"}}
|
|
||||||
)
|
|
||||||
_ = 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)
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
"""Script to extract the configuration json schema from config_schema.py file."""
|
|
||||||
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
import rapidjson
|
|
||||||
|
|
||||||
from freqtrade.configuration.config_schema import CONF_SCHEMA
|
|
||||||
|
|
||||||
|
|
||||||
def extract_config_json_schema():
|
|
||||||
schema_filename = Path(__file__).parent / "schema.json"
|
|
||||||
with schema_filename.open("w") as f:
|
|
||||||
rapidjson.dump(CONF_SCHEMA, f, indent=2)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
extract_config_json_schema()
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
from freqtrade import __version__ as ft_version
|
|
||||||
from freqtrade_client import __version__ as client_version
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
if ft_version != client_version:
|
|
||||||
print(f"Versions do not match: \nft: {ft_version} \nclient: {client_version}")
|
|
||||||
exit(1)
|
|
||||||
print(f"Versions match: ft: {ft_version}, client: {client_version}")
|
|
||||||
exit(0)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
@@ -8,9 +8,8 @@ if [ -n "$2" ] || [ ! -f "${INSTALL_LOC}/lib/libta_lib.a" ]; then
|
|||||||
tar zxvf ta-lib-0.4.0-src.tar.gz
|
tar zxvf ta-lib-0.4.0-src.tar.gz
|
||||||
cd ta-lib \
|
cd ta-lib \
|
||||||
&& sed -i.bak "s|0.00000001|0.000000000000000001 |g" src/ta_func/ta_utility.h \
|
&& sed -i.bak "s|0.00000001|0.000000000000000001 |g" src/ta_func/ta_utility.h \
|
||||||
&& echo "Downloading gcc config.guess and config.sub" \
|
&& curl 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' -o config.guess \
|
||||||
&& curl -s 'https://raw.githubusercontent.com/gcc-mirror/gcc/master/config.guess' -o config.guess \
|
&& curl 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD' -o config.sub \
|
||||||
&& curl -s 'https://raw.githubusercontent.com/gcc-mirror/gcc/master/config.sub' -o config.sub \
|
|
||||||
&& ./configure --prefix=${INSTALL_LOC}/ \
|
&& ./configure --prefix=${INSTALL_LOC}/ \
|
||||||
&& make
|
&& make
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
# vendored Wheels compiled via https://github.com/xmatthias/ta-lib-python/tree/ta_bundled_040
|
# Downloads don't work automatically, since the URL is regenerated via javascript.
|
||||||
|
# Downloaded from https://www.lfd.uci.edu/~gohlke/pythonlibs/#ta-lib
|
||||||
|
|
||||||
python -m pip install --upgrade "pip<=24.0" wheel
|
python -m pip install --upgrade pip wheel
|
||||||
|
|
||||||
$pyv = python -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"
|
$pyv = python -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"
|
||||||
|
|
||||||
|
if ($pyv -eq '3.8') {
|
||||||
pip install --find-links=build_helpers\ --prefer-binary TA-Lib
|
pip install build_helpers\TA_Lib-0.4.24-cp38-cp38-win_amd64.whl
|
||||||
|
}
|
||||||
|
if ($pyv -eq '3.9') {
|
||||||
|
pip install build_helpers\TA_Lib-0.4.24-cp39-cp39-win_amd64.whl
|
||||||
|
}
|
||||||
|
if ($pyv -eq '3.10') {
|
||||||
|
pip install build_helpers\TA_Lib-0.4.24-cp310-cp310-win_amd64.whl
|
||||||
|
}
|
||||||
pip install -r requirements-dev.txt
|
pip install -r requirements-dev.txt
|
||||||
pip install -e .
|
pip install -e .
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# File used in CI to ensure pre-commit dependencies are kept up-to-date.
|
# File used in CI to ensure pre-commit dependencies are kept uptodate.
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -6,30 +6,23 @@ from pathlib import Path
|
|||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
|
||||||
pre_commit_file = Path(".pre-commit-config.yaml")
|
pre_commit_file = Path('.pre-commit-config.yaml')
|
||||||
require_dev = Path("requirements-dev.txt")
|
require_dev = Path('requirements-dev.txt')
|
||||||
require = Path("requirements.txt")
|
|
||||||
|
|
||||||
with require_dev.open("r") as rfile:
|
with require_dev.open('r') as rfile:
|
||||||
requirements = rfile.readlines()
|
requirements = rfile.readlines()
|
||||||
|
|
||||||
with require.open("r") as rfile:
|
|
||||||
requirements.extend(rfile.readlines())
|
|
||||||
|
|
||||||
# Extract types only
|
# Extract types only
|
||||||
type_reqs = [
|
type_reqs = [r.strip('\n') for r in requirements if r.startswith('types-')]
|
||||||
r.strip("\n") for r in requirements if r.startswith("types-") or r.startswith("SQLAlchemy")
|
|
||||||
]
|
|
||||||
|
|
||||||
with pre_commit_file.open("r") as file:
|
with pre_commit_file.open('r') as file:
|
||||||
f = yaml.load(file, Loader=yaml.SafeLoader)
|
f = yaml.load(file, Loader=yaml.FullLoader)
|
||||||
|
|
||||||
|
|
||||||
mypy_repo = [
|
mypy_repo = [repo for repo in f['repos'] if repo['repo']
|
||||||
repo for repo in f["repos"] if repo["repo"] == "https://github.com/pre-commit/mirrors-mypy"
|
== 'https://github.com/pre-commit/mirrors-mypy']
|
||||||
]
|
|
||||||
|
|
||||||
hooks = mypy_repo[0]["hooks"][0]["additional_dependencies"]
|
hooks = mypy_repo[0]['hooks'][0]['additional_dependencies']
|
||||||
|
|
||||||
errors = []
|
errors = []
|
||||||
for hook in hooks:
|
for hook in hooks:
|
||||||
|
|||||||
@@ -3,22 +3,16 @@
|
|||||||
# Use BuildKit, otherwise building on ARM fails
|
# Use BuildKit, otherwise building on ARM fails
|
||||||
export DOCKER_BUILDKIT=1
|
export DOCKER_BUILDKIT=1
|
||||||
|
|
||||||
IMAGE_NAME=freqtradeorg/freqtrade
|
|
||||||
CACHE_IMAGE=freqtradeorg/freqtrade_cache
|
|
||||||
GHCR_IMAGE_NAME=ghcr.io/freqtrade/freqtrade
|
|
||||||
|
|
||||||
# Replace / with _ to create a valid tag
|
# Replace / with _ to create a valid tag
|
||||||
TAG=$(echo "${BRANCH_NAME}" | sed -e "s/\//_/g")
|
TAG=$(echo "${BRANCH_NAME}" | sed -e "s/\//_/g")
|
||||||
TAG_PLOT=${TAG}_plot
|
TAG_PLOT=${TAG}_plot
|
||||||
TAG_FREQAI=${TAG}_freqai
|
TAG_FREQAI=${TAG}_freqai
|
||||||
TAG_FREQAI_RL=${TAG_FREQAI}rl
|
|
||||||
TAG_FREQAI_TORCH=${TAG_FREQAI}torch
|
|
||||||
TAG_PI="${TAG}_pi"
|
TAG_PI="${TAG}_pi"
|
||||||
|
|
||||||
TAG_ARM=${TAG}_arm
|
TAG_ARM=${TAG}_arm
|
||||||
TAG_PLOT_ARM=${TAG_PLOT}_arm
|
TAG_PLOT_ARM=${TAG_PLOT}_arm
|
||||||
TAG_FREQAI_ARM=${TAG_FREQAI}_arm
|
TAG_FREQAI_ARM=${TAG_FREQAI}_arm
|
||||||
TAG_FREQAI_RL_ARM=${TAG_FREQAI_RL}_arm
|
CACHE_IMAGE=freqtradeorg/freqtrade_cache
|
||||||
|
|
||||||
echo "Running for ${TAG}"
|
echo "Running for ${TAG}"
|
||||||
|
|
||||||
@@ -42,19 +36,17 @@ if [ $? -ne 0 ]; then
|
|||||||
echo "failed building multiarch images"
|
echo "failed building multiarch images"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
docker build --build-arg sourceimage=freqtrade --build-arg sourcetag=${TAG_ARM} -t freqtrade:${TAG_PLOT_ARM} -f docker/Dockerfile.plot .
|
|
||||||
docker build --build-arg sourceimage=freqtrade --build-arg sourcetag=${TAG_ARM} -t freqtrade:${TAG_FREQAI_ARM} -f docker/Dockerfile.freqai .
|
|
||||||
docker build --build-arg sourceimage=freqtrade --build-arg sourcetag=${TAG_FREQAI_ARM} -t freqtrade:${TAG_FREQAI_RL_ARM} -f docker/Dockerfile.freqai_rl .
|
|
||||||
|
|
||||||
# Tag image for upload and next build step
|
# Tag image for upload and next build step
|
||||||
docker tag freqtrade:$TAG_ARM ${CACHE_IMAGE}:$TAG_ARM
|
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_PLOT_ARM ${CACHE_IMAGE}:$TAG_PLOT_ARM
|
||||||
docker tag freqtrade:$TAG_FREQAI_ARM ${CACHE_IMAGE}:$TAG_FREQAI_ARM
|
docker tag freqtrade:$TAG_FREQAI_ARM ${CACHE_IMAGE}:$TAG_FREQAI_ARM
|
||||||
docker tag freqtrade:$TAG_FREQAI_RL_ARM ${CACHE_IMAGE}:$TAG_FREQAI_RL_ARM
|
|
||||||
|
|
||||||
# Run backtest
|
# Run backtest
|
||||||
docker run --rm -v $(pwd)/tests/testdata/config.tests.json:/freqtrade/config.json:ro -v $(pwd)/tests:/tests freqtrade:${TAG_ARM} backtesting --datadir /tests/testdata --strategy-path /tests/strategy/strats/ --strategy StrategyTestV3
|
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
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "failed running backtest"
|
echo "failed running backtest"
|
||||||
@@ -63,9 +55,9 @@ fi
|
|||||||
|
|
||||||
docker images
|
docker images
|
||||||
|
|
||||||
|
# docker push ${IMAGE_NAME}
|
||||||
docker push ${CACHE_IMAGE}:$TAG_PLOT_ARM
|
docker push ${CACHE_IMAGE}:$TAG_PLOT_ARM
|
||||||
docker push ${CACHE_IMAGE}:$TAG_FREQAI_ARM
|
docker push ${CACHE_IMAGE}:$TAG_FREQAI_ARM
|
||||||
docker push ${CACHE_IMAGE}:$TAG_FREQAI_RL_ARM
|
|
||||||
docker push ${CACHE_IMAGE}:$TAG_ARM
|
docker push ${CACHE_IMAGE}:$TAG_ARM
|
||||||
|
|
||||||
# Create multi-arch image
|
# Create multi-arch image
|
||||||
@@ -73,47 +65,22 @@ docker push ${CACHE_IMAGE}:$TAG_ARM
|
|||||||
# Otherwise installation might fail.
|
# Otherwise installation might fail.
|
||||||
echo "create manifests"
|
echo "create manifests"
|
||||||
|
|
||||||
docker manifest create ${IMAGE_NAME}:${TAG} ${CACHE_IMAGE}:${TAG} ${CACHE_IMAGE}:${TAG_ARM} ${IMAGE_NAME}:${TAG_PI}
|
docker manifest create --amend ${IMAGE_NAME}:${TAG} ${CACHE_IMAGE}:${TAG_ARM} ${IMAGE_NAME}:${TAG_PI} ${CACHE_IMAGE}:${TAG}
|
||||||
docker manifest push -p ${IMAGE_NAME}:${TAG}
|
docker manifest push -p ${IMAGE_NAME}:${TAG}
|
||||||
|
|
||||||
docker manifest create ${IMAGE_NAME}:${TAG_PLOT} ${CACHE_IMAGE}:${TAG_PLOT} ${CACHE_IMAGE}:${TAG_PLOT_ARM}
|
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 push -p ${IMAGE_NAME}:${TAG_PLOT}
|
||||||
|
|
||||||
docker manifest create ${IMAGE_NAME}:${TAG_FREQAI} ${CACHE_IMAGE}:${TAG_FREQAI} ${CACHE_IMAGE}:${TAG_FREQAI_ARM}
|
docker manifest create ${IMAGE_NAME}:${TAG_FREQAI} ${CACHE_IMAGE}:${TAG_FREQAI_ARM} ${CACHE_IMAGE}:${TAG_FREQAI}
|
||||||
docker manifest push -p ${IMAGE_NAME}:${TAG_FREQAI}
|
docker manifest push -p ${IMAGE_NAME}:${TAG_FREQAI}
|
||||||
|
|
||||||
docker manifest create ${IMAGE_NAME}:${TAG_FREQAI_RL} ${CACHE_IMAGE}:${TAG_FREQAI_RL} ${CACHE_IMAGE}:${TAG_FREQAI_RL_ARM}
|
|
||||||
docker manifest push -p ${IMAGE_NAME}:${TAG_FREQAI_RL}
|
|
||||||
|
|
||||||
# Create special Torch tag - which is identical to the RL tag.
|
|
||||||
docker manifest create ${IMAGE_NAME}:${TAG_FREQAI_TORCH} ${CACHE_IMAGE}:${TAG_FREQAI_RL} ${CACHE_IMAGE}:${TAG_FREQAI_RL_ARM}
|
|
||||||
docker manifest push -p ${IMAGE_NAME}:${TAG_FREQAI_TORCH}
|
|
||||||
|
|
||||||
# copy images to ghcr.io
|
|
||||||
|
|
||||||
alias crane="docker run --rm -i -v $(pwd)/.crane:/home/nonroot/.docker/ gcr.io/go-containerregistry/crane"
|
|
||||||
mkdir .crane
|
|
||||||
chmod a+rwx .crane
|
|
||||||
|
|
||||||
echo "${GHCR_TOKEN}" | crane auth login ghcr.io -u "${GHCR_USERNAME}" --password-stdin
|
|
||||||
|
|
||||||
crane copy ${IMAGE_NAME}:${TAG_FREQAI_RL} ${GHCR_IMAGE_NAME}:${TAG_FREQAI_RL}
|
|
||||||
crane copy ${IMAGE_NAME}:${TAG_FREQAI_RL} ${GHCR_IMAGE_NAME}:${TAG_FREQAI_TORCH}
|
|
||||||
crane copy ${IMAGE_NAME}:${TAG_FREQAI} ${GHCR_IMAGE_NAME}:${TAG_FREQAI}
|
|
||||||
crane copy ${IMAGE_NAME}:${TAG_PLOT} ${GHCR_IMAGE_NAME}:${TAG_PLOT}
|
|
||||||
crane copy ${IMAGE_NAME}:${TAG} ${GHCR_IMAGE_NAME}:${TAG}
|
|
||||||
|
|
||||||
# Tag as latest for develop builds
|
# Tag as latest for develop builds
|
||||||
if [ "${TAG}" = "develop" ]; then
|
if [ "${TAG}" = "develop" ]; then
|
||||||
echo 'Tagging image as latest'
|
|
||||||
docker manifest create ${IMAGE_NAME}:latest ${CACHE_IMAGE}:${TAG_ARM} ${IMAGE_NAME}:${TAG_PI} ${CACHE_IMAGE}:${TAG}
|
docker manifest create ${IMAGE_NAME}:latest ${CACHE_IMAGE}:${TAG_ARM} ${IMAGE_NAME}:${TAG_PI} ${CACHE_IMAGE}:${TAG}
|
||||||
docker manifest push -p ${IMAGE_NAME}:latest
|
docker manifest push -p ${IMAGE_NAME}:latest
|
||||||
|
|
||||||
crane copy ${IMAGE_NAME}:latest ${GHCR_IMAGE_NAME}:latest
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
docker images
|
docker images
|
||||||
rm -rf .crane
|
|
||||||
|
|
||||||
# Cleanup old images from arm64 node.
|
# Cleanup old images from arm64 node.
|
||||||
docker image prune -a --force --filter "until=24h"
|
docker image prune -a --force --filter "until=24h"
|
||||||
|
|||||||
@@ -2,17 +2,15 @@
|
|||||||
|
|
||||||
# The below assumes a correctly setup docker buildx environment
|
# The below assumes a correctly setup docker buildx environment
|
||||||
|
|
||||||
IMAGE_NAME=freqtradeorg/freqtrade
|
|
||||||
CACHE_IMAGE=freqtradeorg/freqtrade_cache
|
|
||||||
# Replace / with _ to create a valid tag
|
# Replace / with _ to create a valid tag
|
||||||
TAG=$(echo "${BRANCH_NAME}" | sed -e "s/\//_/g")
|
TAG=$(echo "${BRANCH_NAME}" | sed -e "s/\//_/g")
|
||||||
TAG_PLOT=${TAG}_plot
|
TAG_PLOT=${TAG}_plot
|
||||||
TAG_FREQAI=${TAG}_freqai
|
TAG_FREQAI=${TAG}_freqai
|
||||||
TAG_FREQAI_RL=${TAG_FREQAI}rl
|
|
||||||
TAG_PI="${TAG}_pi"
|
TAG_PI="${TAG}_pi"
|
||||||
|
|
||||||
PI_PLATFORM="linux/arm/v7"
|
PI_PLATFORM="linux/arm/v7"
|
||||||
echo "Running for ${TAG}"
|
echo "Running for ${TAG}"
|
||||||
|
CACHE_IMAGE=freqtradeorg/freqtrade_cache
|
||||||
CACHE_TAG=${CACHE_IMAGE}:${TAG_PI}_cache
|
CACHE_TAG=${CACHE_IMAGE}:${TAG_PI}_cache
|
||||||
|
|
||||||
# Add commit and commit_message to docker container
|
# Add commit and commit_message to docker container
|
||||||
@@ -27,10 +25,7 @@ if [ "${GITHUB_EVENT_NAME}" = "schedule" ]; then
|
|||||||
--cache-to=type=registry,ref=${CACHE_TAG} \
|
--cache-to=type=registry,ref=${CACHE_TAG} \
|
||||||
-f docker/Dockerfile.armhf \
|
-f docker/Dockerfile.armhf \
|
||||||
--platform ${PI_PLATFORM} \
|
--platform ${PI_PLATFORM} \
|
||||||
-t ${IMAGE_NAME}:${TAG_PI} \
|
-t ${IMAGE_NAME}:${TAG_PI} --push .
|
||||||
--push \
|
|
||||||
--provenance=false \
|
|
||||||
.
|
|
||||||
else
|
else
|
||||||
echo "event ${GITHUB_EVENT_NAME}: building with cache"
|
echo "event ${GITHUB_EVENT_NAME}: building with cache"
|
||||||
# Build regular image
|
# Build regular image
|
||||||
@@ -39,16 +34,12 @@ else
|
|||||||
|
|
||||||
# Pull last build to avoid rebuilding the whole image
|
# Pull last build to avoid rebuilding the whole image
|
||||||
# docker pull --platform ${PI_PLATFORM} ${IMAGE_NAME}:${TAG}
|
# docker pull --platform ${PI_PLATFORM} ${IMAGE_NAME}:${TAG}
|
||||||
# disable provenance due to https://github.com/docker/buildx/issues/1509
|
|
||||||
docker buildx build \
|
docker buildx build \
|
||||||
--cache-from=type=registry,ref=${CACHE_TAG} \
|
--cache-from=type=registry,ref=${CACHE_TAG} \
|
||||||
--cache-to=type=registry,ref=${CACHE_TAG} \
|
--cache-to=type=registry,ref=${CACHE_TAG} \
|
||||||
-f docker/Dockerfile.armhf \
|
-f docker/Dockerfile.armhf \
|
||||||
--platform ${PI_PLATFORM} \
|
--platform ${PI_PLATFORM} \
|
||||||
-t ${IMAGE_NAME}:${TAG_PI} \
|
-t ${IMAGE_NAME}:${TAG_PI} --push .
|
||||||
--push \
|
|
||||||
--provenance=false \
|
|
||||||
.
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
@@ -58,16 +49,14 @@ fi
|
|||||||
# Tag image for upload and next build step
|
# Tag image for upload and next build step
|
||||||
docker tag freqtrade:$TAG ${CACHE_IMAGE}:$TAG
|
docker tag freqtrade:$TAG ${CACHE_IMAGE}:$TAG
|
||||||
|
|
||||||
docker build --build-arg sourceimage=freqtrade --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_PLOT} -f docker/Dockerfile.plot .
|
||||||
docker build --build-arg sourceimage=freqtrade --build-arg sourcetag=${TAG} -t freqtrade:${TAG_FREQAI} -f docker/Dockerfile.freqai .
|
docker build --cache-from freqtrade:${TAG} --build-arg sourceimage=${CACHE_IMAGE} --build-arg sourcetag=${TAG} -t freqtrade:${TAG_FREQAI} -f docker/Dockerfile.freqai .
|
||||||
docker build --build-arg sourceimage=freqtrade --build-arg sourcetag=${TAG_FREQAI} -t freqtrade:${TAG_FREQAI_RL} -f docker/Dockerfile.freqai_rl .
|
|
||||||
|
|
||||||
docker tag freqtrade:$TAG_PLOT ${CACHE_IMAGE}:$TAG_PLOT
|
docker tag freqtrade:$TAG_PLOT ${CACHE_IMAGE}:$TAG_PLOT
|
||||||
docker tag freqtrade:$TAG_FREQAI ${CACHE_IMAGE}:$TAG_FREQAI
|
docker tag freqtrade:$TAG_FREQAI ${CACHE_IMAGE}:$TAG_FREQAI
|
||||||
docker tag freqtrade:$TAG_FREQAI_RL ${CACHE_IMAGE}:$TAG_FREQAI_RL
|
|
||||||
|
|
||||||
# Run backtest
|
# Run backtest
|
||||||
docker run --rm -v $(pwd)/tests/testdata/config.tests.json:/freqtrade/config.json:ro -v $(pwd)/tests:/tests freqtrade:${TAG} backtesting --datadir /tests/testdata --strategy-path /tests/strategy/strats/ --strategy StrategyTestV3
|
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
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "failed running backtest"
|
echo "failed running backtest"
|
||||||
@@ -76,10 +65,11 @@ fi
|
|||||||
|
|
||||||
docker images
|
docker images
|
||||||
|
|
||||||
docker push ${CACHE_IMAGE}:$TAG
|
docker push ${CACHE_IMAGE}
|
||||||
docker push ${CACHE_IMAGE}:$TAG_PLOT
|
docker push ${CACHE_IMAGE}:$TAG_PLOT
|
||||||
docker push ${CACHE_IMAGE}:$TAG_FREQAI
|
docker push ${CACHE_IMAGE}:$TAG_FREQAI
|
||||||
docker push ${CACHE_IMAGE}:$TAG_FREQAI_RL
|
docker push ${CACHE_IMAGE}:$TAG
|
||||||
|
|
||||||
|
|
||||||
docker images
|
docker images
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"max_open_trades": 3,
|
"max_open_trades": 3,
|
||||||
"stake_currency": "USDT",
|
"stake_currency": "BTC",
|
||||||
"stake_amount": 0.05,
|
"stake_amount": 0.05,
|
||||||
"tradable_balance_ratio": 0.99,
|
"tradable_balance_ratio": 0.99,
|
||||||
"fiat_display_currency": "USD",
|
"fiat_display_currency": "USD",
|
||||||
@@ -36,29 +36,43 @@
|
|||||||
"ccxt_async_config": {
|
"ccxt_async_config": {
|
||||||
},
|
},
|
||||||
"pair_whitelist": [
|
"pair_whitelist": [
|
||||||
"ALGO/USDT",
|
"ALGO/BTC",
|
||||||
"ATOM/USDT",
|
"ATOM/BTC",
|
||||||
"BAT/USDT",
|
"BAT/BTC",
|
||||||
"BCH/USDT",
|
"BCH/BTC",
|
||||||
"BRD/USDT",
|
"BRD/BTC",
|
||||||
"EOS/USDT",
|
"EOS/BTC",
|
||||||
"ETH/USDT",
|
"ETH/BTC",
|
||||||
"IOTA/USDT",
|
"IOTA/BTC",
|
||||||
"LINK/USDT",
|
"LINK/BTC",
|
||||||
"LTC/USDT",
|
"LTC/BTC",
|
||||||
"NEO/USDT",
|
"NEO/BTC",
|
||||||
"NXS/USDT",
|
"NXS/BTC",
|
||||||
"XMR/USDT",
|
"XMR/BTC",
|
||||||
"XRP/USDT",
|
"XRP/BTC",
|
||||||
"XTZ/USDT"
|
"XTZ/BTC"
|
||||||
],
|
],
|
||||||
"pair_blacklist": [
|
"pair_blacklist": [
|
||||||
"BNB/.*"
|
"BNB/BTC"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"pairlists": [
|
"pairlists": [
|
||||||
{"method": "StaticPairList"}
|
{"method": "StaticPairList"}
|
||||||
],
|
],
|
||||||
|
"edge": {
|
||||||
|
"enabled": false,
|
||||||
|
"process_throttle_secs": 3600,
|
||||||
|
"calculate_since_number_of_days": 7,
|
||||||
|
"allowed_risk": 0.01,
|
||||||
|
"stoploss_range_min": -0.01,
|
||||||
|
"stoploss_range_max": -0.1,
|
||||||
|
"stoploss_range_step": -0.01,
|
||||||
|
"minimum_winrate": 0.60,
|
||||||
|
"minimum_expectancy": 0.20,
|
||||||
|
"min_trade_number": 10,
|
||||||
|
"max_trade_duration_minute": 1440,
|
||||||
|
"remove_pumps": false
|
||||||
|
},
|
||||||
"telegram": {
|
"telegram": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"token": "your_telegram_token",
|
"token": "your_telegram_token",
|
||||||
|
|||||||
@@ -29,11 +29,14 @@
|
|||||||
"order_book_top": 1
|
"order_book_top": 1
|
||||||
},
|
},
|
||||||
"exchange": {
|
"exchange": {
|
||||||
"name": "binance",
|
"name": "bittrex",
|
||||||
"key": "your_exchange_key",
|
"key": "your_exchange_key",
|
||||||
"secret": "your_exchange_secret",
|
"secret": "your_exchange_secret",
|
||||||
"ccxt_config": {},
|
"ccxt_config": {"enableRateLimit": true},
|
||||||
"ccxt_async_config": {},
|
"ccxt_async_config": {
|
||||||
|
"enableRateLimit": true,
|
||||||
|
"rateLimit": 500
|
||||||
|
},
|
||||||
"pair_whitelist": [
|
"pair_whitelist": [
|
||||||
"ETH/BTC",
|
"ETH/BTC",
|
||||||
"LTC/BTC",
|
"LTC/BTC",
|
||||||
@@ -53,6 +56,20 @@
|
|||||||
"pairlists": [
|
"pairlists": [
|
||||||
{"method": "StaticPairList"}
|
{"method": "StaticPairList"}
|
||||||
],
|
],
|
||||||
|
"edge": {
|
||||||
|
"enabled": false,
|
||||||
|
"process_throttle_secs": 3600,
|
||||||
|
"calculate_since_number_of_days": 7,
|
||||||
|
"allowed_risk": 0.01,
|
||||||
|
"stoploss_range_min": -0.01,
|
||||||
|
"stoploss_range_max": -0.1,
|
||||||
|
"stoploss_range_step": -0.01,
|
||||||
|
"minimum_winrate": 0.60,
|
||||||
|
"minimum_expectancy": 0.20,
|
||||||
|
"min_trade_number": 10,
|
||||||
|
"max_trade_duration_minute": 1440,
|
||||||
|
"remove_pumps": false
|
||||||
|
},
|
||||||
"telegram": {
|
"telegram": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"token": "your_telegram_token",
|
"token": "your_telegram_token",
|
||||||
@@ -18,11 +18,16 @@
|
|||||||
"name": "binance",
|
"name": "binance",
|
||||||
"key": "",
|
"key": "",
|
||||||
"secret": "",
|
"secret": "",
|
||||||
"ccxt_config": {},
|
"ccxt_config": {
|
||||||
"ccxt_async_config": {},
|
"enableRateLimit": true
|
||||||
|
},
|
||||||
|
"ccxt_async_config": {
|
||||||
|
"enableRateLimit": true,
|
||||||
|
"rateLimit": 200
|
||||||
|
},
|
||||||
"pair_whitelist": [
|
"pair_whitelist": [
|
||||||
"1INCH/USDT:USDT",
|
"1INCH/USDT",
|
||||||
"ALGO/USDT:USDT"
|
"ALGO/USDT"
|
||||||
],
|
],
|
||||||
"pair_blacklist": []
|
"pair_blacklist": []
|
||||||
},
|
},
|
||||||
@@ -48,11 +53,12 @@
|
|||||||
],
|
],
|
||||||
"freqai": {
|
"freqai": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"purge_old_models": 2,
|
"startup_candles": 10000,
|
||||||
|
"purge_old_models": true,
|
||||||
"train_period_days": 15,
|
"train_period_days": 15,
|
||||||
"backtest_period_days": 7,
|
"backtest_period_days": 7,
|
||||||
"live_retrain_hours": 0,
|
"live_retrain_hours": 0,
|
||||||
"identifier": "unique-id",
|
"identifier": "uniqe-id",
|
||||||
"feature_parameters": {
|
"feature_parameters": {
|
||||||
"include_timeframes": [
|
"include_timeframes": [
|
||||||
"3m",
|
"3m",
|
||||||
@@ -60,8 +66,8 @@
|
|||||||
"1h"
|
"1h"
|
||||||
],
|
],
|
||||||
"include_corr_pairlist": [
|
"include_corr_pairlist": [
|
||||||
"BTC/USDT:USDT",
|
"BTC/USDT",
|
||||||
"ETH/USDT:USDT"
|
"ETH/USDT"
|
||||||
],
|
],
|
||||||
"label_period_candles": 20,
|
"label_period_candles": 20,
|
||||||
"include_shifted_candles": 2,
|
"include_shifted_candles": 2,
|
||||||
@@ -69,17 +75,17 @@
|
|||||||
"weight_factor": 0.9,
|
"weight_factor": 0.9,
|
||||||
"principal_component_analysis": false,
|
"principal_component_analysis": false,
|
||||||
"use_SVM_to_remove_outliers": true,
|
"use_SVM_to_remove_outliers": true,
|
||||||
"indicator_periods_candles": [
|
"stratify_training_data": 0,
|
||||||
10,
|
"indicator_max_period_candles": 20,
|
||||||
20
|
"indicator_periods_candles": [10, 20]
|
||||||
],
|
|
||||||
"plot_feature_importances": 0
|
|
||||||
},
|
},
|
||||||
"data_split_parameters": {
|
"data_split_parameters": {
|
||||||
"test_size": 0.33,
|
"test_size": 0.33,
|
||||||
"random_state": 1
|
"random_state": 1
|
||||||
},
|
},
|
||||||
"model_training_parameters": {}
|
"model_training_parameters": {
|
||||||
|
"n_estimators": 1000
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"bot_name": "",
|
"bot_name": "",
|
||||||
"force_entry_enable": true,
|
"force_entry_enable": true,
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
{
|
{
|
||||||
"max_open_trades": 3,
|
"max_open_trades": 3,
|
||||||
"stake_currency": "BTC",
|
"stake_currency": "USD",
|
||||||
"stake_amount": 0.05,
|
"stake_amount": 50,
|
||||||
"tradable_balance_ratio": 0.99,
|
"tradable_balance_ratio": 0.99,
|
||||||
"fiat_display_currency": "USD",
|
"fiat_display_currency": "USD",
|
||||||
"timeframe": "5m",
|
"timeframe": "5m",
|
||||||
"dry_run": true,
|
"dry_run": true,
|
||||||
"cancel_open_orders_on_exit": false,
|
"cancel_open_orders_on_exit": false,
|
||||||
"unfilledtimeout": {
|
"unfilledtimeout": {
|
||||||
"entry": 5,
|
"entry": 10,
|
||||||
"exit": 5,
|
"exit": 10,
|
||||||
"exit_timeout_count": 0,
|
"exit_timeout_count": 0,
|
||||||
"unit": "minutes"
|
"unit": "minutes"
|
||||||
},
|
},
|
||||||
@@ -23,33 +23,55 @@
|
|||||||
"bids_to_ask_delta": 1
|
"bids_to_ask_delta": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"exit_pricing":{
|
"exit_pricing": {
|
||||||
"price_side": "same",
|
"price_side": "same",
|
||||||
"use_order_book": true,
|
"use_order_book": true,
|
||||||
"order_book_top": 1
|
"order_book_top": 1
|
||||||
},
|
},
|
||||||
"exchange": {
|
"exchange": {
|
||||||
"name": "gate",
|
"name": "ftx",
|
||||||
"key": "your_exchange_key",
|
"key": "your_exchange_key",
|
||||||
"secret": "your_exchange_secret",
|
"secret": "your_exchange_secret",
|
||||||
"ccxt_config": {},
|
"ccxt_config": {},
|
||||||
"ccxt_async_config": {},
|
"ccxt_async_config": {},
|
||||||
"pair_whitelist": [
|
"pair_whitelist": [
|
||||||
"ETH/BTC",
|
"BTC/USD",
|
||||||
"LTC/BTC",
|
"ETH/USD",
|
||||||
"ETC/BTC",
|
"BNB/USD",
|
||||||
"XLM/BTC",
|
"USDT/USD",
|
||||||
"XRP/BTC",
|
"LTC/USD",
|
||||||
"ADA/BTC",
|
"SRM/USD",
|
||||||
"DOT/BTC"
|
"SXP/USD",
|
||||||
|
"XRP/USD",
|
||||||
|
"DOGE/USD",
|
||||||
|
"1INCH/USD",
|
||||||
|
"CHZ/USD",
|
||||||
|
"MATIC/USD",
|
||||||
|
"LINK/USD",
|
||||||
|
"OXY/USD",
|
||||||
|
"SUSHI/USD"
|
||||||
],
|
],
|
||||||
"pair_blacklist": [
|
"pair_blacklist": [
|
||||||
"DOGE/BTC"
|
"FTT/USD"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"pairlists": [
|
"pairlists": [
|
||||||
{"method": "StaticPairList"}
|
{"method": "StaticPairList"}
|
||||||
],
|
],
|
||||||
|
"edge": {
|
||||||
|
"enabled": false,
|
||||||
|
"process_throttle_secs": 3600,
|
||||||
|
"calculate_since_number_of_days": 7,
|
||||||
|
"allowed_risk": 0.01,
|
||||||
|
"stoploss_range_min": -0.01,
|
||||||
|
"stoploss_range_max": -0.1,
|
||||||
|
"stoploss_range_step": -0.01,
|
||||||
|
"minimum_winrate": 0.60,
|
||||||
|
"minimum_expectancy": 0.20,
|
||||||
|
"min_trade_number": 10,
|
||||||
|
"max_trade_duration_minute": 1440,
|
||||||
|
"remove_pumps": false
|
||||||
|
},
|
||||||
"telegram": {
|
"telegram": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"token": "your_telegram_token",
|
"token": "your_telegram_token",
|
||||||
@@ -60,17 +60,15 @@
|
|||||||
"force_entry": "market",
|
"force_entry": "market",
|
||||||
"stoploss": "market",
|
"stoploss": "market",
|
||||||
"stoploss_on_exchange": false,
|
"stoploss_on_exchange": false,
|
||||||
"stoploss_price_type": "last",
|
|
||||||
"stoploss_on_exchange_interval": 60,
|
"stoploss_on_exchange_interval": 60,
|
||||||
"stoploss_on_exchange_limit_ratio": 0.99
|
"stoploss_on_exchange_limit_ratio": 0.99
|
||||||
},
|
},
|
||||||
"order_time_in_force": {
|
"order_time_in_force": {
|
||||||
"entry": "GTC",
|
"entry": "gtc",
|
||||||
"exit": "GTC"
|
"exit": "gtc"
|
||||||
},
|
},
|
||||||
"pairlists": [
|
"pairlists": [
|
||||||
{"method": "StaticPairList"},
|
{"method": "StaticPairList"},
|
||||||
{"method": "FullTradesFilter"},
|
|
||||||
{
|
{
|
||||||
"method": "VolumePairList",
|
"method": "VolumePairList",
|
||||||
"number_assets": 20,
|
"number_assets": 20,
|
||||||
@@ -90,6 +88,7 @@
|
|||||||
],
|
],
|
||||||
"exchange": {
|
"exchange": {
|
||||||
"name": "binance",
|
"name": "binance",
|
||||||
|
"sandbox": false,
|
||||||
"key": "your_exchange_key",
|
"key": "your_exchange_key",
|
||||||
"secret": "your_exchange_secret",
|
"secret": "your_exchange_secret",
|
||||||
"password": "",
|
"password": "",
|
||||||
@@ -173,24 +172,7 @@
|
|||||||
"jwt_secret_key": "somethingrandom",
|
"jwt_secret_key": "somethingrandom",
|
||||||
"CORS_origins": [],
|
"CORS_origins": [],
|
||||||
"username": "freqtrader",
|
"username": "freqtrader",
|
||||||
"password": "SuperSecurePassword",
|
"password": "SuperSecurePassword"
|
||||||
"ws_token": "secret_ws_t0ken."
|
|
||||||
},
|
|
||||||
"external_message_consumer": {
|
|
||||||
"enabled": false,
|
|
||||||
"producers": [
|
|
||||||
{
|
|
||||||
"name": "default",
|
|
||||||
"host": "127.0.0.2",
|
|
||||||
"port": 8080,
|
|
||||||
"ws_token": "secret_ws_t0ken."
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"wait_timeout": 300,
|
|
||||||
"ping_timeout": 10,
|
|
||||||
"sleep_time": 10,
|
|
||||||
"remove_entry_exit_signals": false,
|
|
||||||
"message_size_limit": 8
|
|
||||||
},
|
},
|
||||||
"bot_name": "freqtrade",
|
"bot_name": "freqtrade",
|
||||||
"db_url": "sqlite:///tradesv3.sqlite",
|
"db_url": "sqlite:///tradesv3.sqlite",
|
||||||
@@ -205,7 +187,6 @@
|
|||||||
"strategy_path": "user_data/strategies/",
|
"strategy_path": "user_data/strategies/",
|
||||||
"recursive_strategy_search": false,
|
"recursive_strategy_search": false,
|
||||||
"add_config_files": [],
|
"add_config_files": [],
|
||||||
"reduce_df_footprint": false,
|
"dataformat_ohlcv": "json",
|
||||||
"dataformat_ohlcv": "feather",
|
"dataformat_trades": "jsongz"
|
||||||
"dataformat_trades": "feather"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,20 @@
|
|||||||
"pairlists": [
|
"pairlists": [
|
||||||
{"method": "StaticPairList"}
|
{"method": "StaticPairList"}
|
||||||
],
|
],
|
||||||
|
"edge": {
|
||||||
|
"enabled": false,
|
||||||
|
"process_throttle_secs": 3600,
|
||||||
|
"calculate_since_number_of_days": 7,
|
||||||
|
"allowed_risk": 0.01,
|
||||||
|
"stoploss_range_min": -0.01,
|
||||||
|
"stoploss_range_max": -0.1,
|
||||||
|
"stoploss_range_step": -0.01,
|
||||||
|
"minimum_winrate": 0.60,
|
||||||
|
"minimum_expectancy": 0.20,
|
||||||
|
"min_trade_number": 10,
|
||||||
|
"max_trade_duration_minute": 1440,
|
||||||
|
"remove_pumps": false
|
||||||
|
},
|
||||||
"telegram": {
|
"telegram": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"token": "your_telegram_token",
|
"token": "your_telegram_token",
|
||||||
|
|||||||
@@ -1,19 +1,11 @@
|
|||||||
---
|
---
|
||||||
|
version: '3'
|
||||||
services:
|
services:
|
||||||
freqtrade:
|
freqtrade:
|
||||||
image: freqtradeorg/freqtrade:stable
|
image: freqtradeorg/freqtrade:stable
|
||||||
# image: freqtradeorg/freqtrade:develop
|
# image: freqtradeorg/freqtrade:develop
|
||||||
# Use plotting image
|
# Use plotting image
|
||||||
# image: freqtradeorg/freqtrade:develop_plot
|
# image: freqtradeorg/freqtrade:develop_plot
|
||||||
# # Enable GPU Image and GPU Resources (only relevant for freqAI)
|
|
||||||
# # Make sure to uncomment the whole deploy section
|
|
||||||
# deploy:
|
|
||||||
# resources:
|
|
||||||
# reservations:
|
|
||||||
# devices:
|
|
||||||
# - driver: nvidia
|
|
||||||
# count: 1
|
|
||||||
# capabilities: [gpu]
|
|
||||||
# Build step - only needed when additional dependencies are needed
|
# Build step - only needed when additional dependencies are needed
|
||||||
# build:
|
# build:
|
||||||
# context: .
|
# context: .
|
||||||
@@ -24,7 +16,7 @@ services:
|
|||||||
- "./user_data:/freqtrade/user_data"
|
- "./user_data:/freqtrade/user_data"
|
||||||
# Expose api on port 8080 (localhost only)
|
# Expose api on port 8080 (localhost only)
|
||||||
# Please read the https://www.freqtrade.io/en/stable/rest-api/ documentation
|
# Please read the https://www.freqtrade.io/en/stable/rest-api/ documentation
|
||||||
# for more information.
|
# before enabling this.
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:8080:8080"
|
- "127.0.0.1:8080:8080"
|
||||||
# Default command used when running `docker compose up`
|
# Default command used when running `docker compose up`
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM python:3.11.8-slim-bookworm as base
|
FROM python:3.9.12-slim-bullseye as base
|
||||||
|
|
||||||
# Setup env
|
# Setup env
|
||||||
ENV LANG C.UTF-8
|
ENV LANG C.UTF-8
|
||||||
@@ -11,13 +11,12 @@ ENV FT_APP_ENV="docker"
|
|||||||
# Prepare environment
|
# Prepare environment
|
||||||
RUN mkdir /freqtrade \
|
RUN mkdir /freqtrade \
|
||||||
&& apt-get update \
|
&& apt-get update \
|
||||||
&& apt-get -y install sudo libatlas3-base libopenblas-dev curl sqlite3 libhdf5-dev libutf8proc-dev libsnappy-dev \
|
&& apt-get -y install sudo libatlas3-base curl sqlite3 libhdf5-dev \
|
||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
&& useradd -u 1000 -G sudo -U -m ftuser \
|
&& useradd -u 1000 -G sudo -U -m ftuser \
|
||||||
&& chown ftuser:ftuser /freqtrade \
|
&& chown ftuser:ftuser /freqtrade \
|
||||||
# Allow sudoers
|
# Allow sudoers
|
||||||
&& echo "ftuser ALL=(ALL) NOPASSWD: /bin/chown" >> /etc/sudoers \
|
&& echo "ftuser ALL=(ALL) NOPASSWD: /bin/chown" >> /etc/sudoers
|
||||||
&& pip install --upgrade "pip<=24.0"
|
|
||||||
|
|
||||||
WORKDIR /freqtrade
|
WORKDIR /freqtrade
|
||||||
|
|
||||||
@@ -26,16 +25,18 @@ FROM base as python-deps
|
|||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get -y install build-essential libssl-dev libffi-dev libgfortran5 pkg-config cmake gcc \
|
&& apt-get -y install build-essential libssl-dev libffi-dev libgfortran5 pkg-config cmake gcc \
|
||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
|
&& pip install --upgrade pip \
|
||||||
&& echo "[global]\nextra-index-url=https://www.piwheels.org/simple" > /etc/pip.conf
|
&& echo "[global]\nextra-index-url=https://www.piwheels.org/simple" > /etc/pip.conf
|
||||||
|
|
||||||
# Install TA-lib
|
# Install TA-lib
|
||||||
COPY build_helpers/* /tmp/
|
COPY build_helpers/* /tmp/
|
||||||
|
RUN cd /tmp && /tmp/install_ta-lib.sh && rm -r /tmp/*ta-lib*
|
||||||
|
ENV LD_LIBRARY_PATH /usr/local/lib
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
COPY --chown=ftuser:ftuser requirements.txt /freqtrade/
|
COPY --chown=ftuser:ftuser requirements.txt /freqtrade/
|
||||||
USER ftuser
|
USER ftuser
|
||||||
RUN pip install --user --no-cache-dir numpy \
|
RUN pip install --user --no-cache-dir numpy \
|
||||||
&& pip install --user --no-index --find-links /tmp/ pyarrow TA-Lib \
|
|
||||||
&& pip install --user --no-cache-dir -r requirements.txt
|
&& pip install --user --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
# Copy dependencies to runtime-image
|
# Copy dependencies to runtime-image
|
||||||
|
|||||||
@@ -6,3 +6,4 @@ FROM ${sourceimage}:${sourcetag}
|
|||||||
COPY requirements-freqai.txt /freqtrade/
|
COPY requirements-freqai.txt /freqtrade/
|
||||||
|
|
||||||
RUN pip install -r requirements-freqai.txt --user --no-cache-dir
|
RUN pip install -r requirements-freqai.txt --user --no-cache-dir
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
ARG sourceimage=freqtradeorg/freqtrade
|
|
||||||
ARG sourcetag=develop_freqai
|
|
||||||
FROM ${sourceimage}:${sourcetag}
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
COPY requirements-freqai.txt requirements-freqai-rl.txt /freqtrade/
|
|
||||||
|
|
||||||
RUN pip install -r requirements-freqai-rl.txt --user --no-cache-dir
|
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
FROM freqtradeorg/freqtrade:develop_plot
|
FROM freqtradeorg/freqtrade:develop_plot
|
||||||
|
|
||||||
|
|
||||||
# Pin prompt-toolkit to avoid questionary version conflict
|
RUN pip install jupyterlab --user --no-cache-dir
|
||||||
RUN pip install jupyterlab "prompt-toolkit<=3.0.36" jupyter-client --user --no-cache-dir
|
|
||||||
|
|
||||||
# Empty the ENTRYPOINT to allow all commands
|
# Empty the ENTRYPOINT to allow all commands
|
||||||
ENTRYPOINT []
|
ENTRYPOINT []
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
---
|
|
||||||
services:
|
|
||||||
freqtrade:
|
|
||||||
image: freqtradeorg/freqtrade:stable_freqaitorch
|
|
||||||
# # Enable GPU Image and GPU Resources
|
|
||||||
# # Make sure to uncomment the whole deploy section
|
|
||||||
# deploy:
|
|
||||||
# resources:
|
|
||||||
# reservations:
|
|
||||||
# devices:
|
|
||||||
# - driver: nvidia
|
|
||||||
# count: 1
|
|
||||||
# capabilities: [gpu]
|
|
||||||
|
|
||||||
# Build step - only needed when additional dependencies are needed
|
|
||||||
# build:
|
|
||||||
# context: .
|
|
||||||
# dockerfile: "./docker/Dockerfile.custom"
|
|
||||||
restart: unless-stopped
|
|
||||||
container_name: freqtrade
|
|
||||||
volumes:
|
|
||||||
- "./user_data:/freqtrade/user_data"
|
|
||||||
# Expose api on port 8080 (localhost only)
|
|
||||||
# Please read the https://www.freqtrade.io/en/stable/rest-api/ documentation
|
|
||||||
# for more information.
|
|
||||||
ports:
|
|
||||||
- "127.0.0.1:8080:8080"
|
|
||||||
# Default command used when running `docker compose up`
|
|
||||||
command: >
|
|
||||||
trade
|
|
||||||
--logfile /freqtrade/user_data/logs/freqtrade.log
|
|
||||||
--db-url sqlite:////freqtrade/user_data/tradesv3.sqlite
|
|
||||||
--config /freqtrade/user_data/config.json
|
|
||||||
--freqaimodel XGBoostRegressor
|
|
||||||
--strategy FreqaiExampleStrategy
|
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
---
|
---
|
||||||
|
version: '3'
|
||||||
services:
|
services:
|
||||||
ft_jupyterlab:
|
ft_jupyterlab:
|
||||||
build:
|
build:
|
||||||
context: ..
|
context: ..
|
||||||
dockerfile: docker/Dockerfile.jupyter
|
dockerfile: docker/Dockerfile.jupyter
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
# container_name: freqtrade
|
container_name: freqtrade
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:8888:8888"
|
- "127.0.0.1:8888:8888"
|
||||||
volumes:
|
volumes:
|
||||||
- "../user_data:/freqtrade/user_data"
|
- "./user_data:/freqtrade/user_data"
|
||||||
# Default command used when running `docker compose up`
|
# Default command used when running `docker compose up`
|
||||||
command: >
|
command: >
|
||||||
jupyter lab --port=8888 --ip 0.0.0.0 --allow-root
|
jupyter lab --port=8888 --ip 0.0.0.0 --allow-root
|
||||||
|
|||||||
@@ -29,22 +29,20 @@ If all goes well, you should now see a `backtest-result-{timestamp}_signals.pkl`
|
|||||||
`user_data/backtest_results` folder.
|
`user_data/backtest_results` folder.
|
||||||
|
|
||||||
To analyze the entry/exit tags, we now need to use the `freqtrade backtesting-analysis` command
|
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:
|
with `--analysis-groups` option provided with space-separated arguments (default `0 1 2`):
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
freqtrade backtesting-analysis -c <config.json> --analysis-groups 0 1 2 3 4 5
|
freqtrade backtesting-analysis -c <config.json> --analysis-groups 0 1 2 3 4
|
||||||
```
|
```
|
||||||
|
|
||||||
This command will read from the last backtesting results. The `--analysis-groups` option is
|
This command will read from the last backtesting results. The `--analysis-groups` option is
|
||||||
used to specify the various tabular outputs showing the profit of each group or trade,
|
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):
|
ranging from the simplest (0) to the most detailed per pair, per buy and per sell tag (4):
|
||||||
|
|
||||||
* 0: overall winrate and profit summary by enter_tag
|
|
||||||
* 1: profit summaries grouped by enter_tag
|
* 1: profit summaries grouped by enter_tag
|
||||||
* 2: profit summaries grouped by enter_tag and exit_tag
|
* 2: profit summaries grouped by enter_tag and exit_tag
|
||||||
* 3: profit summaries grouped by pair and enter_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)
|
* 4: profit summaries grouped by pair, enter_ and exit_tag (this can get quite large)
|
||||||
* 5: profit summaries grouped by exit_tag
|
|
||||||
|
|
||||||
More options are available by running with the `-h` option.
|
More options are available by running with the `-h` option.
|
||||||
|
|
||||||
@@ -102,68 +100,3 @@ freqtrade backtesting-analysis -c <config.json> --analysis-groups 0 2 --enter-re
|
|||||||
The indicators have to be present in your strategy's main DataFrame (either for your main
|
The indicators have to be present in your strategy's main DataFrame (either for your main
|
||||||
timeframe or for informative timeframes) otherwise they will simply be ignored in the script
|
timeframe or for informative timeframes) otherwise they will simply be ignored in the script
|
||||||
output.
|
output.
|
||||||
|
|
||||||
There are a range of candle and trade-related fields that are included in the analysis so are
|
|
||||||
automatically accessible by including them on the indicator-list, and these include:
|
|
||||||
|
|
||||||
- **open_date :** trade open datetime
|
|
||||||
- **close_date :** trade close datetime
|
|
||||||
- **min_rate :** minimum price seen throughout the position
|
|
||||||
- **max_rate :** maximum price seen throughout the position
|
|
||||||
- **open :** signal candle open price
|
|
||||||
- **close :** signal candle close price
|
|
||||||
- **high :** signal candle high price
|
|
||||||
- **low :** signal candle low price
|
|
||||||
- **volume :** signal candle volume
|
|
||||||
- **profit_ratio :** trade profit ratio
|
|
||||||
- **profit_abs :** absolute profit return of the trade
|
|
||||||
|
|
||||||
|
|
||||||
### Filtering the trade output by date
|
|
||||||
|
|
||||||
To show only trades between dates within your backtested timerange, supply the usual `timerange` option in `YYYYMMDD-[YYYYMMDD]` format:
|
|
||||||
|
|
||||||
```
|
|
||||||
--timerange : Timerange to filter output trades, start date inclusive, end date exclusive. e.g. 20220101-20221231
|
|
||||||
```
|
|
||||||
|
|
||||||
For example, if your backtest timerange was `20220101-20221231` but you only want to output trades in January:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
freqtrade backtesting-analysis -c <config.json> --timerange 20220101-20220201
|
|
||||||
```
|
|
||||||
|
|
||||||
### Printing out rejected signals
|
|
||||||
|
|
||||||
Use the `--rejected-signals` option to print out rejected signals.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
freqtrade backtesting-analysis -c <config.json> --rejected-signals
|
|
||||||
```
|
|
||||||
|
|
||||||
### Writing tables to CSV
|
|
||||||
|
|
||||||
Some of the tabular outputs can become large, so printing them out to the terminal is not preferable.
|
|
||||||
Use the `--analysis-to-csv` option to disable printing out of tables to standard out and write them to CSV files.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
freqtrade backtesting-analysis -c <config.json> --analysis-to-csv
|
|
||||||
```
|
|
||||||
|
|
||||||
By default this will write one file per output table you specified in the `backtesting-analysis` command, e.g.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
freqtrade backtesting-analysis -c <config.json> --analysis-to-csv --rejected-signals --analysis-groups 0 1
|
|
||||||
```
|
|
||||||
|
|
||||||
This will write to `user_data/backtest_results`:
|
|
||||||
|
|
||||||
* rejected_signals.csv
|
|
||||||
* group_0.csv
|
|
||||||
* group_1.csv
|
|
||||||
|
|
||||||
To override where the files will be written, also specify the `--analysis-csv-path` option.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
freqtrade backtesting-analysis -c <config.json> --analysis-to-csv --analysis-csv-path another/data/path/
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ from typing import Any, Dict
|
|||||||
|
|
||||||
from pandas import DataFrame
|
from pandas import DataFrame
|
||||||
|
|
||||||
from freqtrade.constants import Config
|
|
||||||
from freqtrade.optimize.hyperopt import IHyperOptLoss
|
from freqtrade.optimize.hyperopt import IHyperOptLoss
|
||||||
|
|
||||||
TARGET_TRADES = 600
|
TARGET_TRADES = 600
|
||||||
@@ -32,7 +31,7 @@ class SuperDuperHyperOptLoss(IHyperOptLoss):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def hyperopt_loss_function(results: DataFrame, trade_count: int,
|
def hyperopt_loss_function(results: DataFrame, trade_count: int,
|
||||||
min_date: datetime, max_date: datetime,
|
min_date: datetime, max_date: datetime,
|
||||||
config: Config, processed: Dict[str, DataFrame],
|
config: Dict, processed: Dict[str, DataFrame],
|
||||||
backtest_stats: Dict[str, Any],
|
backtest_stats: Dict[str, Any],
|
||||||
*args, **kwargs) -> float:
|
*args, **kwargs) -> float:
|
||||||
"""
|
"""
|
||||||
@@ -75,11 +74,9 @@ This function needs to return a floating point number (`float`). Smaller numbers
|
|||||||
|
|
||||||
## Overriding pre-defined spaces
|
## Overriding pre-defined spaces
|
||||||
|
|
||||||
To override a pre-defined space (`roi_space`, `generate_roi_table`, `stoploss_space`, `trailing_space`, `max_open_trades_space`), define a nested class called Hyperopt and define the required spaces as follows:
|
To override a pre-defined space (`roi_space`, `generate_roi_table`, `stoploss_space`, `trailing_space`), define a nested class called Hyperopt and define the required spaces as follows:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from freqtrade.optimize.space import Categorical, Dimension, Integer, SKDecimal
|
|
||||||
|
|
||||||
class MyAwesomeStrategy(IStrategy):
|
class MyAwesomeStrategy(IStrategy):
|
||||||
class HyperOpt:
|
class HyperOpt:
|
||||||
# Define a custom stoploss space.
|
# Define a custom stoploss space.
|
||||||
@@ -96,39 +93,6 @@ class MyAwesomeStrategy(IStrategy):
|
|||||||
SKDecimal(0.01, 0.07, decimals=3, name='roi_p2'),
|
SKDecimal(0.01, 0.07, decimals=3, name='roi_p2'),
|
||||||
SKDecimal(0.01, 0.20, decimals=3, name='roi_p3'),
|
SKDecimal(0.01, 0.20, decimals=3, name='roi_p3'),
|
||||||
]
|
]
|
||||||
|
|
||||||
def generate_roi_table(params: Dict) -> Dict[int, float]:
|
|
||||||
|
|
||||||
roi_table = {}
|
|
||||||
roi_table[0] = params['roi_p1'] + params['roi_p2'] + params['roi_p3']
|
|
||||||
roi_table[params['roi_t3']] = params['roi_p1'] + params['roi_p2']
|
|
||||||
roi_table[params['roi_t3'] + params['roi_t2']] = params['roi_p1']
|
|
||||||
roi_table[params['roi_t3'] + params['roi_t2'] + params['roi_t1']] = 0
|
|
||||||
|
|
||||||
return roi_table
|
|
||||||
|
|
||||||
def trailing_space() -> List[Dimension]:
|
|
||||||
# All parameters here are mandatory, you can only modify their type or the range.
|
|
||||||
return [
|
|
||||||
# Fixed to true, if optimizing trailing_stop we assume to use trailing stop at all times.
|
|
||||||
Categorical([True], name='trailing_stop'),
|
|
||||||
|
|
||||||
SKDecimal(0.01, 0.35, decimals=3, name='trailing_stop_positive'),
|
|
||||||
# 'trailing_stop_positive_offset' should be greater than 'trailing_stop_positive',
|
|
||||||
# so this intermediate parameter is used as the value of the difference between
|
|
||||||
# them. The value of the 'trailing_stop_positive_offset' is constructed in the
|
|
||||||
# generate_trailing_params() method.
|
|
||||||
# This is similar to the hyperspace dimensions used for constructing the ROI tables.
|
|
||||||
SKDecimal(0.001, 0.1, decimals=3, name='trailing_stop_positive_offset_p1'),
|
|
||||||
|
|
||||||
Categorical([True, False], name='trailing_only_offset_is_reached'),
|
|
||||||
]
|
|
||||||
|
|
||||||
# Define a custom max_open_trades space
|
|
||||||
def max_open_trades_space(self) -> List[Dimension]:
|
|
||||||
return [
|
|
||||||
Integer(-1, 10, name='max_open_trades'),
|
|
||||||
]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! Note
|
!!! Note
|
||||||
@@ -136,7 +100,7 @@ class MyAwesomeStrategy(IStrategy):
|
|||||||
|
|
||||||
### Dynamic parameters
|
### Dynamic parameters
|
||||||
|
|
||||||
Parameters can also be defined dynamically, but must be available to the instance once the [`bot_start()` callback](strategy-callbacks.md#bot-start) has been called.
|
Parameters can also be defined dynamically, but must be available to the instance once the * [`bot_start()` callback](strategy-callbacks.md#bot-start) has been called.
|
||||||
|
|
||||||
``` python
|
``` python
|
||||||
|
|
||||||
|
|||||||
@@ -1,152 +0,0 @@
|
|||||||
# Orderflow data
|
|
||||||
|
|
||||||
This guide walks you through utilizing public trade data for advanced orderflow analysis in Freqtrade.
|
|
||||||
|
|
||||||
!!! Warning "Experimental Feature"
|
|
||||||
The orderflow feature is currently in beta and may be subject to changes in future releases. Please report any issues or feedback on the [Freqtrade GitHub repository](https://github.com/freqtrade/freqtrade/issues).
|
|
||||||
|
|
||||||
!!! Warning "Performance"
|
|
||||||
Orderflow requires raw trades data. This data is rather large, and can cause a slow initial startup, when freqtrade needs to download the trades data for the last X candles. Additionally, enabling this feature will cause increased memory usage. Please ensure to have sufficient resources available.
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
### Enable Public Trades
|
|
||||||
|
|
||||||
In your `config.json` file, set the `use_public_trades` option to true under the `exchange` section.
|
|
||||||
|
|
||||||
```json
|
|
||||||
"exchange": {
|
|
||||||
...
|
|
||||||
"use_public_trades": true,
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Configure Orderflow Processing
|
|
||||||
|
|
||||||
Define your desired settings for orderflow processing within the orderflow section of config.json. Here, you can adjust factors like:
|
|
||||||
|
|
||||||
- `cache_size`: How many previous orderflow candles are saved into cache instead of calculated every new candle
|
|
||||||
- `max_candles`: Filter how many candles would you like to get trades data for.
|
|
||||||
- `scale`: This controls the price bin size for the footprint chart.
|
|
||||||
- `stacked_imbalance_range`: Defines the minimum consecutive imbalanced price levels required for consideration.
|
|
||||||
- `imbalance_volume`: Filters out imbalances with volume below this threshold.
|
|
||||||
- `imbalance_ratio`: Filters out imbalances with a ratio (difference between ask and bid volume) lower than this value.
|
|
||||||
|
|
||||||
```json
|
|
||||||
"orderflow": {
|
|
||||||
"cache_size": 1000,
|
|
||||||
"max_candles": 1500,
|
|
||||||
"scale": 0.5,
|
|
||||||
"stacked_imbalance_range": 3, // needs at least this amount of imbalance next to each other
|
|
||||||
"imbalance_volume": 1, // filters out below
|
|
||||||
"imbalance_ratio": 3 // filters out ratio lower than
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|
||||||
## Downloading Trade Data for Backtesting
|
|
||||||
|
|
||||||
To download historical trade data for backtesting, use the --dl-trades flag with the freqtrade download-data command.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
freqtrade download-data -p BTC/USDT:USDT --timerange 20230101- --trading-mode futures --timeframes 5m --dl-trades
|
|
||||||
```
|
|
||||||
|
|
||||||
!!! Warning "Data availability"
|
|
||||||
Not all exchanges provide public trade data. For supported exchanges, freqtrade will warn you if public trade data is not available if you start downloading data with the `--dl-trades` flag.
|
|
||||||
|
|
||||||
## Accessing Orderflow Data
|
|
||||||
|
|
||||||
Once activated, several new columns become available in your dataframe:
|
|
||||||
|
|
||||||
``` python
|
|
||||||
|
|
||||||
dataframe["trades"] # Contains information about each individual trade.
|
|
||||||
dataframe["orderflow"] # Represents a footprint chart dict (see below)
|
|
||||||
dataframe["imbalances"] # Contains information about imbalances in the order flow.
|
|
||||||
dataframe["bid"] # Total bid volume
|
|
||||||
dataframe["ask"] # Total ask volume
|
|
||||||
dataframe["delta"] # Difference between ask and bid volume.
|
|
||||||
dataframe["min_delta"] # Minimum delta within the candle
|
|
||||||
dataframe["max_delta"] # Maximum delta within the candle
|
|
||||||
dataframe["total_trades"] # Total number of trades
|
|
||||||
dataframe["stacked_imbalances_bid"] # Price level of stacked bid imbalance
|
|
||||||
dataframe["stacked_imbalances_ask"] # Price level of stacked ask imbalance
|
|
||||||
```
|
|
||||||
|
|
||||||
You can access these columns in your strategy code for further analysis. Here's an example:
|
|
||||||
|
|
||||||
``` python
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
# Calculating cumulative delta
|
|
||||||
dataframe["cum_delta"] = cumulative_delta(dataframe["delta"])
|
|
||||||
# Accessing total trades
|
|
||||||
total_trades = dataframe["total_trades"]
|
|
||||||
...
|
|
||||||
|
|
||||||
def cumulative_delta(delta: Series):
|
|
||||||
cumdelta = delta.cumsum()
|
|
||||||
return cumdelta
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
### Footprint chart (`dataframe["orderflow"]`)
|
|
||||||
|
|
||||||
This column provides a detailed breakdown of buy and sell orders at different price levels, offering valuable insights into order flow dynamics. The `scale` parameter in your configuration determines the price bin size for this representation
|
|
||||||
|
|
||||||
The `orderflow` column contains a dict with the following structure:
|
|
||||||
|
|
||||||
``` output
|
|
||||||
{
|
|
||||||
"price": {
|
|
||||||
"bid_amount": 0.0,
|
|
||||||
"ask_amount": 0.0,
|
|
||||||
"bid": 0,
|
|
||||||
"ask": 0,
|
|
||||||
"delta": 0.0,
|
|
||||||
"total_volume": 0.0,
|
|
||||||
"total_trades": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Orderflow column explanation
|
|
||||||
|
|
||||||
- key: Price bin - binned at `scale` intervals
|
|
||||||
- `bid_amount`: Total volume bought at each price level.
|
|
||||||
- `ask_amount`: Total volume sold at each price level.
|
|
||||||
- `bid`: Number of buy orders at each price level.
|
|
||||||
- `ask`: Number of sell orders at each price level.
|
|
||||||
- `delta`: Difference between ask and bid volume at each price level.
|
|
||||||
- `total_volume`: Total volume (ask amount + bid amount) at each price level.
|
|
||||||
- `total_trades`: Total number of trades (ask + bid) at each price level.
|
|
||||||
|
|
||||||
By leveraging these features, you can gain valuable insights into market sentiment and potential trading opportunities based on order flow analysis.
|
|
||||||
|
|
||||||
### Raw trades data (`dataframe["trades"]`)
|
|
||||||
|
|
||||||
List with the individual trades that occurred during the candle. This data can be used for more granular analysis of order flow dynamics.
|
|
||||||
|
|
||||||
Each individual entry contains a dict with the following keys:
|
|
||||||
|
|
||||||
- `timestamp`: Timestamp of the trade.
|
|
||||||
- `date`: Date of the trade.
|
|
||||||
- `price`: Price of the trade.
|
|
||||||
- `amount`: Volume of the trade.
|
|
||||||
- `side`: Buy or sell.
|
|
||||||
- `id`: Unique identifier for the trade.
|
|
||||||
- `cost`: Total cost of the trade (price * amount).
|
|
||||||
|
|
||||||
### Imbalances (`dataframe["imbalances"]`)
|
|
||||||
|
|
||||||
This column provides a dict with information about imbalances in the order flow. An imbalance occurs when there is a significant difference between the ask and bid volume at a given price level.
|
|
||||||
|
|
||||||
Each row looks as follows - with price as index, and the corresponding bid and ask imbalance values as columns
|
|
||||||
|
|
||||||
``` output
|
|
||||||
{
|
|
||||||
"price": {
|
|
||||||
"bid_imbalance": False,
|
|
||||||
"ask_imbalance": False
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
@@ -114,46 +114,8 @@ services:
|
|||||||
--strategy SampleStrategy
|
--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.
|
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.
|
||||||
|
|
||||||
## 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. The freqtrade team will not provide any support with setup or maintenance (or backups) of the below database systems.
|
|
||||||
|
|
||||||
### PostgreSQL
|
|
||||||
|
|
||||||
Installation:
|
|
||||||
`pip install psycopg2-binary`
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
`... --db-url postgresql+psycopg2://<username>:<password>@localhost:5432/<database>`
|
|
||||||
|
|
||||||
Freqtrade will automatically create the tables necessary upon startup.
|
|
||||||
|
|
||||||
If you're running different instances of Freqtrade, you must either setup one database per Instance or use different users / schemas for your connections.
|
|
||||||
|
|
||||||
### MariaDB / MySQL
|
|
||||||
|
|
||||||
Freqtrade supports MariaDB by using SQLAlchemy, which supports multiple different database systems.
|
|
||||||
|
|
||||||
Installation:
|
|
||||||
`pip install pymysql`
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
`... --db-url mysql+pymysql://<username>:<password>@localhost:3306/<database>`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Configure the bot running as a systemd service
|
## Configure the bot running as a systemd service
|
||||||
|
|
||||||
@@ -230,7 +192,7 @@ $RepeatedMsgReduction on
|
|||||||
|
|
||||||
### Logging to journald
|
### Logging to journald
|
||||||
|
|
||||||
This needs the `cysystemd` python package installed as dependency (`pip install cysystemd`), which is not available on Windows. Hence, the whole journald logging functionality is not available for a bot running on Windows.
|
This needs the `systemd` python package installed as the dependency, which is not available on Windows. Hence, the whole journald logging functionality is not available for a bot running on Windows.
|
||||||
|
|
||||||
To send Freqtrade log messages to `journald` system service use the `--logfile` command line option with the value in the following format:
|
To send Freqtrade log messages to `journald` system service use the `--logfile` command line option with the value in the following format:
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 242 KiB |
|
Before Width: | Height: | Size: 241 KiB |
|
Before Width: | Height: | Size: 209 KiB |
|
Before Width: | Height: | Size: 307 KiB |
|
Before Width: | Height: | Size: 345 KiB |
BIN
docs/assets/freqai_algo.png
Normal file
|
After Width: | Height: | Size: 995 KiB |
|
Before Width: | Height: | Size: 490 KiB |
|
Before Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 458 KiB |
|
Before Width: | Height: | Size: 270 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 185 KiB |
|
Before Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 362 KiB |
BIN
docs/assets/weights_factor.png
Normal file
|
After Width: | Height: | Size: 126 KiB |
@@ -31,9 +31,9 @@ optional arguments:
|
|||||||
Specify timeframe (`1m`, `5m`, `30m`, `1h`, `1d`).
|
Specify timeframe (`1m`, `5m`, `30m`, `1h`, `1d`).
|
||||||
--timerange TIMERANGE
|
--timerange TIMERANGE
|
||||||
Specify what timerange of data to use.
|
Specify what timerange of data to use.
|
||||||
--data-format-ohlcv {json,jsongz,hdf5,feather,parquet}
|
--data-format-ohlcv {json,jsongz,hdf5}
|
||||||
Storage format for downloaded candle (OHLCV) data.
|
Storage format for downloaded candle (OHLCV) data.
|
||||||
(default: `feather`).
|
(default: `json`).
|
||||||
--max-open-trades INT
|
--max-open-trades INT
|
||||||
Override the value of the `max_open_trades`
|
Override the value of the `max_open_trades`
|
||||||
configuration setting.
|
configuration setting.
|
||||||
@@ -107,7 +107,7 @@ Strategy arguments:
|
|||||||
|
|
||||||
## Test your strategy with Backtesting
|
## Test your strategy with Backtesting
|
||||||
|
|
||||||
Now you have good Entry and exit strategies and some historic data, you want to test it against
|
Now you have good Buy and Sell strategies and some historic data, you want to test it against
|
||||||
real data. This is what we call [backtesting](https://en.wikipedia.org/wiki/Backtesting).
|
real data. This is what we call [backtesting](https://en.wikipedia.org/wiki/Backtesting).
|
||||||
|
|
||||||
Backtesting will use the crypto-currencies (pairs) from your config file and load historical candle (OHLCV) data from `user_data/data/<exchange>` by default.
|
Backtesting will use the crypto-currencies (pairs) from your config file and load historical candle (OHLCV) data from `user_data/data/<exchange>` by default.
|
||||||
@@ -170,11 +170,11 @@ freqtrade backtesting --strategy AwesomeStrategy --dry-run-wallet 1000
|
|||||||
|
|
||||||
Using a different on-disk historical candle (OHLCV) data source
|
Using a different on-disk historical candle (OHLCV) data source
|
||||||
|
|
||||||
Assume you downloaded the history data from the Binance exchange and kept it in the `user_data/data/binance-20180101` directory.
|
Assume you downloaded the history data from the Bittrex exchange and kept it in the `user_data/data/bittrex-20180101` directory.
|
||||||
You can then use this data for backtesting as follows:
|
You can then use this data for backtesting as follows:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
freqtrade backtesting --strategy AwesomeStrategy --datadir user_data/data/binance-20180101
|
freqtrade backtesting --strategy AwesomeStrategy --datadir user_data/data/bittrex-20180101
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -215,7 +215,7 @@ Sometimes your account has certain fee rebates (fee reductions starting with a c
|
|||||||
To account for this in backtesting, you can use the `--fee` command line option to supply this value to backtesting.
|
To account for this in backtesting, you can use the `--fee` command line option to supply this value to backtesting.
|
||||||
This fee must be a ratio, and will be applied twice (once for trade entry, and once for trade exit).
|
This fee must be a ratio, and will be applied twice (once for trade entry, and once for trade exit).
|
||||||
|
|
||||||
For example, if the commission fee per order is 0.1% (i.e., 0.001 written as ratio), then you would run backtesting as the following:
|
For example, if the buying and selling commission fee is 0.1% (i.e., 0.001 written as ratio), then you would run backtesting as the following:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
freqtrade backtesting --fee 0.001
|
freqtrade backtesting --fee 0.001
|
||||||
@@ -252,42 +252,41 @@ The most important in the backtesting is to understand the result.
|
|||||||
A backtesting result will look like that:
|
A backtesting result will look like that:
|
||||||
|
|
||||||
```
|
```
|
||||||
================================================ BACKTESTING REPORT =================================================
|
========================================================= BACKTESTING REPORT ==========================================================
|
||||||
| Pair | Trades | Avg Profit % | Tot Profit BTC | Tot Profit % | Avg Duration | Wins Draws Loss Win% |
|
| Pair | Buys | Avg Profit % | Cum Profit % | Tot Profit BTC | Tot Profit % | Avg Duration | Wins Draws Loss Win% |
|
||||||
|----------+--------+----------------+------------------+----------------+--------------+--------------------------|
|
|:---------|-------:|---------------:|---------------:|-----------------:|---------------:|:-------------|-------------------------:|
|
||||||
| ADA/BTC | 35 | -0.11 | -0.00019428 | -1.94 | 4:35:00 | 14 0 21 40.0 |
|
| ADA/BTC | 35 | -0.11 | -3.88 | -0.00019428 | -1.94 | 4:35:00 | 14 0 21 40.0 |
|
||||||
| ARK/BTC | 11 | -0.41 | -0.00022647 | -2.26 | 2:03:00 | 3 0 8 27.3 |
|
| ARK/BTC | 11 | -0.41 | -4.52 | -0.00022647 | -2.26 | 2:03:00 | 3 0 8 27.3 |
|
||||||
| BTS/BTC | 32 | 0.31 | 0.00048938 | 4.89 | 5:05:00 | 18 0 14 56.2 |
|
| BTS/BTC | 32 | 0.31 | 9.78 | 0.00048938 | 4.89 | 5:05:00 | 18 0 14 56.2 |
|
||||||
| DASH/BTC | 13 | -0.08 | -0.00005343 | -0.53 | 4:39:00 | 6 0 7 46.2 |
|
| DASH/BTC | 13 | -0.08 | -1.07 | -0.00005343 | -0.53 | 4:39:00 | 6 0 7 46.2 |
|
||||||
| ENG/BTC | 18 | 1.36 | 0.00122807 | 12.27 | 2:50:00 | 8 0 10 44.4 |
|
| ENG/BTC | 18 | 1.36 | 24.54 | 0.00122807 | 12.27 | 2:50:00 | 8 0 10 44.4 |
|
||||||
| EOS/BTC | 36 | 0.08 | 0.00015304 | 1.53 | 3:34:00 | 16 0 20 44.4 |
|
| EOS/BTC | 36 | 0.08 | 3.06 | 0.00015304 | 1.53 | 3:34:00 | 16 0 20 44.4 |
|
||||||
| ETC/BTC | 26 | 0.37 | 0.00047576 | 4.75 | 6:14:00 | 11 0 15 42.3 |
|
| ETC/BTC | 26 | 0.37 | 9.51 | 0.00047576 | 4.75 | 6:14:00 | 11 0 15 42.3 |
|
||||||
| ETH/BTC | 33 | 0.30 | 0.00049856 | 4.98 | 7:31:00 | 16 0 17 48.5 |
|
| ETH/BTC | 33 | 0.30 | 9.96 | 0.00049856 | 4.98 | 7:31:00 | 16 0 17 48.5 |
|
||||||
| IOTA/BTC | 32 | 0.03 | 0.00005444 | 0.54 | 3:12:00 | 14 0 18 43.8 |
|
| IOTA/BTC | 32 | 0.03 | 1.09 | 0.00005444 | 0.54 | 3:12:00 | 14 0 18 43.8 |
|
||||||
| LSK/BTC | 15 | 1.75 | 0.00131413 | 13.13 | 2:58:00 | 6 0 9 40.0 |
|
| LSK/BTC | 15 | 1.75 | 26.26 | 0.00131413 | 13.13 | 2:58:00 | 6 0 9 40.0 |
|
||||||
| LTC/BTC | 32 | -0.04 | -0.00006886 | -0.69 | 4:49:00 | 11 0 21 34.4 |
|
| LTC/BTC | 32 | -0.04 | -1.38 | -0.00006886 | -0.69 | 4:49:00 | 11 0 21 34.4 |
|
||||||
| NANO/BTC | 17 | 1.26 | 0.00107058 | 10.70 | 1:55:00 | 10 0 7 58.5 |
|
| NANO/BTC | 17 | 1.26 | 21.39 | 0.00107058 | 10.70 | 1:55:00 | 10 0 7 58.5 |
|
||||||
| NEO/BTC | 23 | 0.82 | 0.00094936 | 9.48 | 2:59:00 | 10 0 13 43.5 |
|
| NEO/BTC | 23 | 0.82 | 18.97 | 0.00094936 | 9.48 | 2:59:00 | 10 0 13 43.5 |
|
||||||
| REQ/BTC | 9 | 1.17 | 0.00052734 | 5.27 | 3:47:00 | 4 0 5 44.4 |
|
| REQ/BTC | 9 | 1.17 | 10.54 | 0.00052734 | 5.27 | 3:47:00 | 4 0 5 44.4 |
|
||||||
| XLM/BTC | 16 | 1.22 | 0.00097800 | 9.77 | 3:15:00 | 7 0 9 43.8 |
|
| XLM/BTC | 16 | 1.22 | 19.54 | 0.00097800 | 9.77 | 3:15:00 | 7 0 9 43.8 |
|
||||||
| XMR/BTC | 23 | -0.18 | -0.00020696 | -2.07 | 5:30:00 | 12 0 11 52.2 |
|
| XMR/BTC | 23 | -0.18 | -4.13 | -0.00020696 | -2.07 | 5:30:00 | 12 0 11 52.2 |
|
||||||
| XRP/BTC | 35 | 0.66 | 0.00114897 | 11.48 | 3:49:00 | 12 0 23 34.3 |
|
| XRP/BTC | 35 | 0.66 | 22.96 | 0.00114897 | 11.48 | 3:49:00 | 12 0 23 34.3 |
|
||||||
| ZEC/BTC | 22 | -0.46 | -0.00050971 | -5.09 | 2:22:00 | 7 0 15 31.8 |
|
| ZEC/BTC | 22 | -0.46 | -10.18 | -0.00050971 | -5.09 | 2:22:00 | 7 0 15 31.8 |
|
||||||
| TOTAL | 429 | 0.36 | 0.00762792 | 76.20 | 4:12:00 | 186 0 243 43.4 |
|
| TOTAL | 429 | 0.36 | 152.41 | 0.00762792 | 76.20 | 4:12:00 | 186 0 243 43.4 |
|
||||||
============================================= LEFT OPEN TRADES REPORT =============================================
|
========================================================= EXIT REASON STATS ==========================================================
|
||||||
| Pair | Trades | Avg Profit % | Tot Profit BTC | Tot Profit % | Avg Duration | Win Draw Loss Win% |
|
| Exit Reason | Sells | Wins | Draws | Losses |
|
||||||
|----------+---------+----------------+------------------+----------------+----------------+---------------------|
|
|:-------------------|--------:|------:|-------:|--------:|
|
||||||
| ADA/BTC | 1 | 0.89 | 0.00004434 | 0.44 | 6:00:00 | 1 0 0 100 |
|
|
||||||
| LTC/BTC | 1 | 0.68 | 0.00003421 | 0.34 | 2:00:00 | 1 0 0 100 |
|
|
||||||
| TOTAL | 2 | 0.78 | 0.00007855 | 0.78 | 4:00:00 | 2 0 0 100 |
|
|
||||||
==================== EXIT REASON STATS ====================
|
|
||||||
| Exit Reason | Exits | Wins | Draws | Losses |
|
|
||||||
|--------------------+---------+-------+--------+---------|
|
|
||||||
| trailing_stop_loss | 205 | 150 | 0 | 55 |
|
| trailing_stop_loss | 205 | 150 | 0 | 55 |
|
||||||
| stop_loss | 166 | 0 | 0 | 166 |
|
| stop_loss | 166 | 0 | 0 | 166 |
|
||||||
| exit_signal | 56 | 36 | 0 | 20 |
|
| exit_signal | 56 | 36 | 0 | 20 |
|
||||||
| force_exit | 2 | 0 | 0 | 2 |
|
| force_exit | 2 | 0 | 0 | 2 |
|
||||||
|
====================================================== LEFT OPEN TRADES REPORT ======================================================
|
||||||
|
| Pair | Buys | Avg Profit % | Cum Profit % | Tot Profit BTC | Tot Profit % | Avg Duration | Win Draw Loss Win% |
|
||||||
|
|:---------|-------:|---------------:|---------------:|-----------------:|---------------:|:---------------|--------------------:|
|
||||||
|
| ADA/BTC | 1 | 0.89 | 0.89 | 0.00004434 | 0.44 | 6:00:00 | 1 0 0 100 |
|
||||||
|
| LTC/BTC | 1 | 0.68 | 0.68 | 0.00003421 | 0.34 | 2:00:00 | 1 0 0 100 |
|
||||||
|
| TOTAL | 2 | 0.78 | 1.57 | 0.00007855 | 0.78 | 4:00:00 | 2 0 0 100 |
|
||||||
================== SUMMARY METRICS ==================
|
================== SUMMARY METRICS ==================
|
||||||
| Metric | Value |
|
| Metric | Value |
|
||||||
|-----------------------------+---------------------|
|
|-----------------------------+---------------------|
|
||||||
@@ -301,11 +300,7 @@ A backtesting result will look like that:
|
|||||||
| Absolute profit | 0.00762792 BTC |
|
| Absolute profit | 0.00762792 BTC |
|
||||||
| Total profit % | 76.2% |
|
| Total profit % | 76.2% |
|
||||||
| CAGR % | 460.87% |
|
| CAGR % | 460.87% |
|
||||||
| Sortino | 1.88 |
|
|
||||||
| Sharpe | 2.97 |
|
|
||||||
| Calmar | 6.29 |
|
|
||||||
| Profit factor | 1.11 |
|
| Profit factor | 1.11 |
|
||||||
| Expectancy (Ratio) | -0.15 (-0.05) |
|
|
||||||
| Avg. stake amount | 0.001 BTC |
|
| Avg. stake amount | 0.001 BTC |
|
||||||
| Total trade volume | 0.429 BTC |
|
| Total trade volume | 0.429 BTC |
|
||||||
| | |
|
| | |
|
||||||
@@ -324,7 +319,6 @@ A backtesting result will look like that:
|
|||||||
| Days win/draw/lose | 12 / 82 / 25 |
|
| Days win/draw/lose | 12 / 82 / 25 |
|
||||||
| Avg. Duration Winners | 4:23:00 |
|
| Avg. Duration Winners | 4:23:00 |
|
||||||
| Avg. Duration Loser | 6:55:00 |
|
| Avg. Duration Loser | 6:55:00 |
|
||||||
| Max Consecutive Wins / Loss | 3 / 4 |
|
|
||||||
| Rejected Entry signals | 3089 |
|
| Rejected Entry signals | 3089 |
|
||||||
| Entry/Exit Timeouts | 0 / 0 |
|
| Entry/Exit Timeouts | 0 / 0 |
|
||||||
| Canceled Trade Entries | 34 |
|
| Canceled Trade Entries | 34 |
|
||||||
@@ -358,11 +352,11 @@ here:
|
|||||||
The bot has made `429` trades for an average duration of `4:12:00`, with a performance of `76.20%` (profit), that means it has
|
The bot has made `429` trades for an average duration of `4:12:00`, with a performance of `76.20%` (profit), that means it has
|
||||||
earned a total of `0.00762792 BTC` starting with a capital of 0.01 BTC.
|
earned a total of `0.00762792 BTC` starting with a capital of 0.01 BTC.
|
||||||
|
|
||||||
The column `Avg Profit %` shows the average profit for all trades made.
|
The column `Avg Profit %` shows the average profit for all trades made while the column `Cum Profit %` sums up all the profits/losses.
|
||||||
The column `Tot Profit %` shows instead the total profit % in relation to the starting balance.
|
The column `Tot Profit %` shows instead the total profit % in relation to the starting balance.
|
||||||
In the above results, we have a starting balance of 0.01 BTC and an absolute profit of 0.00762792 BTC - so the `Tot Profit %` will be `(0.00762792 / 0.01) * 100 ~= 76.2%`.
|
In the above results, we have a starting balance of 0.01 BTC and an absolute profit of 0.00762792 BTC - so the `Tot Profit %` will be `(0.00762792 / 0.01) * 100 ~= 76.2%`.
|
||||||
|
|
||||||
Your strategy performance is influenced by your entry strategy, your exit strategy, and also by the `minimal_roi` and `stop_loss` you have set.
|
Your strategy performance is influenced by your buy strategy, your exit strategy, and also by the `minimal_roi` and `stop_loss` you have set.
|
||||||
|
|
||||||
For example, if your `minimal_roi` is only `"0": 0.01` you cannot expect the bot to make more profit than 1% (because it will exit every time a trade reaches 1%).
|
For example, if your `minimal_roi` is only `"0": 0.01` you cannot expect the bot to make more profit than 1% (because it will exit every time a trade reaches 1%).
|
||||||
|
|
||||||
@@ -406,11 +400,7 @@ It contains some useful key metrics about performance of your strategy on backte
|
|||||||
| Absolute profit | 0.00762792 BTC |
|
| Absolute profit | 0.00762792 BTC |
|
||||||
| Total profit % | 76.2% |
|
| Total profit % | 76.2% |
|
||||||
| CAGR % | 460.87% |
|
| CAGR % | 460.87% |
|
||||||
| Sortino | 1.88 |
|
|
||||||
| Sharpe | 2.97 |
|
|
||||||
| Calmar | 6.29 |
|
|
||||||
| Profit factor | 1.11 |
|
| Profit factor | 1.11 |
|
||||||
| Expectancy (Ratio) | -0.15 (-0.05) |
|
|
||||||
| Avg. stake amount | 0.001 BTC |
|
| Avg. stake amount | 0.001 BTC |
|
||||||
| Total trade volume | 0.429 BTC |
|
| Total trade volume | 0.429 BTC |
|
||||||
| | |
|
| | |
|
||||||
@@ -429,7 +419,6 @@ It contains some useful key metrics about performance of your strategy on backte
|
|||||||
| Days win/draw/lose | 12 / 82 / 25 |
|
| Days win/draw/lose | 12 / 82 / 25 |
|
||||||
| Avg. Duration Winners | 4:23:00 |
|
| Avg. Duration Winners | 4:23:00 |
|
||||||
| Avg. Duration Loser | 6:55:00 |
|
| Avg. Duration Loser | 6:55:00 |
|
||||||
| Max Consecutive Wins / Loss | 3 / 4 |
|
|
||||||
| Rejected Entry signals | 3089 |
|
| Rejected Entry signals | 3089 |
|
||||||
| Entry/Exit Timeouts | 0 / 0 |
|
| Entry/Exit Timeouts | 0 / 0 |
|
||||||
| Canceled Trade Entries | 34 |
|
| Canceled Trade Entries | 34 |
|
||||||
@@ -458,18 +447,14 @@ It contains some useful key metrics about performance of your strategy on backte
|
|||||||
- `Absolute profit`: Profit made in stake currency.
|
- `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`.
|
- `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.
|
- `CAGR %`: Compound annual growth rate.
|
||||||
- `Sortino`: Annualized Sortino ratio.
|
|
||||||
- `Sharpe`: Annualized Sharpe ratio.
|
|
||||||
- `Calmar`: Annualized Calmar ratio.
|
|
||||||
- `Profit factor`: profit / loss.
|
- `Profit factor`: profit / loss.
|
||||||
- `Avg. stake amount`: Average stake amount, either `stake_amount` or the average when using dynamic stake amount.
|
- `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.
|
- `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 `Tot Profit %`.
|
- `Best Pair` / `Worst Pair`: Best and worst performing pair, and it's corresponding `Cum Profit %`.
|
||||||
- `Best Trade` / `Worst Trade`: Biggest single winning trade and biggest single losing trade.
|
- `Best Trade` / `Worst Trade`: Biggest single winning trade and biggest single losing trade.
|
||||||
- `Best day` / `Worst day`: Best and worst day based on daily profit.
|
- `Best day` / `Worst day`: Best and worst day based on daily profit.
|
||||||
- `Days win/draw/lose`: Winning / Losing days (draws are usually days without closed trade).
|
- `Days win/draw/lose`: Winning / Losing days (draws are usually days without closed trade).
|
||||||
- `Avg. Duration Winners` / `Avg. Duration Loser`: Average durations for winning and losing trades.
|
- `Avg. Duration Winners` / `Avg. Duration Loser`: Average durations for winning and losing trades.
|
||||||
- `Max Consecutive Wins / Loss`: Maximum consecutive wins/losses in a row.
|
|
||||||
- `Rejected Entry signals`: Trade entry signals that could not be acted upon due to `max_open_trades` being reached.
|
- `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).
|
- `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 Trade Entries`: Number of trades that have been canceled by user request via `adjust_entry_price`.
|
||||||
@@ -522,30 +507,28 @@ To save time, by default backtest will reuse a cached result from within the las
|
|||||||
|
|
||||||
### Further backtest-result analysis
|
### Further backtest-result analysis
|
||||||
|
|
||||||
To further analyze your backtest results, freqtrade will export the trades to file by default.
|
To further analyze your backtest results, you can [export the trades](#exporting-trades-to-file).
|
||||||
You can then load the trades to perform further analysis as shown in the [data analysis](strategy_analysis_example.md#load-backtest-results-to-pandas-dataframe) backtesting section.
|
You can then load the trades to perform further analysis as shown in the [data analysis](data-analysis.md#backtesting) backtesting section.
|
||||||
|
|
||||||
## Assumptions made by backtesting
|
## Assumptions made by backtesting
|
||||||
|
|
||||||
Since backtesting lacks some detailed information about what happens within a candle, it needs to take a few assumptions:
|
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
|
- Exchange [trading limits](#trading-limits-in-backtesting) are respected
|
||||||
- Entries happen at open-price
|
- Buys happen at open-price
|
||||||
- All orders are filled at the requested price (no slippage) as long as the price is within the candle's high/low range
|
- All orders are filled at the requested price (no slippage, no unfilled orders)
|
||||||
- Exit-signal exits happen at open-price of the consecutive candle
|
- Exit-signal exits happen at open-price of the consecutive candle
|
||||||
- Exits don't free their trade slot for a new trade until the next candle
|
|
||||||
- Exit-signal is favored over Stoploss, because exit-signals are assumed to trigger on candle's open
|
- Exit-signal is favored over Stoploss, because exit-signals are assumed to trigger on candle's open
|
||||||
- ROI
|
- ROI
|
||||||
- Exits are compared to high - but the ROI value is used (e.g. ROI = 2%, high=5% - so the exit will be at 2%)
|
- exits are compared to high - but the ROI value is used (e.g. ROI = 2%, high=5% - so the exit will be at 2%)
|
||||||
- Exits are never "below the candle", so a ROI of 2% may result in a exit at 2.4% if low was at 2.4% profit
|
- exits are never "below the candle", so a ROI of 2% may result in a exit at 2.4% if low was at 2.4% profit
|
||||||
- ROI entries which came into effect on the triggering candle (e.g. `120: 0.02` for 1h candles, from `60: 0.05`) will use the candle's open as exit rate
|
- Forceexits caused by `<N>=-1` ROI entries use low as exit value, unless N falls on the candle open (e.g. `120: -1` for 1h candles)
|
||||||
- Force-exits caused by `<N>=-1` ROI entries use low as exit value, unless N falls on the candle open (e.g. `120: -1` for 1h candles)
|
|
||||||
- Stoploss exits happen exactly at stoploss price, even if low was lower, but the loss will be `2 * fees` higher than the stoploss price
|
- Stoploss exits happen exactly at stoploss price, even if low was lower, but the loss will be `2 * fees` higher than the stoploss price
|
||||||
- Stoploss is evaluated before ROI within one candle. So you can often see more trades with the `stoploss` exit reason comparing to the results obtained with the same strategy in the Dry Run/Live Trade modes
|
- Stoploss is evaluated before ROI within one candle. So you can often see more trades with the `stoploss` exit reason comparing to the results obtained with the same strategy in the Dry Run/Live Trade modes
|
||||||
- Low happens before high for stoploss, protecting capital first
|
- Low happens before high for stoploss, protecting capital first
|
||||||
- Trailing stoploss
|
- Trailing stoploss
|
||||||
- Trailing Stoploss is only adjusted if it's below the candle's low (otherwise it would be triggered)
|
- Trailing Stoploss is only adjusted if it's below the candle's low (otherwise it would be triggered)
|
||||||
- On trade entry candles that trigger trailing stoploss, the "minimum offset" (`stop_positive_offset`) is assumed (instead of high) - and the stop is calculated from this point. This rule is NOT applicable to custom-stoploss scenarios, since there's no information about the stoploss logic available.
|
- On trade entry candles that trigger trailing stoploss, the "minimum offset" (`stop_positive_offset`) is assumed (instead of high) - and the stop is calculated from this point
|
||||||
- High happens first - adjusting stoploss
|
- High happens first - adjusting stoploss
|
||||||
- Low uses the adjusted stoploss (so exits with large high-low difference are backtested correctly)
|
- Low uses the adjusted stoploss (so exits with large high-low difference are backtested correctly)
|
||||||
- ROI applies before trailing-stop, ensuring profits are "top-capped" at ROI if both ROI and trailing stop applies
|
- ROI applies before trailing-stop, ensuring profits are "top-capped" at ROI if both ROI and trailing stop applies
|
||||||
@@ -563,8 +546,8 @@ In addition to the above assumptions, strategy authors should carefully read the
|
|||||||
|
|
||||||
### Trading limits in backtesting
|
### Trading limits in backtesting
|
||||||
|
|
||||||
Exchanges have certain trading limits, like minimum (and maximum) base currency, or minimum/maximum stake (quote) currency.
|
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 and can be quite different between different pairs.
|
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.
|
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.
|
Freqtrade has however no information about historic limits.
|
||||||
@@ -578,17 +561,9 @@ BTC trades at 22.000\$ today (0.001 BTC is related to this) - but the backtestin
|
|||||||
Today's minimum would be `0.001 * 22_000` - or 22\$.
|
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.
|
However the limit could also be 50$ - based on `0.001 * 50_000` in some historic setting.
|
||||||
|
|
||||||
#### Trading precision limits
|
|
||||||
|
|
||||||
Most exchanges pose precision limits on both price and amounts, so you cannot buy 1.0020401 of a pair, or at a price of 1.24567123123.
|
|
||||||
Instead, these prices and amounts will be rounded or truncated (based on the exchange definition) to the defined trading precision.
|
|
||||||
The above values may for example be rounded to an amount of 1.002, and a price of 1.24567.
|
|
||||||
|
|
||||||
These precision values are based on current exchange limits (as described in the [above section](#trading-limits-in-backtesting)), as historic precision limits are not available.
|
|
||||||
|
|
||||||
## Improved backtest accuracy
|
## Improved backtest accuracy
|
||||||
|
|
||||||
One big limitation of backtesting is it's inability to know how prices moved intra-candle (was high before close, or vice-versa?).
|
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).
|
So assuming you run backtesting with a 1h timeframe, there will be 4 prices for that candle (Open, High, Low, Close).
|
||||||
|
|
||||||
While backtesting does take some assumptions (read above) about this - this can never be perfect, and will always be biased in one way or the other.
|
While backtesting does take some assumptions (read above) about this - this can never be perfect, and will always be biased in one way or the other.
|
||||||
@@ -600,8 +575,7 @@ To utilize this, you can append `--timeframe-detail 5m` to your regular backtest
|
|||||||
freqtrade backtesting --strategy AwesomeStrategy --timeframe 1h --timeframe-detail 5m
|
freqtrade backtesting --strategy AwesomeStrategy --timeframe 1h --timeframe-detail 5m
|
||||||
```
|
```
|
||||||
|
|
||||||
This will load 1h data as well as 5m data for the timeframe. The strategy will be analyzed with the 1h timeframe, and Entry orders will only be placed at the main timeframe, however Order fills and exit signals will be evaluated at the 5m candle, simulating intra-candle movements.
|
This will load 1h data as well as 5m data for the timeframe. The strategy will be analyzed with the 1h timeframe - and for every "open trade candle" (candles where a trade is open) the 5m data will be used to simulate intra-candle movements.
|
||||||
|
|
||||||
All callback functions (`custom_exit()`, `custom_stoploss()`, ... ) will be running for each 5m candle once the trade is opened (so 12 times in the above example of 1h timeframe, and 5m detailed timeframe).
|
All callback functions (`custom_exit()`, `custom_stoploss()`, ... ) will be running for each 5m candle once the trade is opened (so 12 times in the above example of 1h timeframe, and 5m detailed timeframe).
|
||||||
|
|
||||||
`--timeframe-detail` must be smaller than the original timeframe, otherwise backtesting will fail to start.
|
`--timeframe-detail` must be smaller than the original timeframe, otherwise backtesting will fail to start.
|
||||||
@@ -619,22 +593,22 @@ To compare multiple strategies, a list of Strategies can be provided to backtest
|
|||||||
This is limited to 1 timeframe value per run. However, data is only loaded once from disk so if you have multiple
|
This is limited to 1 timeframe value per run. However, data is only loaded once from disk so if you have multiple
|
||||||
strategies you'd like to compare, this will give a nice runtime boost.
|
strategies you'd like to compare, this will give a nice runtime boost.
|
||||||
|
|
||||||
All listed Strategies need to be in the same directory, unless also `--recursive-strategy-search` is specified, where sub-directories within the strategy directory are also considered.
|
All listed Strategies need to be in the same directory.
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
freqtrade backtesting --timerange 20180401-20180410 --timeframe 5m --strategy-list Strategy001 Strategy002 --export trades
|
freqtrade backtesting --timerange 20180401-20180410 --timeframe 5m --strategy-list Strategy001 Strategy002 --export trades
|
||||||
```
|
```
|
||||||
|
|
||||||
This will save the results to `user_data/backtest_results/backtest-result-<datetime>.json`, including results for both `Strategy001` and `Strategy002`.
|
This will save the results to `user_data/backtest_results/backtest-result-<strategy>.json`, injecting the strategy-name into the target filename.
|
||||||
There will be an additional table comparing win/losses of the different strategies (identical to the "Total" row in the first table).
|
There will be an additional table comparing win/losses of the different strategies (identical to the "Total" row in the first table).
|
||||||
Detailed output for all strategies one after the other will be available, so make sure to scroll up to see the details per strategy.
|
Detailed output for all strategies one after the other will be available, so make sure to scroll up to see the details per strategy.
|
||||||
|
|
||||||
```
|
```
|
||||||
================================================== STRATEGY SUMMARY ===================================================================
|
=========================================================== STRATEGY SUMMARY =========================================================================
|
||||||
| Strategy | Trades | Avg Profit % | Tot Profit BTC | Tot Profit % | Avg Duration | Wins | Draws | Losses | Drawdown % |
|
| Strategy | Buys | Avg Profit % | Cum Profit % | Tot Profit BTC | Tot Profit % | Avg Duration | Wins | Draws | Losses | Drawdown % |
|
||||||
|-------------+---------+----------------+------------------+----------------+----------------+-------+--------+--------+------------|
|
|:------------|-------:|---------------:|---------------:|-----------------:|---------------:|:---------------|------:|-------:|-------:|-----------:|
|
||||||
| Strategy1 | 429 | 0.36 | 0.00762792 | 76.20 | 4:12:00 | 186 | 0 | 243 | 45.2 |
|
| Strategy1 | 429 | 0.36 | 152.41 | 0.00762792 | 76.20 | 4:12:00 | 186 | 0 | 243 | 45.2 |
|
||||||
| Strategy2 | 1487 | -0.13 | -0.00988917 | -98.79 | 4:43:00 | 662 | 0 | 825 | 241.68 |
|
| Strategy2 | 1487 | -0.13 | -197.58 | -0.00988917 | -98.79 | 4:43:00 | 662 | 0 | 825 | 241.68 |
|
||||||
```
|
```
|
||||||
|
|
||||||
## Next step
|
## Next step
|
||||||
|
|||||||
@@ -7,32 +7,16 @@ This page provides you some basic concepts on how Freqtrade works and operates.
|
|||||||
* **Strategy**: Your trading strategy, telling the bot what to do.
|
* **Strategy**: Your trading strategy, telling the bot what to do.
|
||||||
* **Trade**: Open position.
|
* **Trade**: Open position.
|
||||||
* **Open Order**: Order which is currently placed on the exchange, and is not yet complete.
|
* **Open Order**: Order which is currently placed on the exchange, and is not yet complete.
|
||||||
* **Pair**: Tradable pair, usually in the format of Base/Quote (e.g. `XRP/USDT` for spot, `XRP/USDT:USDT` for futures).
|
* **Pair**: Tradable pair, usually in the format of Base/Quote (e.g. XRP/USDT).
|
||||||
* **Timeframe**: Candle length to use (e.g. `"5m"`, `"1h"`, ...).
|
* **Timeframe**: Candle length to use (e.g. `"5m"`, `"1h"`, ...).
|
||||||
* **Indicators**: Technical indicators (SMA, EMA, RSI, ...).
|
* **Indicators**: Technical indicators (SMA, EMA, RSI, ...).
|
||||||
* **Limit order**: Limit orders which execute at the defined limit price or better.
|
* **Limit order**: Limit orders which execute at the defined limit price or better.
|
||||||
* **Market order**: Guaranteed to fill, may move price depending on the order size.
|
* **Market order**: Guaranteed to fill, may move price depending on the order size.
|
||||||
* **Current Profit**: Currently pending (unrealized) profit for this trade. This is mainly used throughout the bot and UI.
|
|
||||||
* **Realized Profit**: Already realized profit. Only relevant in combination with [partial exits](strategy-callbacks.md#adjust-trade-position) - which also explains the calculation logic for this.
|
|
||||||
* **Total Profit**: Combined realized and unrealized profit. The relative number (%) is calculated against the total investment in this trade.
|
|
||||||
|
|
||||||
## Fee handling
|
## Fee handling
|
||||||
|
|
||||||
All profit calculations of Freqtrade include fees. For Backtesting / Hyperopt / Dry-run modes, the exchange default fee is used (lowest tier on the exchange). For live operations, fees are used as applied by the exchange (this includes BNB rebates etc.).
|
All profit calculations of Freqtrade include fees. For Backtesting / Hyperopt / Dry-run modes, the exchange default fee is used (lowest tier on the exchange). For live operations, fees are used as applied by the exchange (this includes BNB rebates etc.).
|
||||||
|
|
||||||
## Pair naming
|
|
||||||
|
|
||||||
Freqtrade follows the [ccxt naming convention](https://docs.ccxt.com/#/README?id=consistency-of-base-and-quote-currencies) for currencies.
|
|
||||||
Using the wrong naming convention in the wrong market will usually result in the bot not recognizing the pair, usually resulting in errors like "this pair is not available".
|
|
||||||
|
|
||||||
### Spot pair naming
|
|
||||||
|
|
||||||
For spot pairs, naming will be `base/quote` (e.g. `ETH/USDT`).
|
|
||||||
|
|
||||||
### Futures pair naming
|
|
||||||
|
|
||||||
For futures pairs, naming will be `base/quote:settle` (e.g. `ETH/USDT:USDT`).
|
|
||||||
|
|
||||||
## Bot execution logic
|
## Bot execution logic
|
||||||
|
|
||||||
Starting freqtrade in dry-run or live mode (using `freqtrade trade`) will start the bot and start the bot iteration loop.
|
Starting freqtrade in dry-run or live mode (using `freqtrade trade`) will start the bot and start the bot iteration loop.
|
||||||
@@ -49,12 +33,10 @@ By default, the bot loop runs every few seconds (`internals.process_throttle_sec
|
|||||||
* Call `populate_indicators()`
|
* Call `populate_indicators()`
|
||||||
* Call `populate_entry_trend()`
|
* Call `populate_entry_trend()`
|
||||||
* Call `populate_exit_trend()`
|
* Call `populate_exit_trend()`
|
||||||
* Update trades open order state from exchange.
|
* Check timeouts for open orders.
|
||||||
* Call `order_filled()` strategy callback for filled orders.
|
* Calls `check_entry_timeout()` strategy callback for open entry orders.
|
||||||
* Check timeouts for open orders.
|
* Calls `check_exit_timeout()` strategy callback for open exit orders.
|
||||||
* Calls `check_entry_timeout()` strategy callback for open entry orders.
|
* Calls `adjust_entry_price()` 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.
|
* Verifies existing positions and eventually places exit orders.
|
||||||
* Considers stoploss, ROI and exit-signal, `custom_exit()` and `custom_stoploss()`.
|
* 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.
|
* Determine exit-price based on `exit_pricing` configuration setting or by using the `custom_exit_price()` callback.
|
||||||
@@ -75,10 +57,10 @@ This loop will be repeated again and again until the bot is stopped.
|
|||||||
|
|
||||||
* Load historic data for configured pairlist.
|
* Load historic data for configured pairlist.
|
||||||
* Calls `bot_start()` once.
|
* Calls `bot_start()` once.
|
||||||
|
* Calls `bot_loop_start()` once.
|
||||||
* Calculate indicators (calls `populate_indicators()` once per pair).
|
* Calculate indicators (calls `populate_indicators()` once per pair).
|
||||||
* Calculate entry / exit signals (calls `populate_entry_trend()` and `populate_exit_trend()` 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.
|
* Loops per candle simulating entry and exit points.
|
||||||
* Calls `bot_loop_start()` strategy callback.
|
|
||||||
* Check for Order timeouts, either via the `unfilledtimeout` configuration, or via `check_entry_timeout()` / `check_exit_timeout()` strategy callbacks.
|
* 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.
|
* Calls `adjust_entry_price()` strategy callback for open entry orders.
|
||||||
* Check for trade entry signals (`enter_long` / `enter_short` columns).
|
* Check for trade entry signals (`enter_long` / `enter_short` columns).
|
||||||
@@ -87,15 +69,9 @@ This loop will be repeated again and again until the bot is stopped.
|
|||||||
* In Margin and Futures mode, `leverage()` strategy callback is called to determine the desired leverage.
|
* In Margin and Futures mode, `leverage()` strategy callback is called to determine the desired leverage.
|
||||||
* Determine stake size by calling the `custom_stake_amount()` callback.
|
* Determine stake size by calling the `custom_stake_amount()` callback.
|
||||||
* Check position adjustments for open trades if enabled and call `adjust_trade_position()` to determine if an additional order is requested.
|
* Check position adjustments for open trades if enabled and call `adjust_trade_position()` to determine if an additional order is requested.
|
||||||
* Call `order_filled()` strategy callback for filled entry orders.
|
|
||||||
* Call `custom_stoploss()` and `custom_exit()` to find custom exit points.
|
* Call `custom_stoploss()` and `custom_exit()` to find custom exit points.
|
||||||
* For exits based on exit-signal, custom-exit and partial exits: Call `custom_exit_price()` to determine exit price (Prices are moved to be within the closing candle).
|
* For exits based on exit-signal and custom-exit: Call `custom_exit_price()` to determine exit price (Prices are moved to be within the closing candle).
|
||||||
* Call `order_filled()` strategy callback for filled exit orders.
|
|
||||||
* Generate backtest report output
|
* Generate backtest report output
|
||||||
|
|
||||||
!!! Note
|
!!! Note
|
||||||
Both Backtesting and Hyperopt include exchange default Fees in the calculation. Custom fees can be passed to backtesting / hyperopt by specifying the `--fee` argument.
|
Both Backtesting and Hyperopt include exchange default Fees in the calculation. Custom fees can be passed to backtesting / hyperopt by specifying the `--fee` argument.
|
||||||
|
|
||||||
!!! Warning "Callback call frequency"
|
|
||||||
Backtesting will call each callback at max. once per candle (`--timeframe-detail` modifies this behavior to once per detailed candle).
|
|
||||||
Most callbacks will be called once per iteration in live (usually every ~5s) - which can cause backtesting mismatches.
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
This page explains the different parameters of the bot and how to run it.
|
This page explains the different parameters of the bot and how to run it.
|
||||||
|
|
||||||
!!! Note
|
!!! Note
|
||||||
If you've used `setup.sh`, don't forget to activate your virtual environment (`source .venv/bin/activate`) before running freqtrade commands.
|
If you've used `setup.sh`, don't forget to activate your virtual environment (`source .env/bin/activate`) before running freqtrade commands.
|
||||||
|
|
||||||
!!! Warning "Up-to-date clock"
|
!!! Warning "Up-to-date clock"
|
||||||
The clock on the system running the bot must be accurate, synchronized to a NTP server frequently enough to avoid problems with communication to the exchanges.
|
The clock on the system running the bot must be accurate, synchronized to a NTP server frequently enough to avoid problems with communication to the exchanges.
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ Per default, the bot loads the configuration from the `config.json` file, locate
|
|||||||
|
|
||||||
You can specify a different configuration file used by the bot with the `-c/--config` command-line option.
|
You can specify a different configuration file used by the bot with the `-c/--config` command-line option.
|
||||||
|
|
||||||
If you used the [Quick start](docker_quickstart.md#docker-quick-start) method for installing
|
If you used the [Quick start](installation.md/#quick-start) method for installing
|
||||||
the bot, the installation script should have already created the default configuration file (`config.json`) for you.
|
the bot, the installation script should have already created the default configuration file (`config.json`) for you.
|
||||||
|
|
||||||
If the default configuration file is not created we recommend to use `freqtrade new-config --config user_data/config.json` to generate a basic configuration file.
|
If the default configuration file is not created we recommend to use `freqtrade new-config --config config.json` to generate a basic configuration file.
|
||||||
|
|
||||||
The Freqtrade configuration file is to be written in JSON format.
|
The Freqtrade configuration file is to be written in JSON format.
|
||||||
|
|
||||||
@@ -49,13 +49,6 @@ FREQTRADE__EXCHANGE__SECRET=<yourExchangeSecret>
|
|||||||
!!! Note
|
!!! Note
|
||||||
Environment variables detected are logged at startup - so if you can't find why a value is not what you think it should be based on the configuration, make sure it's not loaded from an environment variable.
|
Environment variables detected are logged at startup - so if you can't find why a value is not what you think it should be based on the configuration, make sure it's not loaded from an environment variable.
|
||||||
|
|
||||||
!!! Tip "Validate combined result"
|
|
||||||
You can use the [show-config subcommand](utils.md#show-config) to see the final, combined configuration.
|
|
||||||
|
|
||||||
??? Warning "Loading sequence"
|
|
||||||
Environment variables are loaded after the initial configuration. As such, you cannot provide the path to the configuration through environment variables. Please use `--config path/to/config.json` for that.
|
|
||||||
This also applies to user_dir to some degree. while the user directory can be set through environment variables - the configuration will **not** be loaded from that location.
|
|
||||||
|
|
||||||
### Multiple configuration files
|
### Multiple configuration files
|
||||||
|
|
||||||
Multiple configuration files can be specified and used by the bot or the bot can read its configuration parameters from the process standard input stream.
|
Multiple configuration files can be specified and used by the bot or the bot can read its configuration parameters from the process standard input stream.
|
||||||
@@ -63,25 +56,11 @@ Multiple configuration files can be specified and used by the bot or the bot can
|
|||||||
You can specify additional configuration files in `add_config_files`. Files specified in this parameter will be loaded and merged with the initial config file. The files are resolved relative to the initial configuration file.
|
You can specify additional configuration files in `add_config_files`. Files specified in this parameter will be loaded and merged with the initial config file. The files are resolved relative to the initial configuration file.
|
||||||
This is similar to using multiple `--config` parameters, but simpler in usage as you don't have to specify all files for all commands.
|
This is similar to using multiple `--config` parameters, but simpler in usage as you don't have to specify all files for all commands.
|
||||||
|
|
||||||
!!! Tip "Validate combined result"
|
|
||||||
You can use the [show-config subcommand](utils.md#show-config) to see the final, combined configuration.
|
|
||||||
|
|
||||||
!!! Tip "Use multiple configuration files to keep secrets secret"
|
!!! Tip "Use multiple configuration files to keep secrets secret"
|
||||||
You can use a 2nd configuration file containing your secrets. That way you can share your "primary" configuration file, while still keeping your API keys for yourself.
|
You can use a 2nd configuration file containing your secrets. That way you can share your "primary" configuration file, while still keeping your API keys for yourself.
|
||||||
The 2nd file should only specify what you intend to override.
|
|
||||||
If a key is in more than one of the configurations, then the "last specified configuration" wins (in the above example, `config-private.json`).
|
|
||||||
|
|
||||||
For one-off commands, you can also use the below syntax by specifying multiple "--config" parameters.
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
freqtrade trade --config user_data/config1.json --config user_data/config-private.json <...>
|
|
||||||
```
|
|
||||||
|
|
||||||
The below is equivalent to the example above - but having 2 configuration files in the configuration, for easier reuse.
|
|
||||||
|
|
||||||
``` json title="user_data/config.json"
|
``` json title="user_data/config.json"
|
||||||
"add_config_files": [
|
"add_config_files": [
|
||||||
"config1.json",
|
|
||||||
"config-private.json"
|
"config-private.json"
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
@@ -90,6 +69,17 @@ This is similar to using multiple `--config` parameters, but simpler in usage as
|
|||||||
freqtrade trade --config user_data/config.json <...>
|
freqtrade trade --config user_data/config.json <...>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The 2nd file should only specify what you intend to override.
|
||||||
|
If a key is in more than one of the configurations, then the "last specified configuration" wins (in the above example, `config-private.json`).
|
||||||
|
|
||||||
|
For one-off commands, you can also use the below syntax by specifying multiple "--config" parameters.
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
freqtrade trade --config user_data/config.json --config user_data/config-private.json <...>
|
||||||
|
```
|
||||||
|
|
||||||
|
This is equivalent to the example above - but `config-private.json` is specified as cli argument.
|
||||||
|
|
||||||
??? Note "config collision handling"
|
??? Note "config collision handling"
|
||||||
If the same configuration setting takes place in both `config.json` and `config-import.json`, then the parent configuration wins.
|
If the same configuration setting takes place in both `config.json` and `config-import.json`, then the parent configuration wins.
|
||||||
In the below case, `max_open_trades` would be 3 after the merging - as the reusable "import" configuration has this key overwritten.
|
In the below case, `max_open_trades` would be 3 after the merging - as the reusable "import" configuration has this key overwritten.
|
||||||
@@ -121,8 +111,6 @@ This is similar to using multiple `--config` parameters, but simpler in usage as
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If multiple files are in the `add_config_files` section, then they will be assumed to be at identical levels, having the last occurrence override the earlier config (unless a parent already defined such a key).
|
|
||||||
|
|
||||||
## Configuration parameters
|
## Configuration parameters
|
||||||
|
|
||||||
The table below will list all configuration parameters available.
|
The table below will list all configuration parameters available.
|
||||||
@@ -144,11 +132,11 @@ Mandatory parameters are marked as **Required**, which means that they are requi
|
|||||||
|
|
||||||
| Parameter | Description |
|
| Parameter | Description |
|
||||||
|------------|-------------|
|
|------------|-------------|
|
||||||
| `max_open_trades` | **Required.** Number of open trades your bot is allowed to have. Only one open trade per pair is possible, so the length of your pairlist is another limitation that can apply. If -1 then it is ignored (i.e. potentially unlimited open trades, limited by the pairlist). [More information below](#configuring-amount-per-trade). [Strategy Override](#parameters-in-the-strategy).<br> **Datatype:** Positive integer or -1.
|
| `max_open_trades` | **Required.** Number of open trades your bot is allowed to have. Only one open trade per pair is possible, so the length of your pairlist is another limitation that can apply. If -1 then it is ignored (i.e. potentially unlimited open trades, limited by the pairlist). [More information below](#configuring-amount-per-trade).<br> **Datatype:** Positive integer or -1.
|
||||||
| `stake_currency` | **Required.** Crypto-currency used for trading. <br> **Datatype:** String
|
| `stake_currency` | **Required.** Crypto-currency used for trading. <br> **Datatype:** String
|
||||||
| `stake_amount` | **Required.** Amount of crypto-currency your bot will use for each trade. Set it to `"unlimited"` to allow the bot to use all available balance. [More information below](#configuring-amount-per-trade). <br> **Datatype:** Positive float or `"unlimited"`.
|
| `stake_amount` | **Required.** Amount of crypto-currency your bot will use for each trade. Set it to `"unlimited"` to allow the bot to use all available balance. [More information below](#configuring-amount-per-trade). <br> **Datatype:** Positive float or `"unlimited"`.
|
||||||
| `tradable_balance_ratio` | Ratio of the total account balance the bot is allowed to trade. [More information below](#configuring-amount-per-trade). <br>*Defaults to `0.99` 99%).*<br> **Datatype:** Positive float between `0.1` and `1.0`.
|
| `tradable_balance_ratio` | Ratio of the total account balance the bot is allowed to trade. [More information below](#configuring-amount-per-trade). <br>*Defaults to `0.99` 99%).*<br> **Datatype:** Positive float between `0.1` and `1.0`.
|
||||||
| `available_capital` | Available starting capital for the bot. Useful when running multiple bots on the same exchange account. [More information below](#configuring-amount-per-trade). <br> **Datatype:** Positive float.
|
| `available_capital` | Available starting capital for the bot. Useful when running multiple bots on the same exchange account.[More information below](#configuring-amount-per-trade). <br> **Datatype:** Positive float.
|
||||||
| `amend_last_stake_amount` | Use reduced last stake amount if necessary. [More information below](#configuring-amount-per-trade). <br>*Defaults to `false`.* <br> **Datatype:** Boolean
|
| `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)
|
| `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.
|
| `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.
|
||||||
@@ -165,29 +153,29 @@ 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_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
|
| `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)
|
| `fee` | Fee used during backtesting / dry-runs. Should normally not be configured, which has freqtrade fall back to the exchange default fee. Set as ratio (e.g. 0.001 = 0.1%). Fee is applied twice for each trade, once when buying, once when selling. <br> **Datatype:** Float (as ratio)
|
||||||
| `futures_funding_rate` | User-specified funding rate to be used when historical funding rates are not available from the exchange. This does not overwrite real historical rates. It is recommended that this be set to 0 unless you are testing a specific coin and you understand how the funding rate will affect freqtrade's profit calculations. [More information here](leverage.md#unavailable-funding-rates) <br>*Defaults to `None`.*<br> **Datatype:** Float
|
| `futures_funding_rate` | User-specified funding rate to be used when historical funding rates are not available from the exchange. This does not overwrite real historical rates. It is recommended that this be set to 0 unless you are testing a specific coin and you understand how the funding rate will affect freqtrade's profit calculations. [More information here](leverage.md#unavailable-funding-rates) <br>*Defaults to None.*<br> **Datatype:** Float
|
||||||
| `trading_mode` | Specifies if you want to trade regularly, trade with leverage, or trade contracts whose prices are derived from matching cryptocurrency prices. [leverage documentation](leverage.md). <br>*Defaults to `"spot"`.* <br> **Datatype:** String
|
| `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
|
| `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
|
| `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**
|
| | **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.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.exit` | **Required.** How long (in minutes or seconds) the bot will wait for an unfilled exit order to complete, after which the order will be cancelled and repeated at current (new) price, as long as there is a signal. [Strategy Override](#parameters-in-the-strategy).<br> **Datatype:** Integer
|
||||||
| `unfilledtimeout.unit` | Unit to use in unfilledtimeout setting. Note: If you set unfilledtimeout.unit to "seconds", "internals.process_throttle_secs" must be inferior or equal to timeout [Strategy Override](#parameters-in-the-strategy). <br> *Defaults to `"minutes"`.* <br> **Datatype:** String
|
| `unfilledtimeout.unit` | Unit to use in unfilledtimeout setting. Note: If you set unfilledtimeout.unit to "seconds", "internals.process_throttle_secs" must be inferior or equal to timeout [Strategy Override](#parameters-in-the-strategy). <br> *Defaults to `minutes`.* <br> **Datatype:** String
|
||||||
| `unfilledtimeout.exit_timeout_count` | How many times can exit orders time out. Once this number of timeouts is reached, an emergency exit is triggered. 0 to disable and allow unlimited order cancels. [Strategy Override](#parameters-in-the-strategy).<br>*Defaults to `0`.* <br> **Datatype:** Integer
|
| `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**
|
| | **Pricing**
|
||||||
| `entry_pricing.price_side` | Select the side of the spread the bot should look at to get the entry rate. [More information below](#entry-price).<br> *Defaults to `"same"`.* <br> **Datatype:** String (either `ask`, `bid`, `same` or `other`).
|
| `entry_pricing.price_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.price_last_balance` | **Required.** Interpolate the bidding price. More information [below](#entry-price-without-orderbook-enabled).
|
||||||
| `entry_pricing.use_order_book` | Enable entering using the rates in [Order Book Entry](#entry-price-with-orderbook-enabled). <br> *Defaults to `true`.*<br> **Datatype:** Boolean
|
| `entry_pricing.use_order_book` | Enable entering using the rates in [Order Book Entry](#entry-price-with-orderbook-enabled). <br> *Defaults to `True`.*<br> **Datatype:** Boolean
|
||||||
| `entry_pricing.order_book_top` | Bot will use the top N rate in Order Book "price_side" to enter a trade. I.e. a value of 2 will allow the bot to pick the 2nd entry in [Order Book Entry](#entry-price-with-orderbook-enabled). <br>*Defaults to `1`.* <br> **Datatype:** Positive Integer
|
| `entry_pricing.order_book_top` | Bot will use the top N rate in Order Book "price_side" to enter a trade. I.e. a value of 2 will allow the bot to pick the 2nd entry in [Order Book Entry](#entry-price-with-orderbook-enabled). <br>*Defaults to `1`.* <br> **Datatype:** Positive Integer
|
||||||
| `entry_pricing. check_depth_of_market.enabled` | Do not enter if the difference of buy orders and sell orders is met in Order Book. [Check market depth](#check-depth-of-market). <br>*Defaults to `false`.* <br> **Datatype:** Boolean
|
| `entry_pricing. check_depth_of_market.enabled` | Do not enter if the difference of buy orders and sell orders is met in Order Book. [Check market depth](#check-depth-of-market). <br>*Defaults to `false`.* <br> **Datatype:** Boolean
|
||||||
| `entry_pricing. check_depth_of_market.bids_to_ask_delta` | The difference ratio of buy orders and sell orders found in Order Book. A value below 1 means sell order size is greater, while value greater than 1 means buy order size is higher. [Check market depth](#check-depth-of-market) <br> *Defaults to `0`.* <br> **Datatype:** Float (as ratio)
|
| `entry_pricing. check_depth_of_market.bids_to_ask_delta` | The difference ratio of buy orders and sell orders found in Order Book. A value below 1 means sell order size is greater, while value greater than 1 means buy order size is higher. [Check market depth](#check-depth-of-market) <br> *Defaults to `0`.* <br> **Datatype:** Float (as ratio)
|
||||||
| `exit_pricing.price_side` | Select the side of the spread the bot should look at to get the exit rate. [More information below](#exit-price-side).<br> *Defaults to `"same"`.* <br> **Datatype:** String (either `ask`, `bid`, `same` or `other`).
|
| `exit_pricing.price_side` | Select the side of the spread the bot should look at to get the exit rate. [More information below](#exit-price-side).<br> *Defaults to `same`.* <br> **Datatype:** String (either `ask`, `bid`, `same` or `other`).
|
||||||
| `exit_pricing.price_last_balance` | Interpolate the exiting price. More information [below](#exit-price-without-orderbook-enabled).
|
| `exit_pricing.price_last_balance` | Interpolate the exiting price. More information [below](#exit-price-without-orderbook-enabled).
|
||||||
| `exit_pricing.use_order_book` | Enable exiting of open trades using [Order Book Exit](#exit-price-with-orderbook-enabled). <br> *Defaults to `true`.*<br> **Datatype:** Boolean
|
| `exit_pricing.use_order_book` | Enable exiting of open trades using [Order Book Exit](#exit-price-with-orderbook-enabled). <br> *Defaults to `True`.*<br> **Datatype:** Boolean
|
||||||
| `exit_pricing.order_book_top` | Bot will use the top N rate in Order Book "price_side" to exit. I.e. a value of 2 will allow the bot to pick the 2nd ask rate in [Order Book Exit](#exit-price-with-orderbook-enabled)<br>*Defaults to `1`.* <br> **Datatype:** Positive Integer
|
| `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
|
| `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**
|
| | **TODO**
|
||||||
| `use_exit_signal` | Use exit signals produced by the strategy in addition to the `minimal_roi`. <br>Setting this to false disables the usage of `"exit_long"` and `"exit_short"` columns. Has no influence on other exit methods (Stoploss, ROI, callbacks). [Strategy Override](#parameters-in-the-strategy). <br>*Defaults to `true`.* <br> **Datatype:** Boolean
|
| `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_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)
|
| `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)
|
||||||
| `ignore_roi_if_entry_signal` | Do not exit if the entry signal is still active. This setting takes preference over `minimal_roi` and `use_exit_signal`. [Strategy Override](#parameters-in-the-strategy). <br>*Defaults to `false`.* <br> **Datatype:** Boolean
|
| `ignore_roi_if_entry_signal` | Do not exit if the entry signal is still active. This setting takes preference over `minimal_roi` and `use_exit_signal`. [Strategy Override](#parameters-in-the-strategy). <br>*Defaults to `false`.* <br> **Datatype:** Boolean
|
||||||
@@ -197,22 +185,22 @@ Mandatory parameters are marked as **Required**, which means that they are requi
|
|||||||
| `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
|
| `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
|
| `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**
|
||||||
| `exchange.name` | **Required.** Name of the exchange class to use. <br> **Datatype:** String
|
| `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
|
| `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
|
||||||
| `exchange.secret` | API secret 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
|
| `exchange.secret` | API secret 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
|
||||||
| `exchange.password` | API password to use for the exchange. Only required when you are in production mode and for exchanges that use password for API requests.<br>**Keep it in secret, do not disclose publicly.** <br> **Datatype:** String
|
| `exchange.password` | API password to use for the exchange. Only required when you are in production mode and for exchanges that use password for API requests.<br>**Keep it in secret, do not disclose publicly.** <br> **Datatype:** String
|
||||||
| `exchange.uid` | API uid to use for the exchange. Only required when you are in production mode and for exchanges that use uid for API requests.<br>**Keep it in secret, do not disclose publicly.** <br> **Datatype:** String
|
| `exchange.uid` | API uid to use for the exchange. Only required when you are in production mode and for exchanges that use uid for API requests.<br>**Keep it in secret, do not disclose publicly.** <br> **Datatype:** String
|
||||||
| `exchange.pair_whitelist` | List of pairs to use by the bot for trading and to check for potential trades during backtesting. Supports regex pairs as `.*/BTC`. Not used by VolumePairList. [More information](plugins.md#pairlists-and-pairlist-handlers). <br> **Datatype:** List
|
| `exchange.pair_whitelist` | List of pairs to use by the bot for trading and to check for potential trades during backtesting. Supports regex pairs as `.*/BTC`. Not used by VolumePairList. [More information](plugins.md#pairlists-and-pairlist-handlers). <br> **Datatype:** List
|
||||||
| `exchange.pair_blacklist` | List of pairs the bot must absolutely avoid for trading and backtesting. [More information](plugins.md#pairlists-and-pairlist-handlers). <br> **Datatype:** List
|
| `exchange.pair_blacklist` | List of pairs the bot must absolutely avoid for trading and backtesting. [More information](plugins.md#pairlists-and-pairlist-handlers). <br> **Datatype:** List
|
||||||
| `exchange.ccxt_config` | Additional CCXT parameters passed to both ccxt instances (sync and async). This is usually the correct place for additional ccxt configurations. Parameters may differ from exchange to exchange and are documented in the [ccxt documentation](https://docs.ccxt.com/#/README?id=overriding-exchange-properties-upon-instantiation). Please avoid adding exchange secrets here (use the dedicated fields instead), as they may be contained in logs. <br> **Datatype:** Dict
|
| `exchange.ccxt_config` | Additional CCXT parameters passed to both ccxt instances (sync and async). This is usually the correct place for additional ccxt configurations. Parameters may differ from exchange to exchange and are documented in the [ccxt documentation](https://ccxt.readthedocs.io/en/latest/manual.html#instantiation). Please avoid adding exchange secrets here (use the dedicated fields instead), as they may be contained in logs. <br> **Datatype:** Dict
|
||||||
| `exchange.ccxt_sync_config` | Additional CCXT parameters passed to the regular (sync) ccxt instance. Parameters may differ from exchange to exchange and are documented in the [ccxt documentation](https://docs.ccxt.com/#/README?id=overriding-exchange-properties-upon-instantiation) <br> **Datatype:** Dict
|
| `exchange.ccxt_sync_config` | Additional CCXT parameters passed to the regular (sync) ccxt instance. Parameters may differ from exchange to exchange and are documented in the [ccxt documentation](https://ccxt.readthedocs.io/en/latest/manual.html#instantiation) <br> **Datatype:** Dict
|
||||||
| `exchange.ccxt_async_config` | Additional CCXT parameters passed to the async ccxt instance. Parameters may differ from exchange to exchange and are documented in the [ccxt documentation](https://docs.ccxt.com/#/README?id=overriding-exchange-properties-upon-instantiation) <br> **Datatype:** Dict
|
| `exchange.ccxt_async_config` | Additional CCXT parameters passed to the async ccxt instance. Parameters may differ from exchange to exchange and are documented in the [ccxt documentation](https://ccxt.readthedocs.io/en/latest/manual.html#instantiation) <br> **Datatype:** Dict
|
||||||
| `exchange.enable_ws` | Enable the usage of Websockets for the exchange. <br>[More information](#consuming-exchange-websockets).<br>*Defaults to `true`.* <br> **Datatype:** Boolean
|
|
||||||
| `exchange.markets_refresh_interval` | The interval in minutes in which markets are reloaded. <br>*Defaults to `60` minutes.* <br> **Datatype:** Positive Integer
|
| `exchange.markets_refresh_interval` | The interval in minutes in which markets are reloaded. <br>*Defaults to `60` minutes.* <br> **Datatype:** Positive Integer
|
||||||
| `exchange.skip_pair_validation` | Skip pairlist validation on startup.<br>*Defaults to `false`*<br> **Datatype:** Boolean
|
| `exchange.skip_pair_validation` | Skip pairlist validation on startup.<br>*Defaults to `false`<br> **Datatype:** Boolean
|
||||||
| `exchange.skip_open_order_update` | Skips open order updates on startup should the exchange cause problems. Only relevant in live conditions.<br>*Defaults to `false`*<br> **Datatype:** Boolean
|
| `exchange.skip_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.unknown_fee_rate` | Fallback value to use when calculating trading fees. This can be useful for exchanges which have fees in non-tradable currencies. The value provided here will be multiplied with the "fee cost".<br>*Defaults to `None`<br> **Datatype:** float
|
||||||
| `exchange.log_responses` | Log relevant exchange responses. For debug mode only - use with care.<br>*Defaults to `false`*<br> **Datatype:** Boolean
|
| `exchange.log_responses` | Log relevant exchange responses. For debug mode only - use with care.<br>*Defaults to `false`<br> **Datatype:** Boolean
|
||||||
| `experimental.block_bad_exchanges` | Block exchanges known to not work with freqtrade. Leave on default unless you want to test if that exchange works now. <br>*Defaults to `true`.* <br> **Datatype:** Boolean
|
| `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**
|
| | **Plugins**
|
||||||
| `edge.*` | Please refer to [edge configuration document](edge.md) for detailed explanation of all possible configuration options.
|
| `edge.*` | Please refer to [edge configuration document](edge.md) for detailed explanation of all possible configuration options.
|
||||||
@@ -223,37 +211,33 @@ Mandatory parameters are marked as **Required**, which means that they are requi
|
|||||||
| `telegram.token` | Your Telegram bot token. Only required if `telegram.enabled` is `true`. <br>**Keep it in secret, do not disclose publicly.** <br> **Datatype:** String
|
| `telegram.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.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.balance_dust_level` | Dust-level (in stake currency) - currencies with a balance below this will not be shown by `/balance`. <br> **Datatype:** float
|
||||||
| `telegram.reload` | Allow "reload" buttons on telegram messages. <br>*Defaults to `true`.<br> **Datatype:** boolean
|
| `telegram.reload` | Allow "reload" buttons on telegram messages. <br>*Defaults to `True`.<br> **Datatype:** boolean
|
||||||
| `telegram.notification_settings.*` | Detailed notification settings. Refer to the [telegram documentation](telegram-usage.md) for details.<br> **Datatype:** dictionary
|
| `telegram.notification_settings.*` | Detailed notification settings. Refer to the [telegram documentation](telegram-usage.md) for details.<br> **Datatype:** dictionary
|
||||||
| `telegram.allow_custom_messages` | Enable the sending of Telegram messages from strategies via the dataprovider.send_msg() function. <br> **Datatype:** Boolean
|
|
||||||
| | **Webhook**
|
| | **Webhook**
|
||||||
| `webhook.enabled` | Enable usage of Webhook notifications <br> **Datatype:** Boolean
|
| `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.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.entry` | 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
|
| `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
|
||||||
| `webhook.entry_cancel` | Payload to send on entry order cancel. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
| `webhook.webhookentrycancel` | Payload to send on entry order cancel. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
||||||
| `webhook.entry_fill` | Payload to send on entry order filled. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
| `webhook.webhookentryfill` | Payload to send on entry order filled. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
||||||
| `webhook.exit` | Payload to send on exit. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
| `webhook.webhookexit` | Payload to send on exit. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
||||||
| `webhook.exit_cancel` | 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.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.exit_fill` | 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.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.status` | 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
|
| `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
|
||||||
| `webhook.allow_custom_messages` | Enable the sending of Webhook messages from strategies via the dataprovider.send_msg() function. <br> **Datatype:** Boolean
|
| | **Rest API / FreqUI**
|
||||||
| | **Rest API / FreqUI / Producer-Consumer**
|
|
||||||
| `api_server.enabled` | Enable usage of API Server. See the [API Server documentation](rest-api.md) for more details. <br> **Datatype:** Boolean
|
| `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_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
|
| `api_server.listen_port` | Bind Port. See the [API Server documentation](rest-api.md) for more details. <br>**Datatype:** Integer between 1024 and 65535
|
||||||
| `api_server.verbosity` | Logging verbosity. `info` will print all RPC Calls, while "error" will only display errors. <br>**Datatype:** Enum, either `info` or `error`. Defaults to `info`.
|
| `api_server.verbosity` | Logging verbosity. `info` will print all RPC Calls, while "error" will only display errors. <br>**Datatype:** Enum, either `info` or `error`. Defaults to `info`.
|
||||||
| `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.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
|
| `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
|
||||||
| `api_server.ws_token` | API token for the Message WebSocket. 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
|
| `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
|
||||||
| `external_message_consumer` | Enable [Producer/Consumer mode](producer-consumer.md) for more details. <br> **Datatype:** Dict
|
|
||||||
| | **Other**
|
| | **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`
|
| `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
|
| `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
|
| `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
|
||||||
| `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.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.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](advanced-setup.md#configure-the-bot-running-as-a-systemd-service) for more details. <br> **Datatype:** Boolean
|
| `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
|
||||||
| `strategy` | **Required** Defines Strategy class to use. Recommended to be set via `--strategy NAME`. <br> **Datatype:** ClassName
|
| `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
|
| `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
|
| `recursive_strategy_search` | Set to `true` to recursively search sub-directories inside `user_data/strategies` for a strategy. <br> **Datatype:** Boolean
|
||||||
@@ -261,9 +245,8 @@ Mandatory parameters are marked as **Required**, which means that they are requi
|
|||||||
| `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
|
| `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
|
| `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
|
| `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 `feather`*. <br> **Datatype:** String
|
| `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 `feather`*. <br> **Datatype:** String
|
| `dataformat_trades` | Data format to use to store historical trades data. <br> *Defaults to `jsongz`*. <br> **Datatype:** String
|
||||||
| `reduce_df_footprint` | Recast all numeric columns to float32/int32, with the objective of reducing ram/disk usage (and decreasing train/inference timing in FreqAI). (Currently only affects FreqAI use-cases) <br> **Datatype:** Boolean. <br> Default: `False`.
|
|
||||||
|
|
||||||
### Parameters in the strategy
|
### Parameters in the strategy
|
||||||
|
|
||||||
@@ -273,7 +256,6 @@ Values set in the configuration file always overwrite values set in the strategy
|
|||||||
* `minimal_roi`
|
* `minimal_roi`
|
||||||
* `timeframe`
|
* `timeframe`
|
||||||
* `stoploss`
|
* `stoploss`
|
||||||
* `max_open_trades`
|
|
||||||
* `trailing_stop`
|
* `trailing_stop`
|
||||||
* `trailing_stop_positive`
|
* `trailing_stop_positive`
|
||||||
* `trailing_stop_positive_offset`
|
* `trailing_stop_positive_offset`
|
||||||
@@ -332,13 +314,11 @@ For example, if you have 10 ETH available in your wallet on the exchange and `tr
|
|||||||
To fully utilize compounding profits when using multiple bots on the same exchange account, you'll want to limit each bot to a certain starting balance.
|
To fully utilize compounding profits when using multiple bots on the same exchange account, you'll want to limit each bot to a certain starting balance.
|
||||||
This can be accomplished by setting `available_capital` to the desired starting balance.
|
This can be accomplished by setting `available_capital` to the desired starting balance.
|
||||||
|
|
||||||
Assuming your account has 10000 USDT and you want to run 2 different strategies on this exchange.
|
Assuming your account has 10.000 USDT and you want to run 2 different strategies on this exchange.
|
||||||
You'd set `available_capital=5000` - granting each bot an initial capital of 5000 USDT.
|
You'd set `available_capital=5000` - granting each bot an initial capital of 5000 USDT.
|
||||||
The bot will then split this starting balance equally into `max_open_trades` buckets.
|
The bot will then split this starting balance equally into `max_open_trades` buckets.
|
||||||
Profitable trades will result in increased stake-sizes for this bot - without affecting the stake-sizes of the other bot.
|
Profitable trades will result in increased stake-sizes for this bot - without affecting the stake-sizes of the other bot.
|
||||||
|
|
||||||
Adjusting `available_capital` requires reloading the configuration to take effect. Adjusting the `available_capital` adds the difference between the previous `available_capital` and the new `available_capital`. Decreasing the available capital when trades are open doesn't exit the trades. The difference is returned to the wallet when the trades conclude. The outcome of this differs depending on the price movement between the adjustment and exiting the trades.
|
|
||||||
|
|
||||||
!!! Warning "Incompatible with `tradable_balance_ratio`"
|
!!! Warning "Incompatible with `tradable_balance_ratio`"
|
||||||
Setting this option will replace any configuration of `tradable_balance_ratio`.
|
Setting this option will replace any configuration of `tradable_balance_ratio`.
|
||||||
|
|
||||||
@@ -371,7 +351,7 @@ This setting works in combination with `max_open_trades`. The maximum capital en
|
|||||||
For example, the bot will at most use (0.05 BTC x 3) = 0.15 BTC, assuming a configuration of `max_open_trades=3` and `stake_amount=0.05`.
|
For example, the bot will at most use (0.05 BTC x 3) = 0.15 BTC, assuming a configuration of `max_open_trades=3` and `stake_amount=0.05`.
|
||||||
|
|
||||||
!!! Note
|
!!! Note
|
||||||
This setting respects the [available balance configuration](#tradable-balance).
|
This setting respects the [available balance configuration](#available-balance).
|
||||||
|
|
||||||
#### Dynamic stake amount
|
#### Dynamic stake amount
|
||||||
|
|
||||||
@@ -410,8 +390,6 @@ Or another example if your position adjustment assumes it can do 1 additional bu
|
|||||||
|
|
||||||
--8<-- "includes/pricing.md"
|
--8<-- "includes/pricing.md"
|
||||||
|
|
||||||
## Further Configuration details
|
|
||||||
|
|
||||||
### Understand minimal_roi
|
### Understand minimal_roi
|
||||||
|
|
||||||
The `minimal_roi` configuration parameter is a JSON object where the key is a duration
|
The `minimal_roi` configuration parameter is a JSON object where the key is a duration
|
||||||
@@ -518,13 +496,13 @@ Configuration:
|
|||||||
Please carefully read the section [Market order pricing](#market-order-pricing) section when using market orders.
|
Please carefully read the section [Market order pricing](#market-order-pricing) section when using market orders.
|
||||||
|
|
||||||
!!! Note "Stoploss on exchange"
|
!!! Note "Stoploss on exchange"
|
||||||
`order_types.stoploss_on_exchange_interval` is not mandatory. Do not change its value if you are
|
`stoploss_on_exchange_interval` is not mandatory. Do not change its value if you are
|
||||||
unsure of what you are doing. For more information about how stoploss works please
|
unsure of what you are doing. For more information about how stoploss works please
|
||||||
refer to [the stoploss documentation](stoploss.md).
|
refer to [the stoploss documentation](stoploss.md).
|
||||||
|
|
||||||
If `order_types.stoploss_on_exchange` is enabled and the stoploss is cancelled manually on the exchange, then the bot will create a new stoploss order.
|
If `stoploss_on_exchange` is enabled and the stoploss is cancelled manually on the exchange, then the bot will create a new stoploss order.
|
||||||
|
|
||||||
!!! Warning "Warning: order_types.stoploss_on_exchange failures"
|
!!! Warning "Warning: stoploss_on_exchange failures"
|
||||||
If stoploss on exchange creation fails for some reason, then an "emergency exit" is initiated. By default, this will exit the trade using a market order. The order-type for the emergency-exit can be changed by setting the `emergency_exit` value in the `order_types` dictionary - however, this is not advised.
|
If stoploss on exchange creation fails for some reason, then an "emergency exit" is initiated. By default, this will exit the trade using a market order. The order-type for the emergency-exit can be changed by setting the `emergency_exit` value in the `order_types` dictionary - however, this is not advised.
|
||||||
|
|
||||||
### Understand order_time_in_force
|
### Understand order_time_in_force
|
||||||
@@ -547,38 +525,24 @@ It means if the order is not executed immediately AND fully then it is cancelled
|
|||||||
It is the same as FOK (above) except it can be partially fulfilled. The remaining part
|
It is the same as FOK (above) except it can be partially fulfilled. The remaining part
|
||||||
is automatically cancelled by the exchange.
|
is automatically cancelled by the exchange.
|
||||||
|
|
||||||
**PO (Post only):**
|
The `order_time_in_force` parameter contains a dict with buy and sell time in force policy values.
|
||||||
|
|
||||||
Post only order. The order is either placed as a maker order, or it is canceled.
|
|
||||||
This means the order must be placed on orderbook for at least time in an unfilled state.
|
|
||||||
|
|
||||||
#### time_in_force config
|
|
||||||
|
|
||||||
The `order_time_in_force` parameter contains a dict with entry and exit time in force policy values.
|
|
||||||
This can be set in the configuration file or in the strategy.
|
This can be set in the configuration file or in the strategy.
|
||||||
Values set in the configuration file overwrites values set in the strategy.
|
Values set in the configuration file overwrites values set in the strategy.
|
||||||
|
|
||||||
The possible values are: `GTC` (default), `FOK` or `IOC`.
|
The possible values are: `gtc` (default), `fok` or `ioc`.
|
||||||
|
|
||||||
``` python
|
``` python
|
||||||
"order_time_in_force": {
|
"order_time_in_force": {
|
||||||
"entry": "GTC",
|
"entry": "gtc",
|
||||||
"exit": "GTC"
|
"exit": "gtc"
|
||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! Warning
|
!!! Warning
|
||||||
This is ongoing work. For now, it is supported only for binance, gate and kucoin.
|
This is ongoing work. For now, it is supported only for binance and kucoin.
|
||||||
Please don't change the default value unless you know what you are doing and have researched the impact of using different values for your particular exchange.
|
Please don't change the default value unless you know what you are doing and have researched the impact of using different values for your particular exchange.
|
||||||
|
|
||||||
### Fiat conversion
|
### What values can be used for fiat_display_currency?
|
||||||
|
|
||||||
Freqtrade uses the Coingecko API to convert the coin value to it's corresponding fiat value for the Telegram reports.
|
|
||||||
The FIAT currency can be set in the configuration file as `fiat_display_currency`.
|
|
||||||
|
|
||||||
Removing `fiat_display_currency` completely from the configuration will skip initializing coingecko, and will not show any FIAT currency conversion. This has no importance for the correct functioning of the bot.
|
|
||||||
|
|
||||||
#### What values can be used for fiat_display_currency?
|
|
||||||
|
|
||||||
The `fiat_display_currency` configuration parameter sets the base currency to use for the
|
The `fiat_display_currency` configuration parameter sets the base currency to use for the
|
||||||
conversion from coin to fiat in the bot Telegram reports.
|
conversion from coin to fiat in the bot Telegram reports.
|
||||||
@@ -594,53 +558,9 @@ In addition to fiat currencies, a range of crypto currencies is supported.
|
|||||||
The valid values are:
|
The valid values are:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"BTC", "ETH", "XRP", "LTC", "BCH", "BNB"
|
"BTC", "ETH", "XRP", "LTC", "BCH", "USDT"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Coingecko Rate limit problems
|
|
||||||
|
|
||||||
On some IP ranges, coingecko is heavily rate-limiting.
|
|
||||||
In such cases, you may want to add your coingecko API key to the configuration.
|
|
||||||
|
|
||||||
``` json
|
|
||||||
{
|
|
||||||
"fiat_display_currency": "USD",
|
|
||||||
"coingecko": {
|
|
||||||
"api_key": "your-api",
|
|
||||||
"is_demo": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Freqtrade supports both Demo and Pro coingecko API keys.
|
|
||||||
|
|
||||||
The Coingecko API key is NOT required for the bot to function correctly.
|
|
||||||
It is only used for the conversion of coin to fiat in the Telegram reports, which usually also work without API key.
|
|
||||||
|
|
||||||
## Consuming exchange Websockets
|
|
||||||
|
|
||||||
Freqtrade can consume websockets through ccxt.pro.
|
|
||||||
|
|
||||||
Freqtrade aims ensure data is available at all times.
|
|
||||||
Should the websocket connection fail (or be disabled), the bot will fall back to REST API calls.
|
|
||||||
|
|
||||||
Should you experience problems you suspect are caused by websockets, you can disable these via the setting `exchange.enable_ws`, which defaults to true.
|
|
||||||
|
|
||||||
```jsonc
|
|
||||||
"exchange": {
|
|
||||||
// ...
|
|
||||||
"enable_ws": false,
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Should you be required to use a proxy, please refer to the [proxy section](#using-proxy-with-freqtrade) for more information.
|
|
||||||
|
|
||||||
!!! Info "Rollout"
|
|
||||||
We're implementing this out slowly, ensuring stability of your bots.
|
|
||||||
Currently, usage is limited to ohlcv data streams.
|
|
||||||
It's also limited to a few exchanges, with new exchanges being added on an ongoing basis.
|
|
||||||
|
|
||||||
## Using Dry-run mode
|
## Using Dry-run mode
|
||||||
|
|
||||||
We recommend starting the bot in the Dry-run mode to see how your bot will
|
We recommend starting the bot in the Dry-run mode to see how your bot will
|
||||||
@@ -660,7 +580,7 @@ creating trades on the exchange.
|
|||||||
|
|
||||||
```json
|
```json
|
||||||
"exchange": {
|
"exchange": {
|
||||||
"name": "binance",
|
"name": "bittrex",
|
||||||
"key": "key",
|
"key": "key",
|
||||||
"secret": "secret",
|
"secret": "secret",
|
||||||
...
|
...
|
||||||
@@ -677,9 +597,8 @@ Once you will be happy with your bot performance running in the Dry-run mode, yo
|
|||||||
* API-keys may or may not be provided. Only Read-Only operations (i.e. operations that do not alter account state) on the exchange are performed in dry-run mode.
|
* API-keys may or may not be provided. Only Read-Only operations (i.e. operations that do not alter account state) on the exchange are performed in dry-run mode.
|
||||||
* Wallets (`/balance`) are simulated based on `dry_run_wallet`.
|
* Wallets (`/balance`) are simulated based on `dry_run_wallet`.
|
||||||
* Orders are simulated, and will not be posted to the exchange.
|
* Orders are simulated, and will not be posted to the exchange.
|
||||||
* Market orders fill based on orderbook volume the moment the order is placed, with a maximum slippage of 5%.
|
* 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.
|
* Limit orders fill once the price reaches the defined level - or time out based on `unfilledtimeout` settings.
|
||||||
* Limit orders will be converted to market orders if they cross the price by more than 1%, and will be filled immediately based regular market order rules (see point about Market orders above).
|
|
||||||
* In combination with `stoploss_on_exchange`, the stop_loss price is assumed to be filled.
|
* 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 kept open after bot restarts, with the assumption that they were not filled while being offline.
|
* 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.
|
||||||
|
|
||||||
@@ -710,7 +629,7 @@ API Keys are usually only required for live trading (trading for real money, bot
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"exchange": {
|
"exchange": {
|
||||||
"name": "binance",
|
"name": "bittrex",
|
||||||
"key": "af8ddd35195e9dc500b9a6f799f6f5c93d89193b",
|
"key": "af8ddd35195e9dc500b9a6f799f6f5c93d89193b",
|
||||||
"secret": "08a9dc6db3d7b53e1acebd9275677f4b0a04f1a5",
|
"secret": "08a9dc6db3d7b53e1acebd9275677f4b0a04f1a5",
|
||||||
//"password": "", // Optional, not needed by all exchanges)
|
//"password": "", // Optional, not needed by all exchanges)
|
||||||
@@ -729,10 +648,19 @@ You should also make sure to read the [Exchanges](exchanges.md) section of the d
|
|||||||
|
|
||||||
**NEVER** share your private configuration file or your exchange keys with anyone!
|
**NEVER** share your private configuration file or your exchange keys with anyone!
|
||||||
|
|
||||||
## Using a proxy with Freqtrade
|
### Using proxy with Freqtrade
|
||||||
|
|
||||||
To use a proxy with freqtrade, export your proxy settings using the variables `"HTTP_PROXY"` and `"HTTPS_PROXY"` set to the appropriate values.
|
To use a proxy with freqtrade, add the kwarg `"aiohttp_trust_env"=true` to the `"ccxt_async_kwargs"` dict in the exchange section of the configuration.
|
||||||
This will have the proxy settings applied to everything (telegram, coingecko, ...) **except** for exchange requests.
|
|
||||||
|
An example for this can be found in `config_examples/config_full.example.json`
|
||||||
|
|
||||||
|
``` json
|
||||||
|
"ccxt_async_config": {
|
||||||
|
"aiohttp_trust_env": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, export your proxy settings using the variables `"HTTP_PROXY"` and `"HTTPS_PROXY"` set to the appropriate values
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
export HTTP_PROXY="http://addr:port"
|
export HTTP_PROXY="http://addr:port"
|
||||||
@@ -740,23 +668,6 @@ export HTTPS_PROXY="http://addr:port"
|
|||||||
freqtrade
|
freqtrade
|
||||||
```
|
```
|
||||||
|
|
||||||
### Proxy exchange requests
|
|
||||||
|
|
||||||
To use a proxy for exchange connections - you will have to define the proxies as part of the ccxt configuration.
|
|
||||||
|
|
||||||
``` json
|
|
||||||
{
|
|
||||||
"exchange": {
|
|
||||||
"ccxt_config": {
|
|
||||||
"httpsProxy": "http://addr:port",
|
|
||||||
"wsProxy": "http://addr:port",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
For more information on available proxy types, please consult the [ccxt proxy documentation](https://docs.ccxt.com/#/README?id=proxy).
|
|
||||||
|
|
||||||
## Next step
|
## Next step
|
||||||
|
|
||||||
Now you have configured your config.json, the next step is to [start your bot](bot-usage.md).
|
Now you have configured your config.json, the next step is to [start your bot](bot-usage.md).
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ You can analyze the results of backtests and trading history easily using Jupyte
|
|||||||
## Quick start with docker
|
## Quick start with docker
|
||||||
|
|
||||||
Freqtrade provides a docker-compose file which starts up a jupyter lab server.
|
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`.
|
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.
|
Please use the link that's printed in the console after startup for simplified login.
|
||||||
|
|
||||||
For more information, Please visit the [Data analysis with Docker](docker_quickstart.md#data-analysis-using-docker-compose) section.
|
For more information, Please visit the [Data analysis with Docker](docker_quickstart.md#data-analayis-using-docker-compose) section.
|
||||||
|
|
||||||
### Pro tips
|
### Pro tips
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ For this to work, first activate your virtual environment and run the following
|
|||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
# Activate virtual environment
|
# Activate virtual environment
|
||||||
source .venv/bin/activate
|
source .env/bin/activate
|
||||||
|
|
||||||
pip install ipykernel
|
pip install ipykernel
|
||||||
ipython kernel install --user --name=freqtrade
|
ipython kernel install --user --name=freqtrade
|
||||||
@@ -83,7 +83,7 @@ from pathlib import Path
|
|||||||
project_root = "somedir/freqtrade"
|
project_root = "somedir/freqtrade"
|
||||||
i=0
|
i=0
|
||||||
try:
|
try:
|
||||||
os.chdir(project_root)
|
os.chdirdir(project_root)
|
||||||
assert Path('LICENSE').is_file()
|
assert Path('LICENSE').is_file()
|
||||||
except:
|
except:
|
||||||
while i<4 and (not Path('LICENSE').is_file()):
|
while i<4 and (not Path('LICENSE').is_file()):
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ To download data (candles / OHLCV) needed for backtesting and hyperoptimization
|
|||||||
|
|
||||||
If no additional parameter is specified, freqtrade will download data for `"1m"` and `"5m"` timeframes for the last 30 days.
|
If no additional parameter is specified, freqtrade will download data for `"1m"` and `"5m"` timeframes for the last 30 days.
|
||||||
Exchange and pairs will come from `config.json` (if specified using `-c/--config`).
|
Exchange and pairs will come from `config.json` (if specified using `-c/--config`).
|
||||||
Without provided configuration, `--exchange` becomes mandatory.
|
Otherwise `--exchange` becomes mandatory.
|
||||||
|
|
||||||
You can use a relative timerange (`--days 20`) or an absolute starting point (`--timerange 20200101-`). For incremental downloads, the relative approach should be used.
|
You can use a relative timerange (`--days 20`) or an absolute starting point (`--timerange 20200101-`). For incremental downloads, the relative approach should be used.
|
||||||
|
|
||||||
@@ -24,20 +24,20 @@ usage: freqtrade download-data [-h] [-v] [--logfile FILE] [-V] [-c PATH]
|
|||||||
[--days INT] [--new-pairs-days INT]
|
[--days INT] [--new-pairs-days INT]
|
||||||
[--include-inactive-pairs]
|
[--include-inactive-pairs]
|
||||||
[--timerange TIMERANGE] [--dl-trades]
|
[--timerange TIMERANGE] [--dl-trades]
|
||||||
[--convert] [--exchange EXCHANGE]
|
[--exchange EXCHANGE]
|
||||||
[-t TIMEFRAMES [TIMEFRAMES ...]] [--erase]
|
[-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} ...]]
|
||||||
[--data-format-ohlcv {json,jsongz,hdf5,feather,parquet}]
|
[--erase]
|
||||||
[--data-format-trades {json,jsongz,hdf5,feather,parquet}]
|
[--data-format-ohlcv {json,jsongz,hdf5}]
|
||||||
|
[--data-format-trades {json,jsongz,hdf5}]
|
||||||
[--trading-mode {spot,margin,futures}]
|
[--trading-mode {spot,margin,futures}]
|
||||||
[--prepend]
|
[--prepend]
|
||||||
|
|
||||||
options:
|
optional arguments:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
-p PAIRS [PAIRS ...], --pairs PAIRS [PAIRS ...]
|
-p PAIRS [PAIRS ...], --pairs PAIRS [PAIRS ...]
|
||||||
Limit command to these pairs. Pairs are space-
|
Limit command to these pairs. Pairs are space-
|
||||||
separated.
|
separated.
|
||||||
--pairs-file FILE File containing a list of pairs. Takes precedence over
|
--pairs-file FILE File containing a list of pairs to download.
|
||||||
--pairs or pairs configured in the configuration.
|
|
||||||
--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`.
|
||||||
@@ -48,31 +48,26 @@ options:
|
|||||||
--dl-trades Download trades instead of OHLCV data. The bot will
|
--dl-trades Download trades instead of OHLCV data. The bot will
|
||||||
resample trades to the desired timeframe as specified
|
resample trades to the desired timeframe as specified
|
||||||
as --timeframes/-t.
|
as --timeframes/-t.
|
||||||
--convert Convert downloaded trades to OHLCV data. Only
|
--exchange EXCHANGE Exchange name (default: `bittrex`). Only valid if no
|
||||||
applicable in combination with `--dl-trades`. Will be
|
config is provided.
|
||||||
automatic for exchanges which don't have historic
|
-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} ...], --timeframes {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} ...]
|
||||||
OHLCV (e.g. Kraken). If not provided, use `trades-to-
|
|
||||||
ohlcv` to convert trades data to OHLCV data.
|
|
||||||
--exchange EXCHANGE Exchange name. Only valid if no config is provided.
|
|
||||||
-t TIMEFRAMES [TIMEFRAMES ...], --timeframes TIMEFRAMES [TIMEFRAMES ...]
|
|
||||||
Specify which tickers to download. Space-separated
|
Specify which tickers to download. Space-separated
|
||||||
list. Default: `1m 5m`.
|
list. Default: `1m 5m`.
|
||||||
--erase Clean all existing data for the selected
|
--erase Clean all existing data for the selected
|
||||||
exchange/pairs/timeframes.
|
exchange/pairs/timeframes.
|
||||||
--data-format-ohlcv {json,jsongz,hdf5,feather,parquet}
|
--data-format-ohlcv {json,jsongz,hdf5}
|
||||||
Storage format for downloaded candle (OHLCV) data.
|
Storage format for downloaded candle (OHLCV) data.
|
||||||
(default: `feather`).
|
(default: `json`).
|
||||||
--data-format-trades {json,jsongz,hdf5,feather,parquet}
|
--data-format-trades {json,jsongz,hdf5}
|
||||||
Storage format for downloaded trades data. (default:
|
Storage format for downloaded trades data. (default:
|
||||||
`feather`).
|
`jsongz`).
|
||||||
--trading-mode {spot,margin,futures}, --tradingmode {spot,margin,futures}
|
--trading-mode {spot,margin,futures}
|
||||||
Select Trading mode
|
Select Trading mode
|
||||||
--prepend Allow data prepending. (Data-appending is disabled)
|
--prepend Allow data prepending.
|
||||||
|
|
||||||
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).
|
||||||
--logfile FILE, --log-file FILE
|
--logfile FILE Log to the file specified. Special values are:
|
||||||
Log to the file specified. Special values are:
|
|
||||||
'syslog', 'journald'. See the documentation for more
|
'syslog', 'journald'. See the documentation for more
|
||||||
details.
|
details.
|
||||||
-V, --version show program's version number and exit
|
-V, --version show program's version number and exit
|
||||||
@@ -81,150 +76,25 @@ Common arguments:
|
|||||||
`userdir/config.json` or `config.json` whichever
|
`userdir/config.json` or `config.json` whichever
|
||||||
exists). Multiple --config options may be used. Can be
|
exists). Multiple --config options may be used. Can be
|
||||||
set to `-` to read config from stdin.
|
set to `-` to read config from stdin.
|
||||||
-d PATH, --datadir PATH, --data-dir PATH
|
-d PATH, --datadir PATH
|
||||||
Path to directory with historical backtesting data.
|
Path to directory with historical backtesting data.
|
||||||
--userdir PATH, --user-data-dir PATH
|
--userdir PATH, --user-data-dir PATH
|
||||||
Path to userdata directory.
|
Path to userdata directory.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! Tip "Downloading all data for one quote currency"
|
|
||||||
Often, you'll want to download data for all pairs of a specific quote-currency. In such cases, you can use the following shorthand:
|
|
||||||
`freqtrade download-data --exchange binance --pairs .*/USDT <...>`. The provided "pairs" string will be expanded to contain all active pairs on the exchange.
|
|
||||||
To also download data for inactive (delisted) pairs, add `--include-inactive-pairs` to the command.
|
|
||||||
|
|
||||||
!!! Note "Startup period"
|
!!! Note "Startup period"
|
||||||
`download-data` is a strategy-independent command. The idea is to download a big chunk of data once, and then iteratively increase the amount of data stored.
|
`download-data` is a strategy-independent command. The idea is to download a big chunk of data once, and then iteratively increase the amount of data stored.
|
||||||
|
|
||||||
For that reason, `download-data` does not care about the "startup-period" defined in a strategy. It's up to the user to download additional days if the backtest should start at a specific point in time (while respecting startup period).
|
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).
|
||||||
|
|
||||||
### Start download
|
|
||||||
|
|
||||||
A very simple command (assuming an available `config.json` file) can look as follows.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
freqtrade download-data --exchange binance
|
|
||||||
```
|
|
||||||
|
|
||||||
This will download historical candle (OHLCV) data for all the currency pairs defined in the configuration.
|
|
||||||
|
|
||||||
Alternatively, specify the pairs directly
|
|
||||||
|
|
||||||
```bash
|
|
||||||
freqtrade download-data --exchange binance --pairs ETH/USDT XRP/USDT BTC/USDT
|
|
||||||
```
|
|
||||||
|
|
||||||
or as regex (in this case, to download all active USDT pairs)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
freqtrade download-data --exchange binance --pairs .*/USDT
|
|
||||||
```
|
|
||||||
|
|
||||||
### Other Notes
|
|
||||||
|
|
||||||
* To use a different directory than the exchange specific default, use `--datadir user_data/data/some_directory`.
|
|
||||||
* To change the exchange used to download the historical data from, please use a different configuration file (you'll probably need to adjust rate limits etc.)
|
|
||||||
* To use `pairs.json` from some other directory, use `--pairs-file some_other_dir/pairs.json`.
|
|
||||||
* To download historical candle (OHLCV) data for only 10 days, use `--days 10` (defaults to 30 days).
|
|
||||||
* To download historical candle (OHLCV) data from a fixed starting point, use `--timerange 20200101-` - which will download all data from January 1st, 2020.
|
|
||||||
* Use `--timeframes` to specify what timeframe download the historical candle (OHLCV) data for. Default is `--timeframes 1m 5m` which will download 1-minute and 5-minute data.
|
|
||||||
* To use exchange, timeframe and list of pairs as defined in your configuration file, use the `-c/--config` option. With this, the script uses the whitelist defined in the config as the list of currency pairs to download data for and does not require the pairs.json file. You can combine `-c/--config` with most other options.
|
|
||||||
|
|
||||||
??? Note "Permission denied errors"
|
|
||||||
If your configuration directory `user_data` was made by docker, you may get the following error:
|
|
||||||
|
|
||||||
```
|
|
||||||
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
|
|
||||||
```
|
|
||||||
|
|
||||||
### 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
|
|
||||||
|
|
||||||
Freqtrade currently supports the following data-formats:
|
|
||||||
|
|
||||||
* `feather` - a dataformat based on Apache Arrow
|
|
||||||
* `json` - plain "text" json files
|
|
||||||
* `jsongz` - a gzip-zipped version of json files
|
|
||||||
* `hdf5` - a high performance datastore
|
|
||||||
* `parquet` - columnar datastore (OHLCV only)
|
|
||||||
|
|
||||||
By default, both OHLCV data and trades data are stored in the `feather` format.
|
|
||||||
|
|
||||||
This can be changed via the `--data-format-ohlcv` and `--data-format-trades` command line arguments respectively.
|
|
||||||
To persist this change, you should also add the following snippet to your configuration, so you don't have to insert the above arguments each time:
|
|
||||||
|
|
||||||
``` jsonc
|
|
||||||
// ...
|
|
||||||
"dataformat_ohlcv": "hdf5",
|
|
||||||
"dataformat_trades": "hdf5",
|
|
||||||
// ...
|
|
||||||
```
|
|
||||||
|
|
||||||
If the default data-format has been changed during download, then the keys `dataformat_ohlcv` and `dataformat_trades` in the configuration file need to be adjusted to the selected dataformat as well.
|
|
||||||
|
|
||||||
!!! Note
|
|
||||||
You can convert between data-formats using the [convert-data](#sub-command-convert-data) and [convert-trade-data](#sub-command-convert-trade-data) methods.
|
|
||||||
|
|
||||||
#### Dataformat comparison
|
|
||||||
|
|
||||||
The following comparisons have been made with the following data, and by using the linux `time` command.
|
|
||||||
|
|
||||||
```
|
|
||||||
Found 6 pair / timeframe combinations.
|
|
||||||
+----------+-------------+--------+---------------------+---------------------+
|
|
||||||
| Pair | Timeframe | Type | From | To |
|
|
||||||
|----------+-------------+--------+---------------------+---------------------|
|
|
||||||
| BTC/USDT | 5m | spot | 2017-08-17 04:00:00 | 2022-09-13 19:25:00 |
|
|
||||||
| ETH/USDT | 1m | spot | 2017-08-17 04:00:00 | 2022-09-13 19:26:00 |
|
|
||||||
| BTC/USDT | 1m | spot | 2017-08-17 04:00:00 | 2022-09-13 19:30:00 |
|
|
||||||
| XRP/USDT | 5m | spot | 2018-05-04 08:10:00 | 2022-09-13 19:15:00 |
|
|
||||||
| XRP/USDT | 1m | spot | 2018-05-04 08:11:00 | 2022-09-13 19:22:00 |
|
|
||||||
| ETH/USDT | 5m | spot | 2017-08-17 04:00:00 | 2022-09-13 19:20:00 |
|
|
||||||
+----------+-------------+--------+---------------------+---------------------+
|
|
||||||
```
|
|
||||||
|
|
||||||
Timings have been taken in a not very scientific way with the following command, which forces reading the data into memory.
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
time freqtrade list-data --show-timerange --data-format-ohlcv <dataformat>
|
|
||||||
```
|
|
||||||
|
|
||||||
| Format | Size | timing |
|
|
||||||
|------------|-------------|-------------|
|
|
||||||
| `feather` | 72Mb | 3.5s |
|
|
||||||
| `json` | 149Mb | 25.6s |
|
|
||||||
| `jsongz` | 39Mb | 27s |
|
|
||||||
| `hdf5` | 145Mb | 3.9s |
|
|
||||||
| `parquet` | 83Mb | 3.8s |
|
|
||||||
|
|
||||||
Size has been taken from the BTC/USDT 1m spot combination for the timerange specified above.
|
|
||||||
|
|
||||||
To have a best performance/size mix, we recommend using the default feather format, or parquet.
|
|
||||||
|
|
||||||
### Pairs file
|
### Pairs file
|
||||||
|
|
||||||
In alternative to the whitelist from `config.json`, a `pairs.json` file can be used.
|
In alternative to the whitelist from `config.json`, a `pairs.json` file can be used.
|
||||||
If you are using Binance for example:
|
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.
|
- 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.
|
- update the `pairs.json` file to contain the currency pairs you are interested in.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mkdir -p user_data/data/binance
|
mkdir -p user_data/data/binance
|
||||||
@@ -243,48 +113,130 @@ Mixing different stake-currencies is allowed for this file, since it's only used
|
|||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! Note
|
!!! Tip "Downloading all data for one quote currency"
|
||||||
The `pairs.json` file is only used when no configuration is loaded (implicitly by naming, or via `--config` flag).
|
Often, you'll want to download data for all pairs of a specific quote-currency. In such cases, you can use the following shorthand:
|
||||||
You can force the usage of this file via `--pairs-file pairs.json` - however we recommend to use the pairlist from within the configuration, either via `exchange.pair_whitelist` or `pairs` setting in the configuration.
|
`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.
|
||||||
|
|
||||||
## Sub-command convert data
|
??? 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.
|
||||||
|
- 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
|
||||||
|
|
||||||
|
Freqtrade currently supports 3 data-formats for both OHLCV and trades data:
|
||||||
|
|
||||||
|
* `json` (plain "text" json files)
|
||||||
|
* `jsongz` (a gzip-zipped version of json files)
|
||||||
|
* `hdf5` (a high performance datastore)
|
||||||
|
|
||||||
|
By default, OHLCV data is stored as `json` data, while trades data is stored as `jsongz` data.
|
||||||
|
|
||||||
|
This can be changed via the `--data-format-ohlcv` and `--data-format-trades` command line arguments respectively.
|
||||||
|
To persist this change, you can should also add the following snippet to your configuration, so you don't have to insert the above arguments each time:
|
||||||
|
|
||||||
|
``` jsonc
|
||||||
|
// ...
|
||||||
|
"dataformat_ohlcv": "hdf5",
|
||||||
|
"dataformat_trades": "hdf5",
|
||||||
|
// ...
|
||||||
|
```
|
||||||
|
|
||||||
|
If the default data-format has been changed during download, then the keys `dataformat_ohlcv` and `dataformat_trades` in the configuration file need to be adjusted to the selected dataformat as well.
|
||||||
|
|
||||||
|
!!! Note
|
||||||
|
You can convert between data-formats using the [convert-data](#sub-command-convert-data) and [convert-trade-data](#sub-command-convert-trade-data) methods.
|
||||||
|
|
||||||
|
#### Sub-command convert data
|
||||||
|
|
||||||
```
|
```
|
||||||
usage: freqtrade convert-data [-h] [-v] [--logfile FILE] [-V] [-c PATH]
|
usage: freqtrade convert-data [-h] [-v] [--logfile FILE] [-V] [-c PATH]
|
||||||
[-d PATH] [--userdir PATH]
|
[-d PATH] [--userdir PATH]
|
||||||
[-p PAIRS [PAIRS ...]] --format-from
|
[-p PAIRS [PAIRS ...]] --format-from
|
||||||
{json,jsongz,hdf5,feather,parquet} --format-to
|
{json,jsongz,hdf5} --format-to
|
||||||
{json,jsongz,hdf5,feather,parquet} [--erase]
|
{json,jsongz,hdf5} [--erase]
|
||||||
|
[-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} ...]]
|
||||||
[--exchange EXCHANGE]
|
[--exchange EXCHANGE]
|
||||||
[-t TIMEFRAMES [TIMEFRAMES ...]]
|
|
||||||
[--trading-mode {spot,margin,futures}]
|
[--trading-mode {spot,margin,futures}]
|
||||||
[--candle-types {spot,futures,mark,index,premiumIndex,funding_rate} [{spot,futures,mark,index,premiumIndex,funding_rate} ...]]
|
[--candle-types {spot,,futures,mark,index,premiumIndex,funding_rate} [{spot,,futures,mark,index,premiumIndex,funding_rate} ...]]
|
||||||
|
|
||||||
options:
|
optional arguments:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
-p PAIRS [PAIRS ...], --pairs PAIRS [PAIRS ...]
|
-p PAIRS [PAIRS ...], --pairs PAIRS [PAIRS ...]
|
||||||
Limit command to these pairs. Pairs are space-
|
Limit command to these pairs. Pairs are space-
|
||||||
separated.
|
separated.
|
||||||
--format-from {json,jsongz,hdf5,feather,parquet}
|
--format-from {json,jsongz,hdf5}
|
||||||
Source format for data conversion.
|
Source format for data conversion.
|
||||||
--format-to {json,jsongz,hdf5,feather,parquet}
|
--format-to {json,jsongz,hdf5}
|
||||||
Destination format for data conversion.
|
Destination format for data conversion.
|
||||||
--erase Clean all existing data for the selected
|
--erase Clean all existing data for the selected
|
||||||
exchange/pairs/timeframes.
|
exchange/pairs/timeframes.
|
||||||
--exchange EXCHANGE Exchange name. Only valid if no config is provided.
|
-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} ...], --timeframes {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 TIMEFRAMES [TIMEFRAMES ...], --timeframes TIMEFRAMES [TIMEFRAMES ...]
|
|
||||||
Specify which tickers to download. Space-separated
|
Specify which tickers to download. Space-separated
|
||||||
list. Default: `1m 5m`.
|
list. Default: `1m 5m`.
|
||||||
--trading-mode {spot,margin,futures}, --tradingmode {spot,margin,futures}
|
--exchange EXCHANGE Exchange name (default: `bittrex`). Only valid if no
|
||||||
|
config is provided.
|
||||||
|
--trading-mode {spot,margin,futures}
|
||||||
Select Trading mode
|
Select Trading mode
|
||||||
--candle-types {spot,futures,mark,index,premiumIndex,funding_rate} [{spot,futures,mark,index,premiumIndex,funding_rate} ...]
|
--candle-types {spot,,futures,mark,index,premiumIndex,funding_rate} [{spot,,futures,mark,index,premiumIndex,funding_rate} ...]
|
||||||
Select candle type to convert. Defaults to all
|
Select candle type to use
|
||||||
available types.
|
|
||||||
|
|
||||||
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).
|
||||||
--logfile FILE, --log-file FILE
|
--logfile FILE Log to the file specified. Special values are:
|
||||||
Log to the file specified. Special values are:
|
|
||||||
'syslog', 'journald'. See the documentation for more
|
'syslog', 'journald'. See the documentation for more
|
||||||
details.
|
details.
|
||||||
-V, --version show program's version number and exit
|
-V, --version show program's version number and exit
|
||||||
@@ -293,13 +245,14 @@ Common arguments:
|
|||||||
`userdir/config.json` or `config.json` whichever
|
`userdir/config.json` or `config.json` whichever
|
||||||
exists). Multiple --config options may be used. Can be
|
exists). Multiple --config options may be used. Can be
|
||||||
set to `-` to read config from stdin.
|
set to `-` to read config from stdin.
|
||||||
-d PATH, --datadir PATH, --data-dir PATH
|
-d PATH, --datadir PATH
|
||||||
Path to directory with historical backtesting data.
|
Path to directory with historical backtesting data.
|
||||||
--userdir PATH, --user-data-dir PATH
|
--userdir PATH, --user-data-dir PATH
|
||||||
Path to userdata directory.
|
Path to userdata directory.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example converting data
|
##### Example converting data
|
||||||
|
|
||||||
The following command will convert all candle (OHLCV) data available in `~/.freqtrade/data/binance` from json to jsongz, saving diskspace in the process.
|
The following command will convert all candle (OHLCV) data available in `~/.freqtrade/data/binance` from json to jsongz, saving diskspace in the process.
|
||||||
It'll also remove original json data files (`--erase` parameter).
|
It'll also remove original json data files (`--erase` parameter).
|
||||||
@@ -308,34 +261,30 @@ It'll also remove original json data files (`--erase` parameter).
|
|||||||
freqtrade convert-data --format-from json --format-to jsongz --datadir ~/.freqtrade/data/binance -t 5m 15m --erase
|
freqtrade convert-data --format-from json --format-to jsongz --datadir ~/.freqtrade/data/binance -t 5m 15m --erase
|
||||||
```
|
```
|
||||||
|
|
||||||
## Sub-command convert trade data
|
#### Sub-command convert trade data
|
||||||
|
|
||||||
```
|
```
|
||||||
usage: freqtrade convert-trade-data [-h] [-v] [--logfile FILE] [-V] [-c PATH]
|
usage: freqtrade convert-trade-data [-h] [-v] [--logfile FILE] [-V] [-c PATH]
|
||||||
[-d PATH] [--userdir PATH]
|
[-d PATH] [--userdir PATH]
|
||||||
[-p PAIRS [PAIRS ...]] --format-from
|
[-p PAIRS [PAIRS ...]] --format-from
|
||||||
{json,jsongz,hdf5,feather,parquet}
|
{json,jsongz,hdf5} --format-to
|
||||||
--format-to
|
{json,jsongz,hdf5} [--erase]
|
||||||
{json,jsongz,hdf5,feather,parquet}
|
|
||||||
[--erase] [--exchange EXCHANGE]
|
|
||||||
|
|
||||||
options:
|
optional arguments:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
-p PAIRS [PAIRS ...], --pairs PAIRS [PAIRS ...]
|
-p PAIRS [PAIRS ...], --pairs PAIRS [PAIRS ...]
|
||||||
Limit command to these pairs. Pairs are space-
|
Show profits for only these pairs. Pairs are space-
|
||||||
separated.
|
separated.
|
||||||
--format-from {json,jsongz,hdf5,feather,parquet}
|
--format-from {json,jsongz,hdf5}
|
||||||
Source format for data conversion.
|
Source format for data conversion.
|
||||||
--format-to {json,jsongz,hdf5,feather,parquet}
|
--format-to {json,jsongz,hdf5}
|
||||||
Destination format for data conversion.
|
Destination format for data conversion.
|
||||||
--erase Clean all existing data for the selected
|
--erase Clean all existing data for the selected
|
||||||
exchange/pairs/timeframes.
|
exchange/pairs/timeframes.
|
||||||
--exchange EXCHANGE Exchange name. Only valid if no config is provided.
|
|
||||||
|
|
||||||
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).
|
||||||
--logfile FILE, --log-file FILE
|
--logfile FILE Log to the file specified. Special values are:
|
||||||
Log to the file specified. Special values are:
|
|
||||||
'syslog', 'journald'. See the documentation for more
|
'syslog', 'journald'. See the documentation for more
|
||||||
details.
|
details.
|
||||||
-V, --version show program's version number and exit
|
-V, --version show program's version number and exit
|
||||||
@@ -344,14 +293,14 @@ Common arguments:
|
|||||||
`userdir/config.json` or `config.json` whichever
|
`userdir/config.json` or `config.json` whichever
|
||||||
exists). Multiple --config options may be used. Can be
|
exists). Multiple --config options may be used. Can be
|
||||||
set to `-` to read config from stdin.
|
set to `-` to read config from stdin.
|
||||||
-d PATH, --datadir PATH, --data-dir PATH
|
-d PATH, --datadir PATH
|
||||||
Path to directory with historical backtesting data.
|
Path to directory with historical backtesting data.
|
||||||
--userdir PATH, --user-data-dir PATH
|
--userdir PATH, --user-data-dir PATH
|
||||||
Path to userdata directory.
|
Path to userdata directory.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example converting trades
|
##### Example converting trades
|
||||||
|
|
||||||
The following command will convert all available trade-data in `~/.freqtrade/data/kraken` from jsongz to json.
|
The following command will convert all available trade-data in `~/.freqtrade/data/kraken` from jsongz to json.
|
||||||
It'll also remove original jsongz data files (`--erase` parameter).
|
It'll also remove original jsongz data files (`--erase` parameter).
|
||||||
@@ -360,7 +309,7 @@ It'll also remove original jsongz data files (`--erase` parameter).
|
|||||||
freqtrade convert-trade-data --format-from jsongz --format-to json --datadir ~/.freqtrade/data/kraken --erase
|
freqtrade convert-trade-data --format-from jsongz --format-to json --datadir ~/.freqtrade/data/kraken --erase
|
||||||
```
|
```
|
||||||
|
|
||||||
## Sub-command trades to ohlcv
|
### Sub-command trades to ohlcv
|
||||||
|
|
||||||
When you need to use `--dl-trades` (kraken only) to download data, conversion of trades data to ohlcv data is the last step.
|
When you need to use `--dl-trades` (kraken only) to download data, conversion of trades data to ohlcv data is the last step.
|
||||||
This command will allow you to repeat this last step for additional timeframes without re-downloading the data.
|
This command will allow you to repeat this last step for additional timeframes without re-downloading the data.
|
||||||
@@ -369,31 +318,31 @@ This command will allow you to repeat this last step for additional timeframes w
|
|||||||
usage: freqtrade trades-to-ohlcv [-h] [-v] [--logfile FILE] [-V] [-c PATH]
|
usage: freqtrade trades-to-ohlcv [-h] [-v] [--logfile FILE] [-V] [-c PATH]
|
||||||
[-d PATH] [--userdir PATH]
|
[-d PATH] [--userdir PATH]
|
||||||
[-p PAIRS [PAIRS ...]]
|
[-p PAIRS [PAIRS ...]]
|
||||||
[-t TIMEFRAMES [TIMEFRAMES ...]]
|
[-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} ...]]
|
||||||
[--exchange EXCHANGE]
|
[--exchange EXCHANGE]
|
||||||
[--data-format-ohlcv {json,jsongz,hdf5,feather,parquet}]
|
[--data-format-ohlcv {json,jsongz,hdf5}]
|
||||||
[--data-format-trades {json,jsongz,hdf5,feather}]
|
[--data-format-trades {json,jsongz,hdf5}]
|
||||||
|
|
||||||
options:
|
optional arguments:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
-p PAIRS [PAIRS ...], --pairs PAIRS [PAIRS ...]
|
-p PAIRS [PAIRS ...], --pairs PAIRS [PAIRS ...]
|
||||||
Limit command to these pairs. Pairs are space-
|
Limit command to these pairs. Pairs are space-
|
||||||
separated.
|
separated.
|
||||||
-t TIMEFRAMES [TIMEFRAMES ...], --timeframes TIMEFRAMES [TIMEFRAMES ...]
|
-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} ...], --timeframes {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} ...]
|
||||||
Specify which tickers to download. Space-separated
|
Specify which tickers to download. Space-separated
|
||||||
list. Default: `1m 5m`.
|
list. Default: `1m 5m`.
|
||||||
--exchange EXCHANGE Exchange name. Only valid if no config is provided.
|
--exchange EXCHANGE Exchange name (default: `bittrex`). Only valid if no
|
||||||
--data-format-ohlcv {json,jsongz,hdf5,feather,parquet}
|
config is provided.
|
||||||
|
--data-format-ohlcv {json,jsongz,hdf5}
|
||||||
Storage format for downloaded candle (OHLCV) data.
|
Storage format for downloaded candle (OHLCV) data.
|
||||||
(default: `feather`).
|
(default: `json`).
|
||||||
--data-format-trades {json,jsongz,hdf5,feather}
|
--data-format-trades {json,jsongz,hdf5}
|
||||||
Storage format for downloaded trades data. (default:
|
Storage format for downloaded trades data. (default:
|
||||||
`feather`).
|
`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).
|
||||||
--logfile FILE, --log-file FILE
|
--logfile FILE Log to the file specified. Special values are:
|
||||||
Log to the file specified. Special values are:
|
|
||||||
'syslog', 'journald'. See the documentation for more
|
'syslog', 'journald'. See the documentation for more
|
||||||
details.
|
details.
|
||||||
-V, --version show program's version number and exit
|
-V, --version show program's version number and exit
|
||||||
@@ -402,49 +351,46 @@ Common arguments:
|
|||||||
`userdir/config.json` or `config.json` whichever
|
`userdir/config.json` or `config.json` whichever
|
||||||
exists). Multiple --config options may be used. Can be
|
exists). Multiple --config options may be used. Can be
|
||||||
set to `-` to read config from stdin.
|
set to `-` to read config from stdin.
|
||||||
-d PATH, --datadir PATH, --data-dir PATH
|
-d PATH, --datadir PATH
|
||||||
Path to directory with historical backtesting data.
|
Path to directory with historical backtesting data.
|
||||||
--userdir PATH, --user-data-dir PATH
|
--userdir PATH, --user-data-dir PATH
|
||||||
Path to userdata directory.
|
Path to userdata directory.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example trade-to-ohlcv conversion
|
#### Example trade-to-ohlcv conversion
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
freqtrade trades-to-ohlcv --exchange kraken -t 5m 1h 1d --pairs BTC/EUR ETH/EUR
|
freqtrade trades-to-ohlcv --exchange kraken -t 5m 1h 1d --pairs BTC/EUR ETH/EUR
|
||||||
```
|
```
|
||||||
|
|
||||||
## Sub-command list-data
|
### Sub-command list-data
|
||||||
|
|
||||||
You can get a list of downloaded data using the `list-data` sub-command.
|
You can get a list of downloaded data using the `list-data` sub-command.
|
||||||
|
|
||||||
```
|
```
|
||||||
usage: freqtrade list-data [-h] [-v] [--logfile FILE] [-V] [-c PATH] [-d PATH]
|
usage: freqtrade list-data [-h] [-v] [--logfile FILE] [-V] [-c PATH] [-d PATH]
|
||||||
[--userdir PATH] [--exchange EXCHANGE]
|
[--userdir PATH] [--exchange EXCHANGE]
|
||||||
[--data-format-ohlcv {json,jsongz,hdf5,feather,parquet}]
|
[--data-format-ohlcv {json,jsongz,hdf5}]
|
||||||
[-p PAIRS [PAIRS ...]]
|
[-p PAIRS [PAIRS ...]]
|
||||||
[--trading-mode {spot,margin,futures}]
|
[--trading-mode {spot,margin,futures}]
|
||||||
[--show-timerange]
|
|
||||||
|
|
||||||
options:
|
optional arguments:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
--exchange EXCHANGE Exchange name. Only valid if no config is provided.
|
--exchange EXCHANGE Exchange name (default: `bittrex`). Only valid if no
|
||||||
--data-format-ohlcv {json,jsongz,hdf5,feather,parquet}
|
config is provided.
|
||||||
|
--data-format-ohlcv {json,jsongz,hdf5}
|
||||||
Storage format for downloaded candle (OHLCV) data.
|
Storage format for downloaded candle (OHLCV) data.
|
||||||
(default: `feather`).
|
(default: `json`).
|
||||||
-p PAIRS [PAIRS ...], --pairs PAIRS [PAIRS ...]
|
-p PAIRS [PAIRS ...], --pairs PAIRS [PAIRS ...]
|
||||||
Limit command to these pairs. Pairs are space-
|
Limit command to these pairs. Pairs are space-
|
||||||
separated.
|
separated.
|
||||||
--trading-mode {spot,margin,futures}, --tradingmode {spot,margin,futures}
|
--trading-mode {spot,margin,futures}
|
||||||
Select Trading mode
|
Select Trading mode
|
||||||
--show-timerange Show timerange available for available data. (May take
|
|
||||||
a while to calculate).
|
|
||||||
|
|
||||||
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).
|
||||||
--logfile FILE, --log-file FILE
|
--logfile FILE Log to the file specified. Special values are:
|
||||||
Log to the file specified. Special values are:
|
|
||||||
'syslog', 'journald'. See the documentation for more
|
'syslog', 'journald'. See the documentation for more
|
||||||
details.
|
details.
|
||||||
-V, --version show program's version number and exit
|
-V, --version show program's version number and exit
|
||||||
@@ -453,14 +399,14 @@ Common arguments:
|
|||||||
`userdir/config.json` or `config.json` whichever
|
`userdir/config.json` or `config.json` whichever
|
||||||
exists). Multiple --config options may be used. Can be
|
exists). Multiple --config options may be used. Can be
|
||||||
set to `-` to read config from stdin.
|
set to `-` to read config from stdin.
|
||||||
-d PATH, --datadir PATH, --data-dir PATH
|
-d PATH, --datadir PATH
|
||||||
Path to directory with historical backtesting data.
|
Path to directory with historical backtesting data.
|
||||||
--userdir PATH, --user-data-dir PATH
|
--userdir PATH, --user-data-dir PATH
|
||||||
Path to userdata directory.
|
Path to userdata directory.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example list-data
|
#### Example list-data
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
> freqtrade list-data --userdir ~/.freqtrade/user_data/
|
> freqtrade list-data --userdir ~/.freqtrade/user_data/
|
||||||
@@ -474,22 +420,17 @@ 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
|
||||||
```
|
```
|
||||||
|
|
||||||
## Trades (tick) data
|
### Trades (tick) data
|
||||||
|
|
||||||
By default, `download-data` sub-command downloads Candles (OHLCV) data. Most 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.
|
||||||
This data can be useful if you need many different timeframes, since it is only downloaded once, and then resampled locally to the desired timeframes.
|
This data can be useful if you need many different timeframes, since it is only downloaded once, and then resampled locally to the desired timeframes.
|
||||||
|
|
||||||
Since this data is large by default, the files use the feather file format by default. They are stored in your data-directory with the naming convention of `<pair>-trades.feather` (`ETH_BTC-trades.feather`). Incremental mode is also supported, as for historic OHLCV data, so downloading the data once per week with `--days 8` will create an incremental data-repository.
|
Since this data is large by default, the files use gzip by default. They are stored in your data-directory with the naming convention of `<pair>-trades.json.gz` (`ETH_BTC-trades.json.gz`). Incremental mode is also supported, as for historic OHLCV data, so downloading the data once per week with `--days 8` will create an incremental data-repository.
|
||||||
|
|
||||||
To use this mode, simply add `--dl-trades` to your call. This will swap the download method to download trades.
|
To use this mode, simply add `--dl-trades` to your call. This will swap the download method to download trades, and resamples the data locally.
|
||||||
If `--convert` is also provided, the resample step will happen automatically and overwrite eventually existing OHLCV data for the given pair/timeframe combinations.
|
|
||||||
|
|
||||||
!!! Warning "Do not use"
|
!!! Warning "do not use"
|
||||||
You should not use this unless you're a kraken user (Kraken does not provide historic OHLCV data).
|
You should not use this unless you're a kraken user. Most other exchanges provide OHLCV data with sufficient history.
|
||||||
Most other exchanges provide OHLCV data with sufficient history, so downloading multiple timeframes through that method will still proof to be a lot faster than downloading trades data.
|
|
||||||
|
|
||||||
!!! Note "Kraken user"
|
|
||||||
Kraken users should read [this](exchanges.md#historic-kraken-data) before starting to download data.
|
|
||||||
|
|
||||||
Example call:
|
Example call:
|
||||||
|
|
||||||
@@ -500,6 +441,12 @@ freqtrade download-data --exchange kraken --pairs XRP/EUR ETH/EUR --days 20 --dl
|
|||||||
!!! Note
|
!!! Note
|
||||||
While this method uses async calls, it will be slow, since it requires the result of the previous call to generate the next request to the exchange.
|
While this method uses async calls, it will be slow, since it requires the result of the previous call to generate the next request to the exchange.
|
||||||
|
|
||||||
|
!!! Warning
|
||||||
|
The historic trades are not available during Freqtrade dry-run and live trade modes because all exchanges tested provide this data with a delay of few 100 candles, so it's not suitable for real-time trading.
|
||||||
|
|
||||||
|
!!! Note "Kraken user"
|
||||||
|
Kraken users should read [this](exchanges.md#historic-kraken-data) before starting to download data.
|
||||||
|
|
||||||
## Next step
|
## Next step
|
||||||
|
|
||||||
Great, you now have some data downloaded, so you can now start [backtesting](backtesting.md) your strategy.
|
Great, you now have backtest data downloaded, so you can now start [backtesting](backtesting.md) your strategy.
|
||||||
|
|||||||
@@ -66,16 +66,11 @@ We will keep a compatibility layer for 1-2 versions (so both `buy_tag` and `ente
|
|||||||
|
|
||||||
#### Naming changes
|
#### Naming changes
|
||||||
|
|
||||||
Webhook terminology changed from "sell" to "exit", and from "buy" to "entry", removing "webhook" in the process.
|
Webhook terminology changed from "sell" to "exit", and from "buy" to "entry".
|
||||||
|
|
||||||
* `webhookbuy`, `webhookentry` -> `entry`
|
* `webhookbuy` -> `webhookentry`
|
||||||
* `webhookbuyfill`, `webhookentryfill` -> `entry_fill`
|
* `webhookbuyfill` -> `webhookentryfill`
|
||||||
* `webhookbuycancel`, `webhookentrycancel` -> `entry_cancel`
|
* `webhookbuycancel` -> `webhookentrycancel`
|
||||||
* `webhooksell`, `webhookexit` -> `exit`
|
* `webhooksell` -> `webhookexit`
|
||||||
* `webhooksellfill`, `webhookexitfill` -> `exit_fill`
|
* `webhooksellfill` -> `webhookexitfill`
|
||||||
* `webhooksellcancel`, `webhookexitcancel` -> `exit_cancel`
|
* `webhooksellcancel` -> `webhookexitcancel`
|
||||||
|
|
||||||
|
|
||||||
## Removal of `populate_any_indicators`
|
|
||||||
|
|
||||||
version 2023.3 saw the removal of `populate_any_indicators` in favor of split methods for feature engineering and targets. Please read the [migration document](strategy_migration.md#freqai-strategy) for full details.
|
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ This will spin up a local server (usually on port 8000) so you can see if everyt
|
|||||||
## Developer setup
|
## Developer setup
|
||||||
|
|
||||||
To configure a development environment, you can either use the provided [DevContainer](#devcontainer-setup), or use the `setup.sh` script and answer "y" when asked "Do you want to install dependencies for dev [y/N]? ".
|
To configure a development environment, you can either use the provided [DevContainer](#devcontainer-setup), or use the `setup.sh` script and answer "y" when asked "Do you want to install dependencies for dev [y/N]? ".
|
||||||
Alternatively (e.g. if your system is not supported by the setup.sh script), follow the manual installation process and run `pip3 install -r requirements-dev.txt` - followed by `pip3 install -e .[all]`.
|
Alternatively (e.g. if your system is not supported by the setup.sh script), follow the manual installation process and run `pip3 install -e .[all]`.
|
||||||
|
|
||||||
This will install all required tools for development, including `pytest`, `ruff`, `mypy`, and `coveralls`.
|
This will install all required tools for development, including `pytest`, `flake8`, `mypy`, and `coveralls`.
|
||||||
|
|
||||||
Then install the git hook scripts by running `pre-commit install`, so your changes will be verified locally before committing.
|
Then install the git hook scripts by running `pre-commit install`, so your changes will be verified locally before committing.
|
||||||
This avoids a lot of waiting for CI already, as some basic formatting checks are done locally on your machine.
|
This avoids a lot of waiting for CI already, as some basic formatting checks are done locally on your machine.
|
||||||
@@ -49,13 +49,6 @@ For more information about the [Remote container extension](https://code.visuals
|
|||||||
New code should be covered by basic unittests. Depending on the complexity of the feature, Reviewers may request more in-depth unittests.
|
New code should be covered by basic unittests. Depending on the complexity of the feature, Reviewers may request more in-depth unittests.
|
||||||
If necessary, the Freqtrade team can assist and give guidance with writing good tests (however please don't expect anyone to write the tests for you).
|
If necessary, the Freqtrade team can assist and give guidance with writing good tests (however please don't expect anyone to write the tests for you).
|
||||||
|
|
||||||
#### How to run tests
|
|
||||||
|
|
||||||
Use `pytest` in root folder to run all available testcases and confirm your local environment is setup correctly
|
|
||||||
|
|
||||||
!!! Note "feature branches"
|
|
||||||
Tests are expected to pass on the `develop` and `stable` branches. Other branches may be work in progress with tests not working yet.
|
|
||||||
|
|
||||||
#### Checking log content in tests
|
#### Checking log content in tests
|
||||||
|
|
||||||
Freqtrade uses 2 main methods to check log content in tests, `log_has()` and `log_has_re()` (to check using regex, in case of dynamic log-messages).
|
Freqtrade uses 2 main methods to check log content in tests, `log_has()` and `log_has_re()` (to check using regex, in case of dynamic log-messages).
|
||||||
@@ -77,13 +70,13 @@ def test_method_to_test(caplog):
|
|||||||
|
|
||||||
### Debug configuration
|
### Debug configuration
|
||||||
|
|
||||||
To debug freqtrade, we recommend VSCode (with the Python extension) with the following launch configuration (located in `.vscode/launch.json`).
|
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.
|
Details will obviously vary between setups - but this should work to get you started.
|
||||||
|
|
||||||
``` json
|
``` json
|
||||||
{
|
{
|
||||||
"name": "freqtrade trade",
|
"name": "freqtrade trade",
|
||||||
"type": "debugpy",
|
"type": "python",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"module": "freqtrade",
|
"module": "freqtrade",
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
@@ -102,19 +95,6 @@ This method can also be used to debug a strategy, by setting the breakpoints wit
|
|||||||
|
|
||||||
A similar setup can also be taken for Pycharm - using `freqtrade` as module name, and setting the command line arguments as "parameters".
|
A similar setup can also be taken for Pycharm - using `freqtrade` as module name, and setting the command line arguments as "parameters".
|
||||||
|
|
||||||
??? Tip "Correct venv usage"
|
|
||||||
When using a virtual environment (which you should), make sure that your Editor is using the correct virtual environment to avoid problems or "unknown import" errors.
|
|
||||||
|
|
||||||
#### Vscode
|
|
||||||
|
|
||||||
You can select the correct environment in VSCode with the command "Python: Select Interpreter" - which will show you environments the extension detected.
|
|
||||||
If your environment has not been detected, you can also pick a path manually.
|
|
||||||
|
|
||||||
#### Pycharm
|
|
||||||
|
|
||||||
In pycharm, you can select the appropriate Environment in the "Run/Debug Configurations" window.
|
|
||||||

|
|
||||||
|
|
||||||
!!! Note "Startup directory"
|
!!! 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).
|
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).
|
||||||
|
|
||||||
@@ -129,8 +109,6 @@ Below is an outline of exception inheritance hierarchy:
|
|||||||
+ FreqtradeException
|
+ FreqtradeException
|
||||||
|
|
|
|
||||||
+---+ OperationalException
|
+---+ OperationalException
|
||||||
| |
|
|
||||||
| +---+ ConfigurationError
|
|
||||||
|
|
|
|
||||||
+---+ DependencyException
|
+---+ DependencyException
|
||||||
| |
|
| |
|
||||||
@@ -261,7 +239,7 @@ For that reason, they must implement the following methods:
|
|||||||
|
|
||||||
The `until` portion should be calculated using the provided `calculate_lock_end()` method.
|
The `until` portion should be calculated using the provided `calculate_lock_end()` method.
|
||||||
|
|
||||||
All Protections should use `"stop_duration"` / `"stop_duration_candles"` to define how long a pair (or all pairs) should be locked.
|
All Protections should use `"stop_duration"` / `"stop_duration_candles"` to define how long a a pair (or all pairs) should be locked.
|
||||||
The content of this is made available as `self._stop_duration` to the each Protection.
|
The content of this is made available as `self._stop_duration` to the each Protection.
|
||||||
|
|
||||||
If your protection requires a look-back period, please use `"lookback_period"` / `"lockback_period_candles"` to keep all protections aligned.
|
If your protection requires a look-back period, please use `"lookback_period"` / `"lockback_period_candles"` to keep all protections aligned.
|
||||||
@@ -305,7 +283,7 @@ The `IProtection` parent class provides a helper method for this in `calculate_l
|
|||||||
|
|
||||||
Most exchanges supported by CCXT should work out of the box.
|
Most exchanges supported by CCXT should work out of the box.
|
||||||
|
|
||||||
To quickly test the public endpoints of an exchange, add a configuration for your exchange to `tests/exchange_online/conftest.py` and run these tests with `pytest --longrun tests/exchange_online/test_ccxt_compat.py`.
|
To quickly test the public endpoints of an exchange, add a configuration for your exchange to `test_ccxt_compat.py` and run these tests with `pytest --longrun tests/exchange/test_ccxt_compat.py`.
|
||||||
Completing these tests successfully a good basis point (it's a requirement, actually), however these won't guarantee correct exchange functioning, as this only tests public endpoints, but no private endpoint (like generate order or similar).
|
Completing these tests successfully a good basis point (it's a requirement, actually), however these won't guarantee correct exchange functioning, as this only tests public endpoints, but no private endpoint (like generate order or similar).
|
||||||
|
|
||||||
Also try to use `freqtrade download-data` for an extended timerange (multiple months) and verify that the data downloaded correctly (no holes, the specified timerange was actually downloaded).
|
Also try to use `freqtrade download-data` for an extended timerange (multiple months) and verify that the data downloaded correctly (no holes, the specified timerange was actually downloaded).
|
||||||
@@ -320,7 +298,6 @@ Additional tests / steps to complete:
|
|||||||
* Check if balance shows correctly (*)
|
* Check if balance shows correctly (*)
|
||||||
* Create market order (*)
|
* Create market order (*)
|
||||||
* Create limit order (*)
|
* Create limit order (*)
|
||||||
* Cancel order (*)
|
|
||||||
* Complete trade (enter + exit) (*)
|
* Complete trade (enter + exit) (*)
|
||||||
* Compare result calculation between exchange and bot
|
* Compare result calculation between exchange and bot
|
||||||
* Ensure fees are applied correctly (check the database against the exchange)
|
* Ensure fees are applied correctly (check the database against the exchange)
|
||||||
@@ -343,18 +320,18 @@ To check how the new exchange behaves, you can use the following snippet:
|
|||||||
|
|
||||||
``` python
|
``` python
|
||||||
import ccxt
|
import ccxt
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime
|
||||||
from freqtrade.data.converter import ohlcv_to_dataframe
|
from freqtrade.data.converter import ohlcv_to_dataframe
|
||||||
ct = ccxt.binance() # Use the exchange you're testing
|
ct = ccxt.binance()
|
||||||
timeframe = "1d"
|
timeframe = "1d"
|
||||||
pair = "BTC/USDT" # Make sure to use a pair that exists on that exchange!
|
pair = "XLM/BTC" # Make sure to use a pair that exists on that exchange!
|
||||||
raw = ct.fetch_ohlcv(pair, timeframe=timeframe)
|
raw = ct.fetch_ohlcv(pair, timeframe=timeframe)
|
||||||
|
|
||||||
# convert to dataframe
|
# convert to dataframe
|
||||||
df1 = ohlcv_to_dataframe(raw, timeframe, pair=pair, drop_incomplete=False)
|
df1 = ohlcv_to_dataframe(raw, timeframe, pair=pair, drop_incomplete=False)
|
||||||
|
|
||||||
print(df1.tail(1))
|
print(df1.tail(1))
|
||||||
print(datetime.now(timezone.utc))
|
print(datetime.utcnow())
|
||||||
```
|
```
|
||||||
|
|
||||||
``` output
|
``` output
|
||||||
@@ -378,8 +355,8 @@ from pathlib import Path
|
|||||||
|
|
||||||
exchange = ccxt.binance({
|
exchange = ccxt.binance({
|
||||||
'apiKey': '<apikey>',
|
'apiKey': '<apikey>',
|
||||||
'secret': '<secret>',
|
'secret': '<secret>'
|
||||||
'options': {'defaultType': 'swap'}
|
'options': {'defaultType': 'future'}
|
||||||
})
|
})
|
||||||
_ = exchange.load_markets()
|
_ = exchange.load_markets()
|
||||||
|
|
||||||
@@ -421,9 +398,6 @@ This part of the documentation is aimed at maintainers, and shows how to create
|
|||||||
|
|
||||||
### Create release branch
|
### Create release branch
|
||||||
|
|
||||||
!!! Note
|
|
||||||
Make sure that the `stable` branch is up-to-date!
|
|
||||||
|
|
||||||
First, pick a commit that's about one week old (to not include latest additions to releases).
|
First, pick a commit that's about one week old (to not include latest additions to releases).
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
@@ -435,12 +409,14 @@ Determine if crucial bugfixes have been made between this commit and the current
|
|||||||
|
|
||||||
* Merge the release branch (stable) into this branch.
|
* Merge the release branch (stable) into this branch.
|
||||||
* Edit `freqtrade/__init__.py` and add the version matching the current date (for example `2019.7` for July 2019). Minor versions can be `2019.7.1` should we need to do a second release that month. Version numbers must follow allowed versions from PEP0440 to avoid failures pushing to pypi.
|
* Edit `freqtrade/__init__.py` and add the version matching the current date (for example `2019.7` for July 2019). Minor versions can be `2019.7.1` should we need to do a second release that month. Version numbers must follow allowed versions from PEP0440 to avoid failures pushing to pypi.
|
||||||
* Commit this part.
|
* Commit this part
|
||||||
* Push that branch to the remote and create a PR against the **stable branch**.
|
* push that branch to the remote and create a PR against the stable branch
|
||||||
* Update develop version to next version following the pattern `2019.8-dev`.
|
|
||||||
|
|
||||||
### Create changelog from git commits
|
### Create changelog from git commits
|
||||||
|
|
||||||
|
!!! Note
|
||||||
|
Make sure that the `stable` branch is up-to-date!
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
# Needs to be done before merging / pulling that branch.
|
# Needs to be done before merging / pulling that branch.
|
||||||
git log --oneline --no-decorate --no-merges stable..new_release
|
git log --oneline --no-decorate --no-merges stable..new_release
|
||||||
@@ -457,11 +433,6 @@ To keep the release-log short, best wrap the full git changelog into a collapsib
|
|||||||
</details>
|
</details>
|
||||||
```
|
```
|
||||||
|
|
||||||
### FreqUI release
|
|
||||||
|
|
||||||
If FreqUI has been updated substantially, make sure to create a release before merging the release branch.
|
|
||||||
Make sure that freqUI CI on the release is finished and passed before merging the release.
|
|
||||||
|
|
||||||
### Create github release / tag
|
### Create github release / tag
|
||||||
|
|
||||||
Once the PR against stable is merged (best right after merging):
|
Once the PR against stable is merged (best right after merging):
|
||||||
@@ -469,13 +440,7 @@ Once the PR against stable is merged (best right after merging):
|
|||||||
* Use the button "Draft a new release" in the Github UI (subsection releases).
|
* Use the button "Draft a new release" in the Github UI (subsection releases).
|
||||||
* Use the version-number specified as tag.
|
* Use the version-number specified as tag.
|
||||||
* Use "stable" as reference (this step comes after the above PR is merged).
|
* Use "stable" as reference (this step comes after the above PR is merged).
|
||||||
* Use the above changelog as release comment (as codeblock).
|
* Use the above changelog as release comment (as codeblock)
|
||||||
* Use the below snippet for the new release
|
|
||||||
|
|
||||||
??? Tip "Release template"
|
|
||||||
````
|
|
||||||
--8<-- "includes/release_template.md"
|
|
||||||
````
|
|
||||||
|
|
||||||
## Releases
|
## Releases
|
||||||
|
|
||||||
|
|||||||
@@ -4,25 +4,20 @@ This page explains how to run the bot with Docker. It is not meant to work out o
|
|||||||
|
|
||||||
## Install Docker
|
## Install Docker
|
||||||
|
|
||||||
Start by downloading and installing Docker / Docker Desktop for your platform:
|
Start by downloading and installing Docker CE for your platform:
|
||||||
|
|
||||||
* [Mac](https://docs.docker.com/docker-for-mac/install/)
|
* [Mac](https://docs.docker.com/docker-for-mac/install/)
|
||||||
* [Windows](https://docs.docker.com/docker-for-windows/install/)
|
* [Windows](https://docs.docker.com/docker-for-windows/install/)
|
||||||
* [Linux](https://docs.docker.com/install/)
|
* [Linux](https://docs.docker.com/install/)
|
||||||
|
|
||||||
!!! Info "Docker compose 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).
|
||||||
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`).
|
|
||||||
|
|
||||||
??? Warning "Docker on windows"
|
## Freqtrade with docker-compose
|
||||||
If you just installed docker on a windows system, make sure to reboot your system, otherwise you might encounter unexplainable Problems related to network connectivity to docker containers.
|
|
||||||
|
|
||||||
## 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
|
!!! Note
|
||||||
- The following section assumes that `docker` is installed and available to the logged in user.
|
- The following section assumes that `docker` and `docker-compose` are 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.
|
- All below commands use relative directories and will have to be executed from the directory containing the `docker-compose.yml` file.
|
||||||
|
|
||||||
### Docker quick start
|
### Docker quick start
|
||||||
@@ -36,13 +31,13 @@ cd ft_userdata/
|
|||||||
curl https://raw.githubusercontent.com/freqtrade/freqtrade/stable/docker-compose.yml -o docker-compose.yml
|
curl https://raw.githubusercontent.com/freqtrade/freqtrade/stable/docker-compose.yml -o docker-compose.yml
|
||||||
|
|
||||||
# Pull the freqtrade image
|
# Pull the freqtrade image
|
||||||
docker compose pull
|
docker-compose pull
|
||||||
|
|
||||||
# Create user directory structure
|
# 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
|
# 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.
|
The above snippet creates a new directory called `ft_userdata`, downloads the latest compose file and pulls the freqtrade image.
|
||||||
@@ -69,7 +64,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).
|
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
|
``` bash
|
||||||
docker compose up -d
|
docker-compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! Warning "Default configuration"
|
!!! Warning "Default configuration"
|
||||||
@@ -81,7 +76,7 @@ If you've selected to enable FreqUI in the `new-config` step, you will have freq
|
|||||||
|
|
||||||
You can now access the UI by typing localhost:8080 in your browser.
|
You can now access the UI by typing localhost:8080 in your browser.
|
||||||
|
|
||||||
??? Note "UI Access on a remote server"
|
??? Note "UI Access on a remote servers"
|
||||||
If you're running on a VPS, you should consider using either a ssh tunnel, or setup a VPN (openVPN, wireguard) to connect to your bot.
|
If you're running on a VPS, you should consider using either a ssh tunnel, or setup a VPN (openVPN, wireguard) to connect to your bot.
|
||||||
This will ensure that freqUI is not directly exposed to the internet, which is not recommended for security reasons (freqUI does not support https out of the box).
|
This will ensure that freqUI is not directly exposed to the internet, which is not recommended for security reasons (freqUI does not support https out of the box).
|
||||||
Setup of these tools is not part of this tutorial, however many good tutorials can be found on the internet.
|
Setup of these tools is not part of this tutorial, however many good tutorials can be found on the internet.
|
||||||
@@ -89,27 +84,27 @@ You can now access the UI by typing localhost:8080 in your browser.
|
|||||||
|
|
||||||
#### Monitoring the bot
|
#### 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).
|
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`.
|
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
|
#### Database
|
||||||
|
|
||||||
The database will be located at: `user_data/tradesv3.sqlite`
|
The database will be located at: `user_data/tradesv3.sqlite`
|
||||||
|
|
||||||
#### Updating freqtrade with docker
|
#### Updating freqtrade with docker-compose
|
||||||
|
|
||||||
Updating freqtrade when using `docker` is as simple as running the following 2 commands:
|
Updating freqtrade when using `docker-compose` is as simple as running the following 2 commands:
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
# Download the latest image
|
# Download the latest image
|
||||||
docker compose pull
|
docker-compose pull
|
||||||
# Restart the image
|
# 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.
|
This will first pull the latest image, and will then restart the container with the just pulled version.
|
||||||
@@ -121,43 +116,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.
|
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"
|
!!! 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.
|
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.
|
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.
|
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).
|
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"
|
??? Note "Using docker without docker-compose"
|
||||||
"`docker compose run --rm`" will require a compose file to be provided.
|
"`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.
|
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`.
|
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.
|
This can be useful for fetching exchange information to add to your `config.json` without affecting your running containers.
|
||||||
|
|
||||||
#### Example: Download data with docker
|
#### Example: Download data with docker-compose
|
||||||
|
|
||||||
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.
|
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
|
``` 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.
|
Head over to the [Data Downloading Documentation](data-download.md) for more details on downloading data.
|
||||||
|
|
||||||
#### Example: Backtest with docker
|
#### Example: Backtest with docker-compose
|
||||||
|
|
||||||
Run backtesting in docker-containers for SampleStrategy and specified timerange of historical data, on 5m timeframe:
|
Run backtesting in docker-containers for SampleStrategy and specified timerange of historical data, on 5m timeframe:
|
||||||
|
|
||||||
``` bash
|
``` 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.
|
Head over to the [Backtesting Documentation](backtesting.md) to learn more.
|
||||||
|
|
||||||
### Additional dependencies with docker
|
### Additional dependencies with docker-compose
|
||||||
|
|
||||||
If your strategy requires dependencies not included in the default image - it will be necessary to build the image on your host.
|
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).
|
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).
|
||||||
@@ -171,15 +166,15 @@ You'll then also need to modify the `docker-compose.yml` file and uncomment the
|
|||||||
dockerfile: "./Dockerfile.<yourextension>"
|
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
|
### Plotting with docker-compose
|
||||||
|
|
||||||
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.
|
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:
|
You can then use these commands as follows:
|
||||||
|
|
||||||
``` bash
|
``` 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.
|
The output will be stored in the `user_data/plot` directory, and can be opened with any modern browser.
|
||||||
@@ -190,7 +185,7 @@ Freqtrade provides a docker-compose file which starts up a jupyter lab server.
|
|||||||
You can run this server using the following command:
|
You can run this server using the following command:
|
||||||
|
|
||||||
``` bash
|
``` 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`.
|
This will create a docker-container running jupyter lab, which will be accessible using `https://127.0.0.1:8888/lab`.
|
||||||
@@ -199,27 +194,23 @@ 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.
|
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
|
``` bash
|
||||||
docker compose -f docker/docker-compose-jupyter.yml build --no-cache
|
docker-compose -f docker/docker-compose-jupyter.yml build --no-cache
|
||||||
```
|
```
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
### Docker on Windows
|
### Docker on Windows
|
||||||
|
|
||||||
* Error: `"Timestamp for this request is outside of the recvWindow."`
|
* Error: `"Timestamp for this request is outside of the recvWindow."`
|
||||||
The market api requests require a synchronized clock but the time in the docker container shifts a bit over time into the past.
|
* The market api requests require a synchronized clock but the time in the docker container shifts a bit over time into the past.
|
||||||
To fix this issue temporarily you need to run `wsl --shutdown` and restart docker again (a popup on windows 10 will ask you to do so).
|
To fix this issue temporarily you need to run `wsl --shutdown` and restart docker again (a popup on windows 10 will ask you to do so).
|
||||||
A permanent solution is either to host the docker container on a linux host or restart the wsl from time to time with the scheduler.
|
A permanent solution is either to host the docker container on a linux host or restart the wsl from time to time with the scheduler.
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
taskkill /IM "Docker Desktop.exe" /F
|
taskkill /IM "Docker Desktop.exe" /F
|
||||||
wsl --shutdown
|
wsl --shutdown
|
||||||
start "" "C:\Program Files\Docker\Docker\Docker Desktop.exe"
|
start "" "C:\Program Files\Docker\Docker\Docker Desktop.exe"
|
||||||
```
|
```
|
||||||
|
|
||||||
* Cannot connect to the API (Windows)
|
|
||||||
If you're on windows and just installed Docker (desktop), make sure to reboot your System. Docker can have problems with network connectivity without a restart.
|
|
||||||
You should obviously also make sure to have your [settings](#accessing-the-ui) accordingly.
|
|
||||||
|
|
||||||
!!! Warning
|
!!! Warning
|
||||||
Due to the above, we do not recommend the usage of docker on windows for production setups, but only for experimentation, datadownload and backtesting.
|
Due to the above, we do not recommend the usage of docker on windows for production setups, but only for experimentation, datadownload and backtesting.
|
||||||
|
|||||||
@@ -2,10 +2,6 @@
|
|||||||
|
|
||||||
The `Edge Positioning` module uses probability to calculate your win rate and risk reward ratio. It will use these statistics to control your strategy trade entry points, position size and, stoploss.
|
The `Edge Positioning` module uses probability to calculate your win rate and risk reward ratio. It will use these statistics to control your strategy trade entry points, position size and, stoploss.
|
||||||
|
|
||||||
!!! Danger "Deprecated functionality"
|
|
||||||
`Edge positioning` (or short Edge) is currently in maintenance mode only (we keep existing functionality alive) and should be considered as deprecated.
|
|
||||||
It will currently not receive new features until either someone stepped forward to take up ownership of that module - or we'll decide to remove edge from freqtrade.
|
|
||||||
|
|
||||||
!!! Warning
|
!!! Warning
|
||||||
When using `Edge positioning` with a dynamic whitelist (VolumePairList), make sure to also use `AgeFilter` and set it to at least `calculate_since_number_of_days` to avoid problems with missing data.
|
When using `Edge positioning` with a dynamic whitelist (VolumePairList), make sure to also use `AgeFilter` and set it to at least `calculate_since_number_of_days` to avoid problems with missing data.
|
||||||
|
|
||||||
@@ -137,7 +133,7 @@ $$ R = \frac{\text{average_profit}}{\text{average_loss}} = \frac{\mu_{win}}{\mu_
|
|||||||
|
|
||||||
### Expectancy
|
### Expectancy
|
||||||
|
|
||||||
By combining the Win Rate $W$ and the Risk Reward ratio $R$ to create an expectancy ratio $E$. A expectance ratio is the expected return of the investment made in a trade. We can compute the value of $E$ as follows:
|
By combining the Win Rate $W$ and and the Risk Reward ratio $R$ to create an expectancy ratio $E$. A expectance ratio is the expected return of the investment made in a trade. We can compute the value of $E$ as follows:
|
||||||
|
|
||||||
$$E = R * W - L$$
|
$$E = R * W - L$$
|
||||||
|
|
||||||
|
|||||||
@@ -54,47 +54,15 @@ This configuration enables kraken, as well as rate-limiting to avoid bans from t
|
|||||||
|
|
||||||
## Binance
|
## Binance
|
||||||
|
|
||||||
!!! Warning "Server location and geo-ip restrictions"
|
|
||||||
Please be aware that Binance restricts API access regarding the server country. The current and non-exhaustive countries blocked are Canada, Malaysia, Netherlands and United States. Please go to [binance terms > b. Eligibility](https://www.binance.com/en/terms) to find up to date list.
|
|
||||||
|
|
||||||
Binance supports [time_in_force](configuration.md#understand-order_time_in_force).
|
Binance supports [time_in_force](configuration.md#understand-order_time_in_force).
|
||||||
|
|
||||||
!!! Tip "Stoploss on Exchange"
|
!!! Tip "Stoploss on Exchange"
|
||||||
Binance supports `stoploss_on_exchange` and uses `stop-loss-limit` orders. It provides great advantages, so we recommend to benefit from it by enabling stoploss on exchange.
|
Binance supports `stoploss_on_exchange` and uses `stop-loss-limit` orders. It provides great advantages, so we recommend to benefit from it by enabling stoploss on exchange..
|
||||||
On futures, Binance supports both `stop-limit` as well as `stop-market` orders. You can use either `"limit"` or `"market"` in the `order_types.stoploss` configuration setting to decide which type to use.
|
|
||||||
|
|
||||||
### Binance Blacklist recommendation
|
### Binance Blacklist
|
||||||
|
|
||||||
For Binance, it is suggested to add `"BNB/<STAKE>"` to your blacklist to avoid issues, unless you are willing to maintain enough extra `BNB` on the account or unless you're willing to disable using `BNB` for fees.
|
For Binance, please add `"BNB/<STAKE>"` to your blacklist to avoid issues.
|
||||||
Binance accounts may use `BNB` for fees, and if a trade happens to be on `BNB`, further trades may consume this position and make the initial BNB trade unsellable as the expected amount is not there anymore.
|
Accounts having BNB accounts use this to pay for fees - if your first trade happens to be on `BNB`, further trades will consume this position and make the initial BNB trade unsellable as the expected amount is not there anymore.
|
||||||
|
|
||||||
If not enough `BNB` is available to cover transaction fees, then fees will not be covered by `BNB` and no fee reduction will occur. Freqtrade will never buy BNB to cover for fees. BNB needs to be bought and monitored manually to this end.
|
|
||||||
|
|
||||||
### Binance sites
|
|
||||||
|
|
||||||
Binance has been split into 2, and users must use the correct ccxt exchange ID for their exchange, otherwise API keys are not recognized.
|
|
||||||
|
|
||||||
* [binance.com](https://www.binance.com/) - International users. Use exchange id: `binance`.
|
|
||||||
* [binance.us](https://www.binance.us/) - US based users. Use exchange id: `binanceus`.
|
|
||||||
|
|
||||||
### Binance RSA keys
|
|
||||||
|
|
||||||
Freqtrade supports binance RSA API keys.
|
|
||||||
|
|
||||||
We recommend to use them as environment variable.
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
export FREQTRADE__EXCHANGE__SECRET="$(cat ./rsa_binance.private)"
|
|
||||||
```
|
|
||||||
|
|
||||||
They can however also be configured via configuration file. Since json doesn't support multi-line strings, you'll have to replace all newlines with `\n` to have a valid json file.
|
|
||||||
|
|
||||||
``` json
|
|
||||||
// ...
|
|
||||||
"key": "<someapikey>",
|
|
||||||
"secret": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBABACAFQA<...>s8KX8=\n-----END PRIVATE KEY-----"
|
|
||||||
// ...
|
|
||||||
```
|
|
||||||
|
|
||||||
### Binance Futures
|
### Binance Futures
|
||||||
|
|
||||||
@@ -118,26 +86,15 @@ When trading on Binance Futures market, orderbook must be used because there is
|
|||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Binance futures settings
|
### Binance sites
|
||||||
|
|
||||||
Users will also have to have the futures-setting "Position Mode" set to "One-way Mode", and "Asset Mode" set to "Single-Asset Mode".
|
Binance has been split into 2, and users must use the correct ccxt exchange ID for their exchange, otherwise API keys are not recognized.
|
||||||
These settings will be checked on startup, and freqtrade will show an error if this setting is wrong.
|
|
||||||
|
|
||||||

|
* [binance.com](https://www.binance.com/) - International users. Use exchange id: `binance`.
|
||||||
|
* [binance.us](https://www.binance.us/) - US based users. Use exchange id: `binanceus`.
|
||||||
Freqtrade will not attempt to change these settings.
|
|
||||||
|
|
||||||
## Bingx
|
|
||||||
|
|
||||||
BingX supports [time_in_force](configuration.md#understand-order_time_in_force) with settings "GTC" (good till cancelled), "IOC" (immediate-or-cancel) and "PO" (Post only) settings.
|
|
||||||
|
|
||||||
!!! Tip "Stoploss on Exchange"
|
|
||||||
Bingx supports `stoploss_on_exchange` and can use both stop-limit and stop-market orders. It provides great advantages, so we recommend to benefit from it by enabling stoploss on exchange.
|
|
||||||
|
|
||||||
## Kraken
|
## Kraken
|
||||||
|
|
||||||
Kraken supports [time_in_force](configuration.md#understand-order_time_in_force) with settings "GTC" (good till cancelled), "IOC" (immediate-or-cancel) and "PO" (Post only) settings.
|
|
||||||
|
|
||||||
!!! Tip "Stoploss on Exchange"
|
!!! Tip "Stoploss on Exchange"
|
||||||
Kraken supports `stoploss_on_exchange` and can use both stop-loss-market and stop-loss-limit orders. It provides great advantages, so we recommend to benefit from it.
|
Kraken supports `stoploss_on_exchange` and can use both stop-loss-market and stop-loss-limit orders. It provides great advantages, so we recommend to benefit from it.
|
||||||
You can use either `"limit"` or `"market"` in the `order_types.stoploss` configuration setting to decide which type to use.
|
You can use either `"limit"` or `"market"` in the `order_types.stoploss` configuration setting to decide which type to use.
|
||||||
@@ -147,41 +104,13 @@ Kraken supports [time_in_force](configuration.md#understand-order_time_in_force)
|
|||||||
The Kraken API does only provide 720 historic candles, which is sufficient for Freqtrade dry-run and live trade modes, but is a problem for backtesting.
|
The Kraken API does only provide 720 historic candles, which is sufficient for Freqtrade dry-run and live trade modes, but is a problem for backtesting.
|
||||||
To download data for the Kraken exchange, using `--dl-trades` is mandatory, otherwise the bot will download the same 720 candles over and over, and you'll not have enough backtest data.
|
To download data for the Kraken exchange, using `--dl-trades` is mandatory, otherwise the bot will download the same 720 candles over and over, and you'll not have enough backtest data.
|
||||||
|
|
||||||
To speed up downloading, you can download the [trades zip files](https://support.kraken.com/hc/en-us/articles/360047543791-Downloadable-historical-market-data-time-and-sales-) kraken provides.
|
Due to the heavy rate-limiting applied by Kraken, the following configuration section should be used to download data:
|
||||||
These are usually updated once per quarter. Freqtrade expects these files to be placed in `user_data/data/kraken/trades_csv`.
|
|
||||||
|
|
||||||
A structure as follows can make sense if using incremental files, with the "full" history in one directory, and incremental files in different directories.
|
``` json
|
||||||
The assumption for this mode is that the data is downloaded and unzipped keeping filenames as they are.
|
"ccxt_async_config": {
|
||||||
Duplicate content will be ignored (based on timestamp) - though the assumption is that there is no gap in the data.
|
"enableRateLimit": true,
|
||||||
|
"rateLimit": 3100
|
||||||
This means, if your "full" history ends in Q4 2022 - then both incremental updates Q1 2023 and Q2 2023 are available.
|
},
|
||||||
Not having this will lead to incomplete data, and therefore invalid results while using the data.
|
|
||||||
|
|
||||||
```
|
|
||||||
└── trades_csv
|
|
||||||
├── Kraken_full_history
|
|
||||||
│ ├── BCHEUR.csv
|
|
||||||
│ └── XBTEUR.csv
|
|
||||||
├── Kraken_Trading_History_Q1_2023
|
|
||||||
│ ├── BCHEUR.csv
|
|
||||||
│ └── XBTEUR.csv
|
|
||||||
└── Kraken_Trading_History_Q2_2023
|
|
||||||
├── BCHEUR.csv
|
|
||||||
└── XBTEUR.csv
|
|
||||||
```
|
|
||||||
|
|
||||||
You can convert these files into freqtrade files:
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
freqtrade convert-trade-data --exchange kraken --format-from kraken_csv --format-to feather
|
|
||||||
# Convert trade data to different ohlcv timeframes
|
|
||||||
freqtrade trades-to-ohlcv -p BTC/EUR BCH/EUR --exchange kraken -t 1m 5m 15m 1h
|
|
||||||
```
|
|
||||||
|
|
||||||
The converted data also makes downloading data possible, and will start the download after the latest loaded trade.
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
freqtrade download-data --exchange kraken --dl-trades -p BTC/EUR BCH/EUR
|
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! Warning "Downloading data from kraken"
|
!!! Warning "Downloading data from kraken"
|
||||||
@@ -192,6 +121,68 @@ freqtrade download-data --exchange kraken --dl-trades -p BTC/EUR BCH/EUR
|
|||||||
Please pay attention that rateLimit configuration entry holds delay in milliseconds between requests, NOT requests\sec rate.
|
Please pay attention that rateLimit configuration entry holds delay in milliseconds between requests, NOT requests\sec rate.
|
||||||
So, in order to mitigate Kraken API "Rate limit exceeded" exception, this configuration should be increased, NOT decreased.
|
So, in order to mitigate Kraken API "Rate limit exceeded" exception, this configuration should be increased, NOT decreased.
|
||||||
|
|
||||||
|
## Bittrex
|
||||||
|
|
||||||
|
### Order types
|
||||||
|
|
||||||
|
Bittrex does not support market orders. If you have a message at the bot startup about this, you should change order type values set in your configuration and/or in the strategy from `"market"` to `"limit"`. See some more details on this [here in the FAQ](faq.md#im-getting-the-exchange-bittrex-does-not-support-market-orders-message-and-cannot-run-my-strategy).
|
||||||
|
|
||||||
|
Bittrex also does not support `VolumePairlist` due to limited / split API constellation at the moment.
|
||||||
|
Please use `StaticPairlist`. Other pairlists (other than `VolumePairlist`) should not be affected.
|
||||||
|
|
||||||
|
### Volume pairlist
|
||||||
|
|
||||||
|
Bittrex does not support the direct usage of VolumePairList. This can however be worked around by using the advanced mode with `lookback_days: 1` (or more), which will emulate 24h volume.
|
||||||
|
|
||||||
|
Read more in the [pairlist documentation](plugins.md#volumepairlist-advanced-mode).
|
||||||
|
|
||||||
|
### Restricted markets
|
||||||
|
|
||||||
|
Bittrex split its exchange into US and International versions.
|
||||||
|
The International version has more pairs available, however the API always returns all pairs, so there is currently no automated way to detect if you're affected by the restriction.
|
||||||
|
|
||||||
|
If you have restricted pairs in your whitelist, you'll get a warning message in the log on Freqtrade startup for each restricted pair.
|
||||||
|
|
||||||
|
The warning message will look similar to the following:
|
||||||
|
|
||||||
|
``` output
|
||||||
|
[...] Message: bittrex {"success":false,"message":"RESTRICTED_MARKET","result":null,"explanation":null}"
|
||||||
|
```
|
||||||
|
|
||||||
|
If you're an "International" customer on the Bittrex exchange, then this warning will probably not impact you.
|
||||||
|
If you're a US customer, the bot will fail to create orders for these pairs, and you should remove them from your whitelist.
|
||||||
|
|
||||||
|
You can get a list of restricted markets by using the following snippet:
|
||||||
|
|
||||||
|
``` python
|
||||||
|
import ccxt
|
||||||
|
ct = ccxt.bittrex()
|
||||||
|
lm = ct.load_markets()
|
||||||
|
|
||||||
|
res = [p for p, x in lm.items() if 'US' in x['info']['prohibitedIn']]
|
||||||
|
print(res)
|
||||||
|
```
|
||||||
|
|
||||||
|
## FTX
|
||||||
|
|
||||||
|
!!! Tip "Stoploss on Exchange"
|
||||||
|
FTX supports `stoploss_on_exchange` and can use both stop-loss-market and stop-loss-limit orders. It provides great advantages, so we recommend to benefit from it.
|
||||||
|
You can use either `"limit"` or `"market"` in the `order_types.stoploss` configuration setting to decide which type of stoploss shall be used.
|
||||||
|
|
||||||
|
### Using subaccounts
|
||||||
|
|
||||||
|
To use subaccounts with FTX, you need to edit the configuration and add the following:
|
||||||
|
|
||||||
|
``` json
|
||||||
|
"exchange": {
|
||||||
|
"ccxt_config": {
|
||||||
|
"headers": {
|
||||||
|
"FTX-SUBACCOUNT": "name"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Kucoin
|
## Kucoin
|
||||||
|
|
||||||
Kucoin requires a passphrase for each api key, you will therefore need to add this key into the configuration so your exchange section looks as follows:
|
Kucoin requires a passphrase for each api key, you will therefore need to add this key into the configuration so your exchange section looks as follows:
|
||||||
@@ -214,13 +205,13 @@ Kucoin supports [time_in_force](configuration.md#understand-order_time_in_force)
|
|||||||
|
|
||||||
### Kucoin Blacklists
|
### Kucoin Blacklists
|
||||||
|
|
||||||
For Kucoin, it is suggested to add `"KCS/<STAKE>"` to your blacklist to avoid issues, unless you are willing to maintain enough extra `KCS` on the account or unless you're willing to disable using `KCS` for fees.
|
For Kucoin, please add `"KCS/<STAKE>"` to your blacklist to avoid issues.
|
||||||
Kucoin accounts may use `KCS` for fees, and if a trade happens to be on `KCS`, further trades may consume this position and make the initial `KCS` trade unsellable as the expected amount is not there anymore.
|
Accounts having KCS accounts use this to pay for fees - if your first trade happens to be on `KCS`, further trades will consume this position and make the initial KCS trade unsellable as the expected amount is not there anymore.
|
||||||
|
|
||||||
## HTX (formerly Huobi)
|
## Huobi
|
||||||
|
|
||||||
!!! Tip "Stoploss on Exchange"
|
!!! Tip "Stoploss on Exchange"
|
||||||
HTX supports `stoploss_on_exchange` and uses `stop-limit` orders. It provides great advantages, so we recommend to benefit from it by enabling stoploss on exchange.
|
Huobi supports `stoploss_on_exchange` and uses `stop-limit` orders. It provides great advantages, so we recommend to benefit from it by enabling stoploss on exchange.
|
||||||
|
|
||||||
## OKX (former OKEX)
|
## OKX (former OKEX)
|
||||||
|
|
||||||
@@ -240,8 +231,8 @@ OKX requires a passphrase for each api key, you will therefore need to add this
|
|||||||
OKX only provides 100 candles per api call. Therefore, the strategy will only have a pretty low amount of data available in backtesting mode.
|
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"
|
!!! Warning "Futures"
|
||||||
OKX Futures has the concept of "position mode" - which can be "Buy/Sell" or long/short (hedge mode).
|
OKX Futures has the concept of "position mode" - which can be Net or long/short (hedge mode).
|
||||||
Freqtrade supports both modes (we recommend to use Buy/Sell mode) - but changing the mode mid-trading is not supported and will lead to exceptions and failures to place trades.
|
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.
|
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
|
## Gate.io
|
||||||
@@ -252,43 +243,6 @@ OKX requires a passphrase for each api key, you will therefore need to add this
|
|||||||
Gate.io allows the use of `POINT` to pay for fees. As this is not a tradable currency (no regular market available), automatic fee calculations will fail (and default to a fee of 0).
|
Gate.io allows the use of `POINT` to pay for fees. As this is not a tradable currency (no regular market available), automatic fee calculations will fail (and default to a fee of 0).
|
||||||
The configuration parameter `exchange.unknown_fee_rate` can be used to specify the exchange rate between Point and the stake currency. Obviously, changing the stake-currency will also require changes to this value.
|
The configuration parameter `exchange.unknown_fee_rate` can be used to specify the exchange rate between Point and the stake currency. Obviously, changing the stake-currency will also require changes to this value.
|
||||||
|
|
||||||
## Bybit
|
|
||||||
|
|
||||||
Futures trading on bybit is currently supported for USDT markets, and will use isolated futures mode.
|
|
||||||
Users with unified accounts (there's no way back) can create a Sub-account which will start as "non-unified", and can therefore use isolated futures.
|
|
||||||
On startup, freqtrade will set the position mode to "One-way Mode" for the whole (sub)account. This avoids making this call over and over again (slowing down bot operations), but means that changes to this setting may result in exceptions and errors
|
|
||||||
|
|
||||||
As bybit doesn't provide funding rate history, the dry-run calculation is used for live trades as well.
|
|
||||||
|
|
||||||
API Keys for live futures trading (Subaccount on non-unified) must have the following permissions:
|
|
||||||
* Read-write
|
|
||||||
* Contract - Orders
|
|
||||||
* Contract - Positions
|
|
||||||
|
|
||||||
We do strongly recommend to limit all API keys to the IP you're going to use it from.
|
|
||||||
|
|
||||||
!!! Tip "Stoploss on Exchange"
|
|
||||||
Bybit (futures only) supports `stoploss_on_exchange` and uses `stop-loss-limit` orders. It provides great advantages, so we recommend to benefit from it by enabling stoploss on exchange.
|
|
||||||
On futures, Bybit supports both `stop-limit` as well as `stop-market` orders. You can use either `"limit"` or `"market"` in the `order_types.stoploss` configuration setting to decide which type to use.
|
|
||||||
|
|
||||||
## Bitmart
|
|
||||||
|
|
||||||
Bitmart requires the API key Memo (the name you give the API key) to go along with the exchange key and secret.
|
|
||||||
It's therefore required to pass the UID as well.
|
|
||||||
|
|
||||||
```json
|
|
||||||
"exchange": {
|
|
||||||
"name": "bitmart",
|
|
||||||
"uid": "your_bitmart_api_key_memo",
|
|
||||||
"secret": "your_exchange_secret",
|
|
||||||
"password": "your_exchange_api_key_password",
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
!!! Warning "Necessary Verification"
|
|
||||||
Bitmart requires Verification Lvl2 to successfully trade on the spot market through the API - even though trading via UI works just fine with just Lvl1 verification.
|
|
||||||
|
|
||||||
## All exchanges
|
## All exchanges
|
||||||
|
|
||||||
Should you experience constant errors with Nonce (like `InvalidNonce`), it is best to regenerate the API keys. Resetting Nonce is difficult and it's usually easier to regenerate the API keys.
|
Should you experience constant errors with Nonce (like `InvalidNonce`), it is best to regenerate the API keys. Resetting Nonce is difficult and it's usually easier to regenerate the API keys.
|
||||||
@@ -306,7 +260,7 @@ $ pip3 install web3
|
|||||||
Most exchanges return current incomplete candle via their OHLCV/klines API interface.
|
Most exchanges return current incomplete candle via their OHLCV/klines API interface.
|
||||||
By default, Freqtrade assumes that incomplete candle is fetched from the exchange and removes the last candle assuming it's the incomplete candle.
|
By default, Freqtrade assumes that incomplete candle is fetched from the exchange and removes the last candle assuming it's the incomplete candle.
|
||||||
|
|
||||||
Whether your exchange returns incomplete candles or not can be checked using [the helper script](developer.md#incomplete-candles) from the Contributor documentation.
|
Whether your exchange returns incomplete candles or not can be checked using [the helper script](developer.md#Incomplete-candles) from the Contributor documentation.
|
||||||
|
|
||||||
Due to the danger of repainting, Freqtrade does not allow you to use this incomplete candle.
|
Due to the danger of repainting, Freqtrade does not allow you to use this incomplete candle.
|
||||||
|
|
||||||
@@ -324,7 +278,7 @@ For example, to test the order type `FOK` with Kraken, and modify candle limit t
|
|||||||
"exchange": {
|
"exchange": {
|
||||||
"name": "kraken",
|
"name": "kraken",
|
||||||
"_ft_has_params": {
|
"_ft_has_params": {
|
||||||
"order_time_in_force": ["GTC", "FOK"],
|
"order_time_in_force": ["gtc", "fok"],
|
||||||
"ohlcv_candle_limit": 200
|
"ohlcv_candle_limit": 200
|
||||||
}
|
}
|
||||||
//...
|
//...
|
||||||
|
|||||||
86
docs/faq.md
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
## Supported Markets
|
## Supported Markets
|
||||||
|
|
||||||
Freqtrade supports spot trading, as well as (isolated) futures trading for some selected exchanges. Please refer to the [documentation start page](index.md#supported-futures-exchanges-experimental) for an up-to-date list of supported exchanges.
|
Freqtrade supports spot trading only.
|
||||||
|
|
||||||
### Can my bot open short positions?
|
### Can I open short positions?
|
||||||
|
|
||||||
Freqtrade can open short positions in futures markets.
|
Freqtrade can open short positions in futures markets.
|
||||||
This requires the strategy to be made for this - and `"trading_mode": "futures"` in the configuration.
|
This requires the strategy to be made for this - and `"trading_mode": "futures"` in the configuration.
|
||||||
@@ -12,22 +12,15 @@ Please make sure to read the [relevant documentation page](leverage.md) first.
|
|||||||
|
|
||||||
In spot markets, you can in some cases use leveraged spot tokens, which reflect an inverted pair (eg. BTCUP/USD, BTCDOWN/USD, ETHBULL/USD, ETHBEAR/USD,...) which can be traded with Freqtrade.
|
In spot markets, you can in some cases use leveraged spot tokens, which reflect an inverted pair (eg. BTCUP/USD, BTCDOWN/USD, ETHBULL/USD, ETHBEAR/USD,...) which can be traded with Freqtrade.
|
||||||
|
|
||||||
### Can my bot trade options or futures?
|
### Can I trade options or futures?
|
||||||
|
|
||||||
Futures trading is supported for selected exchanges. Please refer to the [documentation start page](index.md#supported-futures-exchanges-experimental) for an up-to-date list of supported exchanges.
|
Futures trading is supported for selected exchanges.
|
||||||
|
|
||||||
## Beginner Tips & Tricks
|
## Beginner Tips & Tricks
|
||||||
|
|
||||||
* When you work with your strategy & hyperopt file you should use a proper code editor like VSCode or PyCharm. A good code editor will provide syntax highlighting as well as line numbers, making it easy to find syntax errors (most likely pointed out by Freqtrade during startup).
|
* When you work with your strategy & hyperopt file you should use a proper code editor like VSCode or PyCharm. A good code editor will provide syntax highlighting as well as line numbers, making it easy to find syntax errors (most likely pointed out by Freqtrade during startup).
|
||||||
|
|
||||||
## Freqtrade common questions
|
## Freqtrade common issues
|
||||||
|
|
||||||
### Can freqtrade open multiple positions on the same pair in parallel?
|
|
||||||
|
|
||||||
No. Freqtrade will only open one position per pair at a time.
|
|
||||||
You can however use the [`adjust_trade_position()` callback](strategy-callbacks.md#adjust-trade-position) to adjust an open position.
|
|
||||||
|
|
||||||
Backtesting provides an option for this in `--eps` - however this is only there to highlight "hidden" signals, and will not work in live.
|
|
||||||
|
|
||||||
### The bot does not start
|
### The bot does not start
|
||||||
|
|
||||||
@@ -36,8 +29,8 @@ Running the bot with `freqtrade trade --config config.json` shows the output `fr
|
|||||||
This could be caused by the following reasons:
|
This could be caused by the following reasons:
|
||||||
|
|
||||||
* The virtual environment is not active.
|
* The virtual environment is not active.
|
||||||
* Run `source .venv/bin/activate` to activate the virtual environment.
|
* Run `source .env/bin/activate` to activate the virtual environment.
|
||||||
* The installation did not complete successfully.
|
* The installation did not work correctly.
|
||||||
* Please check the [Installation documentation](installation.md).
|
* Please check the [Installation documentation](installation.md).
|
||||||
|
|
||||||
### I have waited 5 minutes, why hasn't the bot made any trades yet?
|
### I have waited 5 minutes, why hasn't the bot made any trades yet?
|
||||||
@@ -74,27 +67,19 @@ This is not a bot-problem, but will also happen while manual trading.
|
|||||||
While freqtrade can handle this (it'll sell 99 COIN), fees are often below the minimum tradable lot-size (you can only trade full COIN, not 0.9 COIN).
|
While freqtrade can handle this (it'll sell 99 COIN), fees are often below the minimum tradable lot-size (you can only trade full COIN, not 0.9 COIN).
|
||||||
Leaving the dust (0.9 COIN) on the exchange makes usually sense, as the next time freqtrade buys COIN, it'll eat into the remaining small balance, this time selling everything it bought, and therefore slowly declining the dust balance (although it most likely will never reach exactly 0).
|
Leaving the dust (0.9 COIN) on the exchange makes usually sense, as the next time freqtrade buys COIN, it'll eat into the remaining small balance, this time selling everything it bought, and therefore slowly declining the dust balance (although it most likely will never reach exactly 0).
|
||||||
|
|
||||||
Where possible (e.g. on binance), the use of the exchange's dedicated fee currency will fix this.
|
Where possible (e.g. on binance), the use of the exchange's dedicated fee currency will fix this.
|
||||||
On binance, it's sufficient to have BNB in your account, and have "Pay fees in BNB" enabled in your profile. Your BNB balance will slowly decline (as it's used to pay fees) - but you'll no longer encounter dust (Freqtrade will include the fees in the profit calculations).
|
On binance, it's sufficient to have BNB in your account, and have "Pay fees in BNB" enabled in your profile. Your BNB balance will slowly decline (as it's used to pay fees) - but you'll no longer encounter dust (Freqtrade will include the fees in the profit calculations).
|
||||||
Other exchanges don't offer such possibilities, where it's simply something you'll have to accept or move to a different exchange.
|
Other exchanges don't offer such possibilities, where it's simply something you'll have to accept or move to a different exchange.
|
||||||
|
|
||||||
### I deposited more funds to the exchange, but my bot doesn't recognize this
|
|
||||||
|
|
||||||
Freqtrade will update the exchange balance when necessary (Before placing an order).
|
|
||||||
RPC calls (Telegram's `/balance`, API calls to `/balance`) can trigger an update at max. once per hour.
|
|
||||||
|
|
||||||
If `adjust_trade_position` is enabled (and the bot has open trades eligible for position adjustments) - then the wallets will be refreshed once per hour.
|
|
||||||
To force an immediate update, you can use `/reload_config` - which will restart the bot.
|
|
||||||
|
|
||||||
### I want to use incomplete candles
|
### I want to use incomplete candles
|
||||||
|
|
||||||
Freqtrade will not provide incomplete candles to strategies. Using incomplete candles will lead to repainting and consequently to strategies with "ghost" buys, which are impossible to both backtest, and verify after they happened.
|
Freqtrade will not provide incomplete candles to strategies. Using incomplete candles will lead to repainting and consequently to strategies with "ghost" buys, which are impossible to both backtest, and verify after they happened.
|
||||||
|
|
||||||
You can use "current" market data by using the [dataprovider](strategy-customization.md#orderbookpair-maximum)'s orderbook or ticker methods - which however cannot be used during backtesting.
|
You can use "current" market data by using the [dataprovider](strategy-customization.md#orderbookpair-maximum)'s orderbook or ticker methods - which however cannot be used during backtesting.
|
||||||
|
|
||||||
### Is there a setting to only Exit the trades being held and not perform any new Entries?
|
### Is there a setting to only SELL the coins being held and not perform anymore BUYS?
|
||||||
|
|
||||||
You can use the `/stopentry` command in Telegram to prevent future trade entry, followed by `/forceexit all` (sell all open trades).
|
You can use the `/stopbuy` command in Telegram to prevent future buys, followed by `/forceexit all` (sell all open trades).
|
||||||
|
|
||||||
### I want to run multiple bots on the same machine
|
### I want to run multiple bots on the same machine
|
||||||
|
|
||||||
@@ -110,12 +95,6 @@ If this happens for all pairs in the pairlist, this might indicate a recent exch
|
|||||||
|
|
||||||
Irrespectively of the reason, Freqtrade will fill up these candles with "empty" candles, where open, high, low and close are set to the previous candle close - and volume is empty. In a chart, this will look like a `_` - and is aligned with how exchanges usually represent 0 volume candles.
|
Irrespectively of the reason, Freqtrade will fill up these candles with "empty" candles, where open, high, low and close are set to the previous candle close - and volume is empty. In a chart, this will look like a `_` - and is aligned with how exchanges usually represent 0 volume candles.
|
||||||
|
|
||||||
### I'm getting "Price jump between 2 candles detected"
|
|
||||||
|
|
||||||
This message is a warning that the candles had a price jump of > 30%.
|
|
||||||
This might be a sign that the pair stopped trading, and some token exchange took place (e.g. COCOS in 2021 - where price jumped from 0.0000154 to 0.01621).
|
|
||||||
This message is often accompanied by ["Missing data fillup"](#im-getting-missing-data-fillup-messages-in-the-log) - as trading on such pairs is often stopped for some time.
|
|
||||||
|
|
||||||
### I'm getting "Outdated history for pair xxx" in the log
|
### I'm getting "Outdated history for pair xxx" in the log
|
||||||
|
|
||||||
The bot is trying to tell you that it got an outdated last candle (not the last complete candle).
|
The bot is trying to tell you that it got an outdated last candle (not the last complete candle).
|
||||||
@@ -128,9 +107,15 @@ This warning can point to one of the below problems:
|
|||||||
* Barely traded pair -> Check the pair on the exchange webpage, look at the timeframe your strategy uses. If the pair does not have any volume in some candles (usually visualized with a "volume 0" bar, and a "_" as candle), this pair did not have any trades in this timeframe. These pairs should ideally be avoided, as they can cause problems with order-filling.
|
* Barely traded pair -> Check the pair on the exchange webpage, look at the timeframe your strategy uses. If the pair does not have any volume in some candles (usually visualized with a "volume 0" bar, and a "_" as candle), this pair did not have any trades in this timeframe. These pairs should ideally be avoided, as they can cause problems with order-filling.
|
||||||
* API problem -> API returns wrong data (this only here for completeness, and should not happen with supported exchanges).
|
* API problem -> API returns wrong data (this only here for completeness, and should not happen with supported exchanges).
|
||||||
|
|
||||||
|
### I'm getting the "RESTRICTED_MARKET" message in the log
|
||||||
|
|
||||||
|
Currently known to happen for US Bittrex users.
|
||||||
|
|
||||||
|
Read [the Bittrex section about restricted markets](exchanges.md#restricted-markets) for more information.
|
||||||
|
|
||||||
### I'm getting the "Exchange XXX does not support market orders." message and cannot run my strategy
|
### I'm getting the "Exchange XXX does not support market orders." message and cannot run my strategy
|
||||||
|
|
||||||
As the message says, your exchange does not support market orders and you have one of the [order types](configuration.md/#understand-order_types) set to "market". Your strategy was probably written with other exchanges in mind and sets "market" orders for "stoploss" orders, which is correct and preferable for most of the exchanges supporting market orders (but not for Gate.io).
|
As the message says, your exchange does not support market orders and you have one of the [order types](configuration.md/#understand-order_types) set to "market". Your strategy was probably written with other exchanges in mind and sets "market" orders for "stoploss" orders, which is correct and preferable for most of the exchanges supporting market orders (but not for Bittrex and Gate.io).
|
||||||
|
|
||||||
To fix this, redefine order types in the strategy to use "limit" instead of "market":
|
To fix this, redefine order types in the strategy to use "limit" instead of "market":
|
||||||
|
|
||||||
@@ -144,13 +129,6 @@ To fix this, redefine order types in the strategy to use "limit" instead of "mar
|
|||||||
|
|
||||||
The same fix should be applied in the configuration file, if order types are defined in your custom config rather than in the strategy.
|
The same fix should be applied in the configuration file, if order types are defined in your custom config rather than in the strategy.
|
||||||
|
|
||||||
### I'm trying to start the bot live, but get an API permission error
|
|
||||||
|
|
||||||
Errors like `Invalid API-key, IP, or permissions for action` mean exactly what they actually say.
|
|
||||||
Your API key is either invalid (copy/paste error? check for leading/trailing spaces in the config), expired, or the IP you're running the bot from is not enabled in the Exchange's API console.
|
|
||||||
Usually, the permission "Spot Trading" (or the equivalent in the exchange you use) will be necessary.
|
|
||||||
Futures will usually have to be enabled specifically.
|
|
||||||
|
|
||||||
### How do I search the bot logs for something?
|
### How do I search the bot logs for something?
|
||||||
|
|
||||||
By default, the bot writes its log into stderr stream. This is implemented this way so that you can easily separate the bot's diagnostics messages from Backtesting, Edge and Hyperopt results, output from other various Freqtrade utility sub-commands, as well as from the output of your custom `print()`'s you may have inserted into your strategy. So if you need to search the log messages with the grep utility, you need to redirect stderr to stdout and disregard stdout.
|
By default, the bot writes its log into stderr stream. This is implemented this way so that you can easily separate the bot's diagnostics messages from Backtesting, Edge and Hyperopt results, output from other various Freqtrade utility sub-commands, as well as from the output of your custom `print()`'s you may have inserted into your strategy. So if you need to search the log messages with the grep utility, you need to redirect stderr to stdout and disregard stdout.
|
||||||
@@ -199,8 +177,8 @@ The GPU improvements would only apply to pandas-native calculations - or ones wr
|
|||||||
For hyperopt, freqtrade is using scikit-optimize, which is built on top of scikit-learn.
|
For hyperopt, freqtrade is using scikit-optimize, which is built on top of scikit-learn.
|
||||||
Their statement about GPU support is [pretty clear](https://scikit-learn.org/stable/faq.html#will-you-add-gpu-support).
|
Their statement about GPU support is [pretty clear](https://scikit-learn.org/stable/faq.html#will-you-add-gpu-support).
|
||||||
|
|
||||||
GPU's also are only good at crunching numbers (floating point operations).
|
GPU's also are only good at crunching numbers (floating point operations).
|
||||||
For hyperopt, we need both number-crunching (find next parameters) and running python code (running backtesting).
|
For hyperopt, we need both number-crunching (find next parameters) and running python code (running backtesting).
|
||||||
As such, GPU's are not too well suited for most parts of hyperopt.
|
As such, GPU's are not too well suited for most parts of hyperopt.
|
||||||
|
|
||||||
The benefit of using GPU would therefore be pretty slim - and will not justify the complexity introduced by trying to add GPU support.
|
The benefit of using GPU would therefore be pretty slim - and will not justify the complexity introduced by trying to add GPU support.
|
||||||
@@ -241,9 +219,9 @@ already 8\*10^9\*10 evaluations. A roughly total of 80 billion evaluations.
|
|||||||
Did you run 100 000 evaluations? Congrats, you've done roughly 1 / 100 000 th
|
Did you run 100 000 evaluations? Congrats, you've done roughly 1 / 100 000 th
|
||||||
of the search space, assuming that the bot never tests the same parameters more than once.
|
of the search space, assuming that the bot never tests the same parameters more than once.
|
||||||
|
|
||||||
* The time it takes to run 1000 hyperopt epochs depends on things like: The available cpu, hard-disk, ram, timeframe, timerange, indicator settings, indicator count, amount of coins that hyperopt test strategies on and the resulting trade count - which can be 650 trades in a year or 100000 trades depending if the strategy aims for big profits by trading rarely or for many low profit trades.
|
* The time it takes to run 1000 hyperopt epochs depends on things like: The available cpu, hard-disk, ram, timeframe, timerange, indicator settings, indicator count, amount of coins that hyperopt test strategies on and the resulting trade count - which can be 650 trades in a year or 100000 trades depending if the strategy aims for big profits by trading rarely or for many low profit trades.
|
||||||
|
|
||||||
Example: 4% profit 650 times vs 0,3% profit a trade 10000 times in a year. If we assume you set the --timerange to 365 days.
|
Example: 4% profit 650 times vs 0,3% profit a trade 10000 times in a year. If we assume you set the --timerange to 365 days.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
`freqtrade --config config.json --strategy SampleStrategy --hyperopt SampleHyperopt -e 1000 --timerange 20190601-20200601`
|
`freqtrade --config config.json --strategy SampleStrategy --hyperopt SampleHyperopt -e 1000 --timerange 20190601-20200601`
|
||||||
@@ -257,26 +235,8 @@ The Edge module is mostly a result of brainstorming of [@mishaker](https://githu
|
|||||||
You can find further info on expectancy, win rate, risk management and position size in the following sources:
|
You can find further info on expectancy, win rate, risk management and position size in the following sources:
|
||||||
|
|
||||||
- https://www.tradeciety.com/ultimate-math-guide-for-traders/
|
- https://www.tradeciety.com/ultimate-math-guide-for-traders/
|
||||||
|
- http://www.vantharp.com/tharp-concepts/expectancy.asp
|
||||||
- https://samuraitradingacademy.com/trading-expectancy/
|
- https://samuraitradingacademy.com/trading-expectancy/
|
||||||
- https://www.learningmarkets.com/determining-expectancy-in-your-trading/
|
- https://www.learningmarkets.com/determining-expectancy-in-your-trading/
|
||||||
- https://www.lonestocktrader.com/make-money-trading-positive-expectancy/
|
- http://www.lonestocktrader.com/make-money-trading-positive-expectancy/
|
||||||
- https://www.babypips.com/trading/trade-expectancy-matter
|
- https://www.babypips.com/trading/trade-expectancy-matter
|
||||||
|
|
||||||
## Official channels
|
|
||||||
|
|
||||||
Freqtrade is using exclusively the following official channels:
|
|
||||||
|
|
||||||
* [Freqtrade discord server](https://discord.gg/p7nuUNVfP7)
|
|
||||||
* [Freqtrade documentation (https://freqtrade.io)](https://freqtrade.io)
|
|
||||||
* [Freqtrade github organization](https://github.com/freqtrade)
|
|
||||||
|
|
||||||
Nobody affiliated with the freqtrade project will ask you about your exchange keys or anything else exposing your funds to exploitation.
|
|
||||||
Should you be asked to expose your exchange keys or send funds to some random wallet, then please don't follow these instructions.
|
|
||||||
|
|
||||||
Failing to follow these guidelines will not be responsibility of freqtrade.
|
|
||||||
|
|
||||||
## "Freqtrade token"
|
|
||||||
|
|
||||||
Freqtrade does not have a Crypto token offering.
|
|
||||||
|
|
||||||
Token offerings you find on the internet referring Freqtrade, FreqAI or freqUI must be considered to be a scam, trying to exploit freqtrade's popularity for their own, nefarious gains.
|
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
# FreqUI
|
|
||||||
|
|
||||||
Freqtrade provides a builtin webserver, which can serve [FreqUI](https://github.com/freqtrade/frequi), the freqtrade frontend.
|
|
||||||
|
|
||||||
By default, the UI is automatically installed as part of the installation (script, docker).
|
|
||||||
freqUI can also be manually installed by using the `freqtrade install-ui` command.
|
|
||||||
This same command can also be used to update freqUI to new new releases.
|
|
||||||
|
|
||||||
Once the bot is started in trade / dry-run mode (with `freqtrade trade`) - the UI will be available under the configured API port (by default `http://127.0.0.1:8080`).
|
|
||||||
|
|
||||||
??? Note "Looking to contribute to freqUI?"
|
|
||||||
Developers should not use this method, but instead clone the corresponding use the method described in the [freqUI repository](https://github.com/freqtrade/frequi) to get the source-code of freqUI. A working installation of node will be required to build the frontend.
|
|
||||||
|
|
||||||
!!! tip "freqUI is not required to run freqtrade"
|
|
||||||
freqUI is an optional component of freqtrade, and is not required to run the bot.
|
|
||||||
It is a frontend that can be used to monitor the bot and to interact with it - but freqtrade itself will work perfectly fine without it.
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
FreqUI does not have it's own configuration file - but assumes a working setup for the [rest-api](rest-api.md) is available.
|
|
||||||
Please refer to the corresponding documentation page to get setup with freqUI
|
|
||||||
|
|
||||||
## UI
|
|
||||||
|
|
||||||
FreqUI is a modern, responsive web application that can be used to monitor and interact with your bot.
|
|
||||||
|
|
||||||
FreqUI provides a light, as well as a dark theme.
|
|
||||||
Themes can be easily switched via a prominent button at the top of the page.
|
|
||||||
The theme of the screenshots on this page will adapt to the selected documentation Theme, so to see the dark (or light) version, please switch the theme of the Documentation.
|
|
||||||
|
|
||||||
### Login
|
|
||||||
|
|
||||||
The below screenshot shows the login screen of freqUI.
|
|
||||||
|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
!!! Hint "CORS"
|
|
||||||
The Cors error shown in this screenshot is due to the fact that the UI is running on a different port than the API, and [CORS](#cors) has not been setup correctly yet.
|
|
||||||
|
|
||||||
### Trade view
|
|
||||||
|
|
||||||
The trade view allows you to visualize the trades that the bot is making and to interact with the bot.
|
|
||||||
On this page, you can also interact with the bot by starting and stopping it and - if configured - force trade entries and exits.
|
|
||||||
|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
### Plot Configurator
|
|
||||||
|
|
||||||
FreqUI Plots can be configured either via a `plot_config` configuration object in the strategy (which can be loaded via "from strategy" button) or via the UI.
|
|
||||||
Multiple plot configurations can be created and switched at will - allowing for flexible, different views into your charts.
|
|
||||||
|
|
||||||
The plot configuration can be accessed via the "Plot Configurator" (Cog icon) button in the top right corner of the trade view.
|
|
||||||
|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
### Settings
|
|
||||||
|
|
||||||
|
|
||||||
Several UI related settings can be changed by accessing the settings page.
|
|
||||||
|
|
||||||
Things you can change (among others):
|
|
||||||
|
|
||||||
* Timezone of the UI
|
|
||||||
* Visualization of open trades as part of the favicon (browser tab)
|
|
||||||
* Candle colors (up/down -> red/green)
|
|
||||||
* Enable / disable in-app notification types
|
|
||||||
|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
## Backtesting
|
|
||||||
|
|
||||||
When freqtrade is started in [webserver mode](utils.md#webserver-mode) (freqtrade started with `freqtrade webserver`), the backtesting view becomes available.
|
|
||||||
This view allows you to backtest strategies and visualize the results.
|
|
||||||
|
|
||||||
You can also load and visualize previous backtest results, as well as compare the results with each other.
|
|
||||||
|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
--8<-- "includes/cors.md"
|
|
||||||
@@ -1,421 +0,0 @@
|
|||||||
# Configuration
|
|
||||||
|
|
||||||
FreqAI is configured through the typical [Freqtrade config file](configuration.md) and the standard [Freqtrade strategy](strategy-customization.md). Examples of FreqAI config and strategy files can be found in `config_examples/config_freqai.example.json` and `freqtrade/templates/FreqaiExampleStrategy.py`, respectively.
|
|
||||||
|
|
||||||
## Setting up the configuration file
|
|
||||||
|
|
||||||
Although there are plenty of additional parameters to choose from, as highlighted in the [parameter table](freqai-parameter-table.md#parameter-table), a FreqAI config must at minimum include the following parameters (the parameter values are only examples):
|
|
||||||
|
|
||||||
```json
|
|
||||||
"freqai": {
|
|
||||||
"enabled": true,
|
|
||||||
"purge_old_models": 2,
|
|
||||||
"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,
|
|
||||||
"indicator_periods_candles": [10, 20]
|
|
||||||
},
|
|
||||||
"data_split_parameters" : {
|
|
||||||
"test_size": 0.25
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
A full example config is available in `config_examples/config_freqai.example.json`.
|
|
||||||
|
|
||||||
!!! Note
|
|
||||||
The `identifier` is commonly overlooked by newcomers, however, this value plays an important role in your configuration. This value is a unique ID that you choose to describe one of your runs. Keeping it the same allows you to maintain crash resilience as well as faster backtesting. As soon as you want to try a new run (new features, new model, etc.), you should change this value (or delete the `user_data/models/unique-id` folder. More details available in the [parameter table](freqai-parameter-table.md#feature-parameters).
|
|
||||||
|
|
||||||
## Building a FreqAI strategy
|
|
||||||
|
|
||||||
The FreqAI strategy requires including the following lines of code in the standard [Freqtrade strategy](strategy-customization.md):
|
|
||||||
|
|
||||||
```python
|
|
||||||
# user should define the maximum startup candle count (the largest number of candles
|
|
||||||
# passed to any single indicator)
|
|
||||||
startup_candle_count: int = 20
|
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
||||||
|
|
||||||
# the model will return all labels created by user in `set_freqai_targets()`
|
|
||||||
# (& appended targets), an indication of whether or not the prediction should be accepted,
|
|
||||||
# the target mean/std values for each of the labels created by user in
|
|
||||||
# `set_freqai_targets()` for each training period.
|
|
||||||
|
|
||||||
dataframe = self.freqai.start(dataframe, metadata, self)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def feature_engineering_expand_all(self, dataframe: DataFrame, period, **kwargs) -> DataFrame:
|
|
||||||
"""
|
|
||||||
*Only functional with FreqAI enabled strategies*
|
|
||||||
This function will automatically expand the defined features on the config defined
|
|
||||||
`indicator_periods_candles`, `include_timeframes`, `include_shifted_candles`, and
|
|
||||||
`include_corr_pairs`. In other words, a single feature defined in this function
|
|
||||||
will automatically expand to a total of
|
|
||||||
`indicator_periods_candles` * `include_timeframes` * `include_shifted_candles` *
|
|
||||||
`include_corr_pairs` numbers of features added to the model.
|
|
||||||
|
|
||||||
All features must be prepended with `%` to be recognized by FreqAI internals.
|
|
||||||
|
|
||||||
:param df: strategy dataframe which will receive the features
|
|
||||||
:param period: period of the indicator - usage example:
|
|
||||||
dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period)
|
|
||||||
"""
|
|
||||||
|
|
||||||
dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
|
|
||||||
dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period)
|
|
||||||
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
|
|
||||||
dataframe["%-sma-period"] = ta.SMA(dataframe, timeperiod=period)
|
|
||||||
dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def feature_engineering_expand_basic(self, dataframe: DataFrame, **kwargs) -> DataFrame:
|
|
||||||
"""
|
|
||||||
*Only functional with FreqAI enabled strategies*
|
|
||||||
This function will automatically expand the defined features on the config defined
|
|
||||||
`include_timeframes`, `include_shifted_candles`, and `include_corr_pairs`.
|
|
||||||
In other words, a single feature defined in this function
|
|
||||||
will automatically expand to a total of
|
|
||||||
`include_timeframes` * `include_shifted_candles` * `include_corr_pairs`
|
|
||||||
numbers of features added to the model.
|
|
||||||
|
|
||||||
Features defined here will *not* be automatically duplicated on user defined
|
|
||||||
`indicator_periods_candles`
|
|
||||||
|
|
||||||
All features must be prepended with `%` to be recognized by FreqAI internals.
|
|
||||||
|
|
||||||
:param df: strategy dataframe which will receive the features
|
|
||||||
dataframe["%-pct-change"] = dataframe["close"].pct_change()
|
|
||||||
dataframe["%-ema-200"] = ta.EMA(dataframe, timeperiod=200)
|
|
||||||
"""
|
|
||||||
dataframe["%-pct-change"] = dataframe["close"].pct_change()
|
|
||||||
dataframe["%-raw_volume"] = dataframe["volume"]
|
|
||||||
dataframe["%-raw_price"] = dataframe["close"]
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def feature_engineering_standard(self, dataframe: DataFrame, **kwargs) -> DataFrame:
|
|
||||||
"""
|
|
||||||
*Only functional with FreqAI enabled strategies*
|
|
||||||
This optional function will be called once with the dataframe of the base timeframe.
|
|
||||||
This is the final function to be called, which means that the dataframe entering this
|
|
||||||
function will contain all the features and columns created by all other
|
|
||||||
freqai_feature_engineering_* functions.
|
|
||||||
|
|
||||||
This function is a good place to do custom exotic feature extractions (e.g. tsfresh).
|
|
||||||
This function is a good place for any feature that should not be auto-expanded upon
|
|
||||||
(e.g. day of the week).
|
|
||||||
|
|
||||||
All features must be prepended with `%` to be recognized by FreqAI internals.
|
|
||||||
|
|
||||||
:param df: strategy dataframe which will receive the features
|
|
||||||
usage example: dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7
|
|
||||||
"""
|
|
||||||
dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7
|
|
||||||
dataframe["%-hour_of_day"] = (dataframe["date"].dt.hour + 1) / 25
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def set_freqai_targets(self, dataframe: DataFrame, **kwargs) -> DataFrame:
|
|
||||||
"""
|
|
||||||
*Only functional with FreqAI enabled strategies*
|
|
||||||
Required function to set the targets for the model.
|
|
||||||
All targets must be prepended with `&` to be recognized by the FreqAI internals.
|
|
||||||
|
|
||||||
:param df: strategy dataframe which will receive the targets
|
|
||||||
usage example: dataframe["&-target"] = dataframe["close"].shift(-1) / dataframe["close"]
|
|
||||||
"""
|
|
||||||
dataframe["&-s_close"] = (
|
|
||||||
dataframe["close"]
|
|
||||||
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
|
|
||||||
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
|
|
||||||
.mean()
|
|
||||||
/ dataframe["close"]
|
|
||||||
- 1
|
|
||||||
)
|
|
||||||
return dataframe
|
|
||||||
```
|
|
||||||
|
|
||||||
Notice how the `feature_engineering_*()` is where [features](freqai-feature-engineering.md#feature-engineering) are added. Meanwhile `set_freqai_targets()` adds the labels/targets. A full example strategy is available in `templates/FreqaiExampleStrategy.py`.
|
|
||||||
|
|
||||||
!!! Note
|
|
||||||
The `self.freqai.start()` function cannot be called outside the `populate_indicators()`.
|
|
||||||
|
|
||||||
!!! Note
|
|
||||||
Features **must** be defined in `feature_engineering_*()`. Defining FreqAI features in `populate_indicators()`
|
|
||||||
will cause the algorithm to fail in live/dry mode. In order to add generalized features that are not associated with a specific pair or timeframe, you should use `feature_engineering_standard()`
|
|
||||||
(as exemplified in `freqtrade/templates/FreqaiExampleStrategy.py`).
|
|
||||||
|
|
||||||
## Important dataframe key patterns
|
|
||||||
|
|
||||||
Below are the values you can expect to include/use inside a typical strategy dataframe (`df[]`):
|
|
||||||
|
|
||||||
| DataFrame Key | Description |
|
|
||||||
|------------|-------------|
|
|
||||||
| `df['&*']` | Any dataframe column prepended with `&` in `set_freqai_targets()` is treated as a training target (label) inside FreqAI (typically following the naming convention `&-s*`). For example, to predict the close price 40 candles into the future, you would set `df['&-s_close'] = df['close'].shift(-self.freqai_info["feature_parameters"]["label_period_candles"])` with `"label_period_candles": 40` in the config. FreqAI makes the predictions and gives them back under the same key (`df['&-s_close']`) to be used in `populate_entry/exit_trend()`. <br> **Datatype:** Depends on the output of the model.
|
|
||||||
| `df['&*_std/mean']` | Standard deviation and mean values of the defined labels during training (or live tracking with `fit_live_predictions_candles`). Commonly used to understand the rarity of a prediction (use the z-score as shown in `templates/FreqaiExampleStrategy.py` and explained [here](#creating-a-dynamic-target-threshold) to evaluate how often a particular prediction was observed during training or historically with `fit_live_predictions_candles`). <br> **Datatype:** Float.
|
|
||||||
| `df['do_predict']` | Indication of an outlier data point. The return value is integer between -2 and 2, which lets you know if the prediction is trustworthy or not. `do_predict==1` means that the prediction is trustworthy. If the Dissimilarity Index (DI, see details [here](freqai-feature-engineering.md#identifying-outliers-with-the-dissimilarity-index-di)) of the input data point is above the threshold defined in the config, FreqAI will subtract 1 from `do_predict`, resulting in `do_predict==0`. If `use_SVM_to_remove_outliers` is active, the Support Vector Machine (SVM, see details [here](freqai-feature-engineering.md#identifying-outliers-using-a-support-vector-machine-svm)) may also detect outliers in training and prediction data. In this case, the SVM will also subtract 1 from `do_predict`. If the input data point was considered an outlier by the SVM but not by the DI, or vice versa, the result will be `do_predict==0`. If both the DI and the SVM considers the input data point to be an outlier, the result will be `do_predict==-1`. As with the SVM, if `use_DBSCAN_to_remove_outliers` is active, DBSCAN (see details [here](freqai-feature-engineering.md#identifying-outliers-with-dbscan)) may also detect outliers and subtract 1 from `do_predict`. Hence, if both the SVM and DBSCAN are active and identify a datapoint that was above the DI threshold as an outlier, the result will be `do_predict==-2`. A particular case is when `do_predict == 2`, which means that the model has expired due to exceeding `expired_hours`. <br> **Datatype:** Integer between -2 and 2.
|
|
||||||
| `df['DI_values']` | Dissimilarity Index (DI) values are proxies for the level of confidence FreqAI has in the prediction. A lower DI means the prediction is close to the training data, i.e., higher prediction confidence. See details about the DI [here](freqai-feature-engineering.md#identifying-outliers-with-the-dissimilarity-index-di). <br> **Datatype:** Float.
|
|
||||||
| `df['%*']` | Any dataframe column prepended with `%` in `feature_engineering_*()` is treated as a training feature. For example, you can include the RSI in the training feature set (similar to in `templates/FreqaiExampleStrategy.py`) by setting `df['%-rsi']`. See more details on how this is done [here](freqai-feature-engineering.md). <br> **Note:** Since the number of features prepended with `%` can multiply very quickly (10s of thousands of features are easily engineered using the multiplictative functionality of, e.g., `include_shifted_candles` and `include_timeframes` as described in the [parameter table](freqai-parameter-table.md)), these features are removed from the dataframe that is returned from FreqAI to the strategy. To keep a particular type of feature for plotting purposes, you would prepend it with `%%` (see details below). <br> **Datatype:** Depends on the feature created by the user.
|
|
||||||
| `df['%%*']` | Any dataframe column prepended with `%%` in `feature_engineering_*()` is treated as a training feature, just the same as the above `%` prepend. However, in this case, the features are returned back to the strategy for FreqUI/plot-dataframe plotting and monitoring in Dry/Live/Backtesting <br> **Datatype:** Depends on the feature created by the user. Please note that features created in `feature_engineering_expand()` will have automatic FreqAI naming schemas depending on the expansions that you configured (i.e. `include_timeframes`, `include_corr_pairlist`, `indicators_periods_candles`, `include_shifted_candles`). So if you want to plot `%%-rsi` from `feature_engineering_expand_all()`, the final naming scheme for your plotting config would be: `%%-rsi-period_10_ETH/USDT:USDT_1h` for the `rsi` feature with `period=10`, `timeframe=1h`, and `pair=ETH/USDT:USDT` (the `:USDT` is added if you are using futures pairs). It is useful to simply add `print(dataframe.columns)` in your `populate_indicators()` after `self.freqai.start()` to see the full list of available features that are returned to the strategy for plotting purposes.
|
|
||||||
|
|
||||||
## Setting the `startup_candle_count`
|
|
||||||
|
|
||||||
The `startup_candle_count` in the FreqAI strategy needs to be set up in the same way as in the standard Freqtrade strategy (see details [here](strategy-customization.md#strategy-startup-period)). This value is used by Freqtrade to ensure that a sufficient amount of data is provided when calling the `dataprovider`, to avoid any NaNs at the beginning of the first training. You can easily set this value by identifying the longest period (in candle units) which is passed to the indicator creation functions (e.g., TA-Lib functions). In the presented example, `startup_candle_count` is 20 since this is the maximum value in `indicators_periods_candles`.
|
|
||||||
|
|
||||||
!!! Note
|
|
||||||
There are instances where the TA-Lib functions actually require more data than just the passed `period` or else the feature dataset gets populated with NaNs. Anecdotally, multiplying the `startup_candle_count` by 2 always leads to a fully NaN free training dataset. Hence, it is typically safest to multiply the expected `startup_candle_count` by 2. Look out for this log message to confirm that the data is clean:
|
|
||||||
|
|
||||||
```
|
|
||||||
2022-08-31 15:14:04 - freqtrade.freqai.data_kitchen - INFO - dropped 0 training points due to NaNs in populated dataset 4319.
|
|
||||||
```
|
|
||||||
|
|
||||||
## Creating a dynamic target threshold
|
|
||||||
|
|
||||||
Deciding when to enter or exit a trade can be done in a dynamic way to reflect current market conditions. FreqAI allows you to return additional information from the training of a model (more info [here](freqai-feature-engineering.md#returning-additional-info-from-training)). For example, the `&*_std/mean` return values describe the statistical distribution of the target/label *during the most recent training*. Comparing a given prediction to these values allows you to know the rarity of the prediction. In `templates/FreqaiExampleStrategy.py`, the `target_roi` and `sell_roi` are defined to be 1.25 z-scores away from the mean which causes predictions that are closer to the mean to be filtered out.
|
|
||||||
|
|
||||||
```python
|
|
||||||
dataframe["target_roi"] = dataframe["&-s_close_mean"] + dataframe["&-s_close_std"] * 1.25
|
|
||||||
dataframe["sell_roi"] = dataframe["&-s_close_mean"] - dataframe["&-s_close_std"] * 1.25
|
|
||||||
```
|
|
||||||
|
|
||||||
To consider the population of *historical predictions* for creating the dynamic target instead of information from the training as discussed above, you would set `fit_live_predictions_candles` in the config to the number of historical prediction candles you wish to use to generate target statistics.
|
|
||||||
|
|
||||||
```json
|
|
||||||
"freqai": {
|
|
||||||
"fit_live_predictions_candles": 300,
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
If this value is set, FreqAI will initially use the predictions from the training data and subsequently begin introducing real prediction data as it is generated. FreqAI will save this historical data to be reloaded if you stop and restart a model with the same `identifier`.
|
|
||||||
|
|
||||||
## Using different prediction models
|
|
||||||
|
|
||||||
FreqAI has multiple example prediction model libraries that are ready to be used as is via the flag `--freqaimodel`. These libraries include `CatBoost`, `LightGBM`, and `XGBoost` regression, classification, and multi-target models, and can be found in `freqai/prediction_models/`.
|
|
||||||
|
|
||||||
Regression and classification models differ in what targets they predict - a regression model will predict a target of continuous values, for example what price BTC will be at tomorrow, whilst a classifier will predict a target of discrete values, for example if the price of BTC will go up tomorrow or not. This means that you have to specify your targets differently depending on which model type you are using (see details [below](#setting-model-targets)).
|
|
||||||
|
|
||||||
All of the aforementioned model libraries implement gradient boosted decision tree algorithms. They all work on the principle of ensemble learning, where predictions from multiple simple learners are combined to get a final prediction that is more stable and generalized. The simple learners in this case are decision trees. Gradient boosting refers to the method of learning, where each simple learner is built in sequence - the subsequent learner is used to improve on the error from the previous learner. If you want to learn more about the different model libraries you can find the information in their respective docs:
|
|
||||||
|
|
||||||
* CatBoost: https://catboost.ai/en/docs/
|
|
||||||
* LightGBM: https://lightgbm.readthedocs.io/en/v3.3.2/#
|
|
||||||
* XGBoost: https://xgboost.readthedocs.io/en/stable/#
|
|
||||||
|
|
||||||
There are also numerous online articles describing and comparing the algorithms. Some relatively lightweight examples would be [CatBoost vs. LightGBM vs. XGBoost — Which is the best algorithm?](https://towardsdatascience.com/catboost-vs-lightgbm-vs-xgboost-c80f40662924#:~:text=In%20CatBoost%2C%20symmetric%20trees%2C%20or,the%20same%20depth%20can%20differ.) and [XGBoost, LightGBM or CatBoost — which boosting algorithm should I use?](https://medium.com/riskified-technology/xgboost-lightgbm-or-catboost-which-boosting-algorithm-should-i-use-e7fda7bb36bc). Keep in mind that the performance of each model is highly dependent on the application and so any reported metrics might not be true for your particular use of the model.
|
|
||||||
|
|
||||||
Apart from the models already available in FreqAI, it is also possible to customize and create your own prediction models using the `IFreqaiModel` class. You are encouraged to inherit `fit()`, `train()`, and `predict()` to customize various aspects of the training procedures. You can place custom FreqAI models in `user_data/freqaimodels` - and freqtrade will pick them up from there based on the provided `--freqaimodel` name - which has to correspond to the class name of your custom model.
|
|
||||||
Make sure to use unique names to avoid overriding built-in models.
|
|
||||||
|
|
||||||
### Setting model targets
|
|
||||||
|
|
||||||
#### Regressors
|
|
||||||
|
|
||||||
If you are using a regressor, you need to specify a target that has continuous values. FreqAI includes a variety of regressors, such as the `CatboostRegressor`via the flag `--freqaimodel CatboostRegressor`. An example of how you could set a regression target for predicting the price 100 candles into the future would be
|
|
||||||
|
|
||||||
```python
|
|
||||||
df['&s-close_price'] = df['close'].shift(-100)
|
|
||||||
```
|
|
||||||
|
|
||||||
If you want to predict multiple targets, you need to define multiple labels using the same syntax as shown above.
|
|
||||||
|
|
||||||
#### Classifiers
|
|
||||||
|
|
||||||
If you are using a classifier, you need to specify a target that has discrete values. FreqAI includes a variety of classifiers, such as the `CatboostClassifier` via the flag `--freqaimodel CatboostClassifier`. If you elects to use a classifier, the classes need to be set using strings. For example, if you want to predict if the price 100 candles into the future goes up or down you would set
|
|
||||||
|
|
||||||
```python
|
|
||||||
df['&s-up_or_down'] = np.where( df["close"].shift(-100) > df["close"], 'up', 'down')
|
|
||||||
```
|
|
||||||
|
|
||||||
If you want to predict multiple targets you must specify all labels in the same label column. You could, for example, add the label `same` to define where the price was unchanged by setting
|
|
||||||
|
|
||||||
```python
|
|
||||||
df['&s-up_or_down'] = np.where( df["close"].shift(-100) > df["close"], 'up', 'down')
|
|
||||||
df['&s-up_or_down'] = np.where( df["close"].shift(-100) == df["close"], 'same', df['&s-up_or_down'])
|
|
||||||
```
|
|
||||||
|
|
||||||
## PyTorch Module
|
|
||||||
|
|
||||||
### Quick start
|
|
||||||
|
|
||||||
The easiest way to quickly run a pytorch model is with the following command (for regression task):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
freqtrade trade --config config_examples/config_freqai.example.json --strategy FreqaiExampleStrategy --freqaimodel PyTorchMLPRegressor --strategy-path freqtrade/templates
|
|
||||||
```
|
|
||||||
|
|
||||||
!!! Note "Installation/docker"
|
|
||||||
The PyTorch module requires large packages such as `torch`, which should be explicitly requested during `./setup.sh -i` by answering "y" to the question "Do you also want dependencies for freqai-rl or PyTorch (~700mb additional space required) [y/N]?".
|
|
||||||
Users who prefer docker should ensure they use the docker image appended with `_freqaitorch`.
|
|
||||||
We do provide an explicit docker-compose file for this in `docker/docker-compose-freqai.yml` - which can be used via `docker compose -f docker/docker-compose-freqai.yml run ...` - or can be copied to replace the original docker file.
|
|
||||||
This docker-compose file also contains a (disabled) section to enable GPU resources within docker containers. This obviously assumes the system has GPU resources available.
|
|
||||||
|
|
||||||
### Structure
|
|
||||||
|
|
||||||
#### Model
|
|
||||||
|
|
||||||
You can construct your own Neural Network architecture in PyTorch by simply defining your `nn.Module` class inside your custom [`IFreqaiModel` file](#using-different-prediction-models) and then using that class in your `def train()` function. Here is an example of logistic regression model implementation using PyTorch (should be used with nn.BCELoss criterion) for classification tasks.
|
|
||||||
|
|
||||||
```python
|
|
||||||
|
|
||||||
class LogisticRegression(nn.Module):
|
|
||||||
def __init__(self, input_size: int):
|
|
||||||
super().__init__()
|
|
||||||
# Define your layers
|
|
||||||
self.linear = nn.Linear(input_size, 1)
|
|
||||||
self.activation = nn.Sigmoid()
|
|
||||||
|
|
||||||
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
|
||||||
# Define the forward pass
|
|
||||||
out = self.linear(x)
|
|
||||||
out = self.activation(out)
|
|
||||||
return out
|
|
||||||
|
|
||||||
class MyCoolPyTorchClassifier(BasePyTorchClassifier):
|
|
||||||
"""
|
|
||||||
This is a custom IFreqaiModel showing how a user might setup their own
|
|
||||||
custom Neural Network architecture for their training.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@property
|
|
||||||
def data_convertor(self) -> PyTorchDataConvertor:
|
|
||||||
return DefaultPyTorchDataConvertor(target_tensor_type=torch.float)
|
|
||||||
|
|
||||||
def __init__(self, **kwargs) -> None:
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
config = self.freqai_info.get("model_training_parameters", {})
|
|
||||||
self.learning_rate: float = config.get("learning_rate", 3e-4)
|
|
||||||
self.model_kwargs: Dict[str, Any] = config.get("model_kwargs", {})
|
|
||||||
self.trainer_kwargs: Dict[str, Any] = config.get("trainer_kwargs", {})
|
|
||||||
|
|
||||||
def fit(self, data_dictionary: Dict, dk: FreqaiDataKitchen, **kwargs) -> Any:
|
|
||||||
"""
|
|
||||||
User sets up the training and test data to fit their desired model here
|
|
||||||
:param data_dictionary: the dictionary holding all data for train, test,
|
|
||||||
labels, weights
|
|
||||||
:param dk: The datakitchen object for the current coin/model
|
|
||||||
"""
|
|
||||||
|
|
||||||
class_names = self.get_class_names()
|
|
||||||
self.convert_label_column_to_int(data_dictionary, dk, class_names)
|
|
||||||
n_features = data_dictionary["train_features"].shape[-1]
|
|
||||||
model = LogisticRegression(
|
|
||||||
input_dim=n_features
|
|
||||||
)
|
|
||||||
model.to(self.device)
|
|
||||||
optimizer = torch.optim.AdamW(model.parameters(), lr=self.learning_rate)
|
|
||||||
criterion = torch.nn.CrossEntropyLoss()
|
|
||||||
init_model = self.get_init_model(dk.pair)
|
|
||||||
trainer = PyTorchModelTrainer(
|
|
||||||
model=model,
|
|
||||||
optimizer=optimizer,
|
|
||||||
criterion=criterion,
|
|
||||||
model_meta_data={"class_names": class_names},
|
|
||||||
device=self.device,
|
|
||||||
init_model=init_model,
|
|
||||||
data_convertor=self.data_convertor,
|
|
||||||
**self.trainer_kwargs,
|
|
||||||
)
|
|
||||||
trainer.fit(data_dictionary, self.splits)
|
|
||||||
return trainer
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Trainer
|
|
||||||
|
|
||||||
The `PyTorchModelTrainer` performs the idiomatic PyTorch train loop:
|
|
||||||
Define our model, loss function, and optimizer, and then move them to the appropriate device (GPU or CPU). Inside the loop, we iterate through the batches in the dataloader, move the data to the device, compute the prediction and loss, backpropagate, and update the model parameters using the optimizer.
|
|
||||||
|
|
||||||
In addition, the trainer is responsible for the following:
|
|
||||||
- saving and loading the model
|
|
||||||
- converting the data from `pandas.DataFrame` to `torch.Tensor`.
|
|
||||||
|
|
||||||
#### Integration with Freqai module
|
|
||||||
|
|
||||||
Like all freqai models, PyTorch models inherit `IFreqaiModel`. `IFreqaiModel` declares three abstract methods: `train`, `fit`, and `predict`. we implement these methods in three levels of hierarchy.
|
|
||||||
From top to bottom:
|
|
||||||
|
|
||||||
1. `BasePyTorchModel` - Implements the `train` method. all `BasePyTorch*` inherit it. responsible for general data preparation (e.g., data normalization) and calling the `fit` method. Sets `device` attribute used by children classes. Sets `model_type` attribute used by the parent class.
|
|
||||||
2. `BasePyTorch*` - Implements the `predict` method. Here, the `*` represents a group of algorithms, such as classifiers or regressors. responsible for data preprocessing, predicting, and postprocessing if needed.
|
|
||||||
3. `PyTorch*Classifier` / `PyTorch*Regressor` - implements the `fit` method. responsible for the main train flaw, where we initialize the trainer and model objects.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
#### Full example
|
|
||||||
|
|
||||||
Building a PyTorch regressor using MLP (multilayer perceptron) model, MSELoss criterion, and AdamW optimizer.
|
|
||||||
|
|
||||||
```python
|
|
||||||
class PyTorchMLPRegressor(BasePyTorchRegressor):
|
|
||||||
def __init__(self, **kwargs) -> None:
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
config = self.freqai_info.get("model_training_parameters", {})
|
|
||||||
self.learning_rate: float = config.get("learning_rate", 3e-4)
|
|
||||||
self.model_kwargs: Dict[str, Any] = config.get("model_kwargs", {})
|
|
||||||
self.trainer_kwargs: Dict[str, Any] = config.get("trainer_kwargs", {})
|
|
||||||
|
|
||||||
def fit(self, data_dictionary: Dict, dk: FreqaiDataKitchen, **kwargs) -> Any:
|
|
||||||
n_features = data_dictionary["train_features"].shape[-1]
|
|
||||||
model = PyTorchMLPModel(
|
|
||||||
input_dim=n_features,
|
|
||||||
output_dim=1,
|
|
||||||
**self.model_kwargs
|
|
||||||
)
|
|
||||||
model.to(self.device)
|
|
||||||
optimizer = torch.optim.AdamW(model.parameters(), lr=self.learning_rate)
|
|
||||||
criterion = torch.nn.MSELoss()
|
|
||||||
init_model = self.get_init_model(dk.pair)
|
|
||||||
trainer = PyTorchModelTrainer(
|
|
||||||
model=model,
|
|
||||||
optimizer=optimizer,
|
|
||||||
criterion=criterion,
|
|
||||||
device=self.device,
|
|
||||||
init_model=init_model,
|
|
||||||
target_tensor_type=torch.float,
|
|
||||||
**self.trainer_kwargs,
|
|
||||||
)
|
|
||||||
trainer.fit(data_dictionary)
|
|
||||||
return trainer
|
|
||||||
```
|
|
||||||
|
|
||||||
Here we create a `PyTorchMLPRegressor` class that implements the `fit` method. The `fit` method specifies the training building blocks: model, optimizer, criterion, and trainer. We inherit both `BasePyTorchRegressor` and `BasePyTorchModel`, where the former implements the `predict` method that is suitable for our regression task, and the latter implements the train method.
|
|
||||||
|
|
||||||
??? Note "Setting Class Names for Classifiers"
|
|
||||||
When using classifiers, the user must declare the class names (or targets) by overriding the `IFreqaiModel.class_names` attribute. This is achieved by setting `self.freqai.class_names` in the FreqAI strategy inside the `set_freqai_targets` method.
|
|
||||||
|
|
||||||
For example, if you are using a binary classifier to predict price movements as up or down, you can set the class names as follows:
|
|
||||||
```python
|
|
||||||
def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs) -> DataFrame:
|
|
||||||
self.freqai.class_names = ["down", "up"]
|
|
||||||
dataframe['&s-up_or_down'] = np.where(dataframe["close"].shift(-100) >
|
|
||||||
dataframe["close"], 'up', 'down')
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
```
|
|
||||||
To see a full example, you can refer to the [classifier test strategy class](https://github.com/freqtrade/freqtrade/blob/develop/tests/strategy/strats/freqai_test_classifier.py).
|
|
||||||
|
|
||||||
|
|
||||||
#### Improving performance with `torch.compile()`
|
|
||||||
|
|
||||||
Torch provides a `torch.compile()` method that can be used to improve performance for specific GPU hardware. More details can be found [here](https://pytorch.org/tutorials/intermediate/torch_compile_tutorial.html). In brief, you simply wrap your `model` in `torch.compile()`:
|
|
||||||
|
|
||||||
|
|
||||||
```python
|
|
||||||
model = PyTorchMLPModel(
|
|
||||||
input_dim=n_features,
|
|
||||||
output_dim=1,
|
|
||||||
**self.model_kwargs
|
|
||||||
)
|
|
||||||
model.to(self.device)
|
|
||||||
model = torch.compile(model)
|
|
||||||
```
|
|
||||||
|
|
||||||
Then proceed to use the model as normal. Keep in mind that doing this will remove eager execution, which means errors and tracebacks will not be informative.
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
# Development
|
|
||||||
|
|
||||||
## Project architecture
|
|
||||||
|
|
||||||
The architecture and functions of FreqAI are generalized to encourages development of unique features, functions, models, etc.
|
|
||||||
|
|
||||||
The class structure and a detailed algorithmic overview is depicted in the following diagram:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
As shown, there are three distinct objects comprising FreqAI:
|
|
||||||
|
|
||||||
* **IFreqaiModel** - A singular persistent object containing all the necessary logic to collect, store, and process data, engineer features, run training, and inference models.
|
|
||||||
* **FreqaiDataKitchen** - A non-persistent object which is created uniquely for each unique asset/model. Beyond metadata, it also contains a variety of data processing tools.
|
|
||||||
* **FreqaiDataDrawer** - A singular persistent object containing all the historical predictions, models, and save/load methods.
|
|
||||||
|
|
||||||
There are a variety of built-in [prediction models](freqai-configuration.md#using-different-prediction-models) which inherit directly from `IFreqaiModel`. Each of these models have full access to all methods in `IFreqaiModel` and can therefore override any of those functions at will. However, advanced users will likely stick to overriding `fit()`, `train()`, `predict()`, and `data_cleaning_train/predict()`.
|
|
||||||
|
|
||||||
## Data handling
|
|
||||||
|
|
||||||
FreqAI aims to organize model files, prediction data, and meta data in a way that simplifies post-processing and enhances crash resilience by automatic data reloading. The data is saved in a file structure,`user_data_dir/models/`, which contains all the data associated with the trainings and backtests. The `FreqaiDataKitchen()` relies heavily on the file structure for proper training and inferencing and should therefore not be manually modified.
|
|
||||||
|
|
||||||
### File structure
|
|
||||||
|
|
||||||
The file structure is automatically generated based on the model `identifier` set in the [config](freqai-configuration.md#setting-up-the-configuration-file). The following structure shows where the data is stored for post processing:
|
|
||||||
|
|
||||||
| Structure | Description |
|
|
||||||
|-----------|-------------|
|
|
||||||
| `config_*.json` | A copy of the model specific configuration file. |
|
|
||||||
| `historic_predictions.pkl` | A file containing all historic predictions generated during the lifetime of the `identifier` model during live deployment. `historic_predictions.pkl` is used to reload the model after a crash or a config change. A backup file is always held in case of corruption on the main file. FreqAI **automatically** detects corruption and replaces the corrupted file with the backup. |
|
|
||||||
| `pair_dictionary.json` | A file containing the training queue as well as the on disk location of the most recently trained model. |
|
|
||||||
| `sub-train-*_TIMESTAMP` | A folder containing all the files associated with a single model, such as: <br>
|
|
||||||
|| `*_metadata.json` - Metadata for the model, such as normalization max/min, expected training feature list, etc. <br>
|
|
||||||
|| `*_model.*` - The model file saved to disk for reloading from a crash. Can be `joblib` (typical boosting libs), `zip` (stable_baselines), `hd5` (keras type), etc. <br>
|
|
||||||
|| `*_pca_object.pkl` - The [Principal component analysis (PCA)](freqai-feature-engineering.md#data-dimensionality-reduction-with-principal-component-analysis) transform (if `principal_component_analysis: True` is set in the config) which will be used to transform unseen prediction features. <br>
|
|
||||||
|| `*_svm_model.pkl` - The [Support Vector Machine (SVM)](freqai-feature-engineering.md#identifying-outliers-using-a-support-vector-machine-svm) model (if `use_SVM_to_remove_outliers: True` is set in the config) which is used to detect outliers in unseen prediction features. <br>
|
|
||||||
|| `*_trained_df.pkl` - The dataframe containing all the training features used to train the `identifier` model. This is used for computing the [Dissimilarity Index (DI)](freqai-feature-engineering.md#identifying-outliers-with-the-dissimilarity-index-di) and can also be used for post-processing. <br>
|
|
||||||
|| `*_trained_dates.df.pkl` - The dates associated with the `trained_df.pkl`, which is useful for post-processing. |
|
|
||||||
|
|
||||||
The example file structure would look like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
├── models
|
|
||||||
│ └── unique-id
|
|
||||||
│ ├── config_freqai.example.json
|
|
||||||
│ ├── historic_predictions.backup.pkl
|
|
||||||
│ ├── historic_predictions.pkl
|
|
||||||
│ ├── pair_dictionary.json
|
|
||||||
│ ├── sub-train-1INCH_1662821319
|
|
||||||
│ │ ├── cb_1inch_1662821319_metadata.json
|
|
||||||
│ │ ├── cb_1inch_1662821319_model.joblib
|
|
||||||
│ │ ├── cb_1inch_1662821319_pca_object.pkl
|
|
||||||
│ │ ├── cb_1inch_1662821319_svm_model.joblib
|
|
||||||
│ │ ├── cb_1inch_1662821319_trained_dates_df.pkl
|
|
||||||
│ │ └── cb_1inch_1662821319_trained_df.pkl
|
|
||||||
│ ├── sub-train-1INCH_1662821371
|
|
||||||
│ │ ├── cb_1inch_1662821371_metadata.json
|
|
||||||
│ │ ├── cb_1inch_1662821371_model.joblib
|
|
||||||
│ │ ├── cb_1inch_1662821371_pca_object.pkl
|
|
||||||
│ │ ├── cb_1inch_1662821371_svm_model.joblib
|
|
||||||
│ │ ├── cb_1inch_1662821371_trained_dates_df.pkl
|
|
||||||
│ │ └── cb_1inch_1662821371_trained_df.pkl
|
|
||||||
│ ├── sub-train-ADA_1662821344
|
|
||||||
│ │ ├── cb_ada_1662821344_metadata.json
|
|
||||||
│ │ ├── cb_ada_1662821344_model.joblib
|
|
||||||
│ │ ├── cb_ada_1662821344_pca_object.pkl
|
|
||||||
│ │ ├── cb_ada_1662821344_svm_model.joblib
|
|
||||||
│ │ ├── cb_ada_1662821344_trained_dates_df.pkl
|
|
||||||
│ │ └── cb_ada_1662821344_trained_df.pkl
|
|
||||||
│ └── sub-train-ADA_1662821399
|
|
||||||
│ ├── cb_ada_1662821399_metadata.json
|
|
||||||
│ ├── cb_ada_1662821399_model.joblib
|
|
||||||
│ ├── cb_ada_1662821399_pca_object.pkl
|
|
||||||
│ ├── cb_ada_1662821399_svm_model.joblib
|
|
||||||
│ ├── cb_ada_1662821399_trained_dates_df.pkl
|
|
||||||
│ └── cb_ada_1662821399_trained_df.pkl
|
|
||||||
|
|
||||||
```
|
|
||||||
@@ -1,408 +0,0 @@
|
|||||||
# Feature engineering
|
|
||||||
|
|
||||||
## Defining the features
|
|
||||||
|
|
||||||
Low level feature engineering is performed in the user strategy within a set of functions called `feature_engineering_*`. These function set the `base features` such as, `RSI`, `MFI`, `EMA`, `SMA`, time of day, volume, etc. The `base features` can be custom indicators or they can be imported from any technical-analysis library that you can find. FreqAI is equipped with a set of functions to simplify rapid large-scale feature engineering:
|
|
||||||
|
|
||||||
| Function | Description |
|
|
||||||
|---------------|-------------|
|
|
||||||
| `feature_engineering_expand_all()` | This optional function will automatically expand the defined features on the config defined `indicator_periods_candles`, `include_timeframes`, `include_shifted_candles`, and `include_corr_pairs`.
|
|
||||||
| `feature_engineering_expand_basic()` | This optional function will automatically expand the defined features on the config defined `include_timeframes`, `include_shifted_candles`, and `include_corr_pairs`. Note: this function does *not* expand across `indicator_periods_candles`.
|
|
||||||
| `feature_engineering_standard()` | This optional function will be called once with the dataframe of the base timeframe. This is the final function to be called, which means that the dataframe entering this function will contain all the features and columns from the base asset created by the other `feature_engineering_expand` functions. This function is a good place to do custom exotic feature extractions (e.g. tsfresh). This function is also a good place for any feature that should not be auto-expanded upon (e.g., day of the week).
|
|
||||||
| `set_freqai_targets()` | Required function to set the targets for the model. All targets must be prepended with `&` to be recognized by the FreqAI internals.
|
|
||||||
|
|
||||||
Meanwhile, high level feature engineering is handled within `"feature_parameters":{}` in the FreqAI config. Within this file, it is possible to decide large scale feature expansions on top of the `base_features` such as "including correlated pairs" or "including informative timeframes" or even "including recent candles."
|
|
||||||
|
|
||||||
It is advisable to start from the template `feature_engineering_*` functions in the source provided example strategy (found in `templates/FreqaiExampleStrategy.py`) to ensure that the feature definitions are following the correct conventions. Here is an example of how to set the indicators and labels in the strategy:
|
|
||||||
|
|
||||||
```python
|
|
||||||
def feature_engineering_expand_all(self, dataframe: DataFrame, period, metadata, **kwargs) -> DataFrame:
|
|
||||||
"""
|
|
||||||
*Only functional with FreqAI enabled strategies*
|
|
||||||
This function will automatically expand the defined features on the config defined
|
|
||||||
`indicator_periods_candles`, `include_timeframes`, `include_shifted_candles`, and
|
|
||||||
`include_corr_pairs`. In other words, a single feature defined in this function
|
|
||||||
will automatically expand to a total of
|
|
||||||
`indicator_periods_candles` * `include_timeframes` * `include_shifted_candles` *
|
|
||||||
`include_corr_pairs` numbers of features added to the model.
|
|
||||||
|
|
||||||
All features must be prepended with `%` to be recognized by FreqAI internals.
|
|
||||||
|
|
||||||
Access metadata such as the current pair/timeframe/period with:
|
|
||||||
|
|
||||||
`metadata["pair"]` `metadata["tf"]` `metadata["period"]`
|
|
||||||
|
|
||||||
:param df: strategy dataframe which will receive the features
|
|
||||||
:param period: period of the indicator - usage example:
|
|
||||||
:param metadata: metadata of current pair
|
|
||||||
dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period)
|
|
||||||
"""
|
|
||||||
|
|
||||||
dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
|
|
||||||
dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period)
|
|
||||||
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
|
|
||||||
dataframe["%-sma-period"] = ta.SMA(dataframe, timeperiod=period)
|
|
||||||
dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period)
|
|
||||||
|
|
||||||
bollinger = qtpylib.bollinger_bands(
|
|
||||||
qtpylib.typical_price(dataframe), window=period, stds=2.2
|
|
||||||
)
|
|
||||||
dataframe["bb_lowerband-period"] = bollinger["lower"]
|
|
||||||
dataframe["bb_middleband-period"] = bollinger["mid"]
|
|
||||||
dataframe["bb_upperband-period"] = bollinger["upper"]
|
|
||||||
|
|
||||||
dataframe["%-bb_width-period"] = (
|
|
||||||
dataframe["bb_upperband-period"]
|
|
||||||
- dataframe["bb_lowerband-period"]
|
|
||||||
) / dataframe["bb_middleband-period"]
|
|
||||||
dataframe["%-close-bb_lower-period"] = (
|
|
||||||
dataframe["close"] / dataframe["bb_lowerband-period"]
|
|
||||||
)
|
|
||||||
|
|
||||||
dataframe["%-roc-period"] = ta.ROC(dataframe, timeperiod=period)
|
|
||||||
|
|
||||||
dataframe["%-relative_volume-period"] = (
|
|
||||||
dataframe["volume"] / dataframe["volume"].rolling(period).mean()
|
|
||||||
)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata, **kwargs) -> DataFrame:
|
|
||||||
"""
|
|
||||||
*Only functional with FreqAI enabled strategies*
|
|
||||||
This function will automatically expand the defined features on the config defined
|
|
||||||
`include_timeframes`, `include_shifted_candles`, and `include_corr_pairs`.
|
|
||||||
In other words, a single feature defined in this function
|
|
||||||
will automatically expand to a total of
|
|
||||||
`include_timeframes` * `include_shifted_candles` * `include_corr_pairs`
|
|
||||||
numbers of features added to the model.
|
|
||||||
|
|
||||||
Features defined here will *not* be automatically duplicated on user defined
|
|
||||||
`indicator_periods_candles`
|
|
||||||
|
|
||||||
Access metadata such as the current pair/timeframe with:
|
|
||||||
|
|
||||||
`metadata["pair"]` `metadata["tf"]`
|
|
||||||
|
|
||||||
All features must be prepended with `%` to be recognized by FreqAI internals.
|
|
||||||
|
|
||||||
:param df: strategy dataframe which will receive the features
|
|
||||||
:param metadata: metadata of current pair
|
|
||||||
dataframe["%-pct-change"] = dataframe["close"].pct_change()
|
|
||||||
dataframe["%-ema-200"] = ta.EMA(dataframe, timeperiod=200)
|
|
||||||
"""
|
|
||||||
dataframe["%-pct-change"] = dataframe["close"].pct_change()
|
|
||||||
dataframe["%-raw_volume"] = dataframe["volume"]
|
|
||||||
dataframe["%-raw_price"] = dataframe["close"]
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def feature_engineering_standard(self, dataframe: DataFrame, metadata, **kwargs) -> DataFrame:
|
|
||||||
"""
|
|
||||||
*Only functional with FreqAI enabled strategies*
|
|
||||||
This optional function will be called once with the dataframe of the base timeframe.
|
|
||||||
This is the final function to be called, which means that the dataframe entering this
|
|
||||||
function will contain all the features and columns created by all other
|
|
||||||
freqai_feature_engineering_* functions.
|
|
||||||
|
|
||||||
This function is a good place to do custom exotic feature extractions (e.g. tsfresh).
|
|
||||||
This function is a good place for any feature that should not be auto-expanded upon
|
|
||||||
(e.g. day of the week).
|
|
||||||
|
|
||||||
Access metadata such as the current pair with:
|
|
||||||
|
|
||||||
`metadata["pair"]`
|
|
||||||
|
|
||||||
All features must be prepended with `%` to be recognized by FreqAI internals.
|
|
||||||
|
|
||||||
:param df: strategy dataframe which will receive the features
|
|
||||||
:param metadata: metadata of current pair
|
|
||||||
usage example: dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7
|
|
||||||
"""
|
|
||||||
dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7
|
|
||||||
dataframe["%-hour_of_day"] = (dataframe["date"].dt.hour + 1) / 25
|
|
||||||
return dataframe
|
|
||||||
|
|
||||||
def set_freqai_targets(self, dataframe: DataFrame, metadata, **kwargs) -> DataFrame:
|
|
||||||
"""
|
|
||||||
*Only functional with FreqAI enabled strategies*
|
|
||||||
Required function to set the targets for the model.
|
|
||||||
All targets must be prepended with `&` to be recognized by the FreqAI internals.
|
|
||||||
|
|
||||||
Access metadata such as the current pair with:
|
|
||||||
|
|
||||||
`metadata["pair"]`
|
|
||||||
|
|
||||||
:param df: strategy dataframe which will receive the targets
|
|
||||||
:param metadata: metadata of current pair
|
|
||||||
usage example: dataframe["&-target"] = dataframe["close"].shift(-1) / dataframe["close"]
|
|
||||||
"""
|
|
||||||
dataframe["&-s_close"] = (
|
|
||||||
dataframe["close"]
|
|
||||||
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
|
|
||||||
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
|
|
||||||
.mean()
|
|
||||||
/ dataframe["close"]
|
|
||||||
- 1
|
|
||||||
)
|
|
||||||
|
|
||||||
return dataframe
|
|
||||||
```
|
|
||||||
|
|
||||||
In the presented example, the user 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 `%`.
|
|
||||||
|
|
||||||
After having defined the `base features`, the next step is to expand upon them using the powerful `feature_parameters` in the configuration file:
|
|
||||||
|
|
||||||
```json
|
|
||||||
"freqai": {
|
|
||||||
//...
|
|
||||||
"feature_parameters" : {
|
|
||||||
"include_timeframes": ["5m","15m","4h"],
|
|
||||||
"include_corr_pairlist": [
|
|
||||||
"ETH/USD",
|
|
||||||
"LINK/USD",
|
|
||||||
"BNB/USD"
|
|
||||||
],
|
|
||||||
"label_period_candles": 24,
|
|
||||||
"include_shifted_candles": 2,
|
|
||||||
"indicator_periods_candles": [10, 20]
|
|
||||||
},
|
|
||||||
//...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The `include_timeframes` in the config above are the timeframes (`tf`) of each call to `feature_engineering_expand_*()` in the strategy. In the presented case, the user is asking for the `5m`, `15m`, and `4h` timeframes of the `rsi`, `mfi`, `roc`, and `bb_width` to be included in the feature set.
|
|
||||||
|
|
||||||
You can ask for each of the defined features to be included also for informative pairs using the `include_corr_pairlist`. This means that the feature set will include all the features from `feature_engineering_expand_*()` on all the `include_timeframes` for each of the correlated pairs defined in the config (`ETH/USD`, `LINK/USD`, and `BNB/USD` in the presented example).
|
|
||||||
|
|
||||||
`include_shifted_candles` indicates the number of previous candles to include in the feature set. For example, `include_shifted_candles: 2` tells FreqAI to include the past 2 candles for each of the features in the feature set.
|
|
||||||
|
|
||||||
In total, the number of features the user of the presented example strategy has created is: length of `include_timeframes` * no. features in `feature_engineering_expand_*()` * length of `include_corr_pairlist` * no. `include_shifted_candles` * length of `indicator_periods_candles`
|
|
||||||
$= 3 * 3 * 3 * 2 * 2 = 108$.
|
|
||||||
|
|
||||||
!!! note "Learn more about creative feature engineering"
|
|
||||||
Check out our [medium article](https://emergentmethods.medium.com/freqai-from-price-to-prediction-6fadac18b665) geared toward helping users learn how to creatively engineer features.
|
|
||||||
|
|
||||||
### Gain finer control over `feature_engineering_*` functions with `metadata`
|
|
||||||
|
|
||||||
All `feature_engineering_*` and `set_freqai_targets()` functions are passed a `metadata` dictionary which contains information about the `pair`, `tf` (timeframe), and `period` that FreqAI is automating for feature building. As such, a user can use `metadata` inside `feature_engineering_*` functions as criteria for blocking/reserving features for certain timeframes, periods, pairs etc.
|
|
||||||
|
|
||||||
```python
|
|
||||||
def feature_engineering_expand_all(self, dataframe: DataFrame, period, metadata, **kwargs) -> DataFrame:
|
|
||||||
if metadata["tf"] == "1h":
|
|
||||||
dataframe["%-roc-period"] = ta.ROC(dataframe, timeperiod=period)
|
|
||||||
```
|
|
||||||
|
|
||||||
This will block `ta.ROC()` from being added to any timeframes other than `"1h"`.
|
|
||||||
|
|
||||||
### Returning additional info from training
|
|
||||||
|
|
||||||
Important metrics can be returned to the strategy at the end of each model training by assigning them to `dk.data['extra_returns_per_train']['my_new_value'] = XYZ` inside the custom prediction model class.
|
|
||||||
|
|
||||||
FreqAI takes the `my_new_value` assigned in this dictionary and expands it to fit the dataframe that is returned to the strategy. You can then use the returned metrics in your strategy through `dataframe['my_new_value']`. An example of how return values can be used in FreqAI are the `&*_mean` and `&*_std` values that are used to [created a dynamic target threshold](freqai-configuration.md#creating-a-dynamic-target-threshold).
|
|
||||||
|
|
||||||
Another example, where the user wants to use live metrics from the trade database, is shown below:
|
|
||||||
|
|
||||||
```json
|
|
||||||
"freqai": {
|
|
||||||
"extra_returns_per_train": {"total_profit": 4}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
You need to set the standard dictionary in the config so that FreqAI can return proper dataframe shapes. These values will likely be overridden by the prediction model, but in the case where the model has yet to set them, or needs a default initial value, the pre-set values are what will be returned.
|
|
||||||
|
|
||||||
### Weighting features for temporal importance
|
|
||||||
|
|
||||||
FreqAI allows you to set a `weight_factor` to weight recent data more strongly than past data via an exponential function:
|
|
||||||
|
|
||||||
$$ 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. Below is a figure showing the effect of different weight factors on the data points in a feature set.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Building the data pipeline
|
|
||||||
|
|
||||||
By default, FreqAI builds a dynamic pipeline based on user configuration settings. The default settings are robust and designed to work with a variety of methods. These two steps are a `MinMaxScaler(-1,1)` and a `VarianceThreshold` which removes any column that has 0 variance. Users can activate other steps with more configuration parameters. For example if users add `use_SVM_to_remove_outliers: true` to the `freqai` config, then FreqAI will automatically add the [`SVMOutlierExtractor`](#identifying-outliers-using-a-support-vector-machine-svm) to the pipeline. Likewise, users can add `principal_component_analysis: true` to the `freqai` config to activate PCA. The [DissimilarityIndex](#identifying-outliers-with-the-dissimilarity-index-di) is activated with `DI_threshold: 1`. Finally, noise can also be added to the data with `noise_standard_deviation: 0.1`. Finally, users can add [DBSCAN](#identifying-outliers-with-dbscan) outlier removal with `use_DBSCAN_to_remove_outliers: true`.
|
|
||||||
|
|
||||||
!!! note "More information available"
|
|
||||||
Please review the [parameter table](freqai-parameter-table.md) for more information on these parameters.
|
|
||||||
|
|
||||||
|
|
||||||
### Customizing the pipeline
|
|
||||||
|
|
||||||
Users are encouraged to customize the data pipeline to their needs by building their own data pipeline. This can be done by simply setting `dk.feature_pipeline` to their desired `Pipeline` object inside their `IFreqaiModel` `train()` function, or if they prefer not to touch the `train()` function, they can override `define_data_pipeline`/`define_label_pipeline` functions in their `IFreqaiModel`:
|
|
||||||
|
|
||||||
!!! note "More information available"
|
|
||||||
FreqAI uses the [`DataSieve`](https://github.com/emergentmethods/datasieve) pipeline, which follows the SKlearn pipeline API, but adds, among other features, coherence between the X, y, and sample_weight vector point removals, feature removal, feature name following.
|
|
||||||
|
|
||||||
```python
|
|
||||||
from datasieve.transforms import SKLearnWrapper, DissimilarityIndex
|
|
||||||
from datasieve.pipeline import Pipeline
|
|
||||||
from sklearn.preprocessing import QuantileTransformer, StandardScaler
|
|
||||||
from freqai.base_models import BaseRegressionModel
|
|
||||||
|
|
||||||
|
|
||||||
class MyFreqaiModel(BaseRegressionModel):
|
|
||||||
"""
|
|
||||||
Some cool custom model
|
|
||||||
"""
|
|
||||||
def fit(self, data_dictionary: Dict, dk: FreqaiDataKitchen, **kwargs) -> Any:
|
|
||||||
"""
|
|
||||||
My custom fit function
|
|
||||||
"""
|
|
||||||
model = cool_model.fit()
|
|
||||||
return model
|
|
||||||
|
|
||||||
def define_data_pipeline(self) -> Pipeline:
|
|
||||||
"""
|
|
||||||
User defines their custom feature pipeline here (if they wish)
|
|
||||||
"""
|
|
||||||
feature_pipeline = Pipeline([
|
|
||||||
('qt', SKLearnWrapper(QuantileTransformer(output_distribution='normal'))),
|
|
||||||
('di', ds.DissimilarityIndex(di_threshold=1))
|
|
||||||
])
|
|
||||||
|
|
||||||
return feature_pipeline
|
|
||||||
|
|
||||||
def define_label_pipeline(self) -> Pipeline:
|
|
||||||
"""
|
|
||||||
User defines their custom label pipeline here (if they wish)
|
|
||||||
"""
|
|
||||||
label_pipeline = Pipeline([
|
|
||||||
('qt', SKLearnWrapper(StandardScaler())),
|
|
||||||
])
|
|
||||||
|
|
||||||
return label_pipeline
|
|
||||||
```
|
|
||||||
|
|
||||||
Here, you are defining the exact pipeline that will be used for your feature set during training and prediction. You can use *most* SKLearn transformation steps by wrapping them in the `SKLearnWrapper` class as shown above. In addition, you can use any of the transformations available in the [`DataSieve` library](https://github.com/emergentmethods/datasieve).
|
|
||||||
|
|
||||||
You can easily add your own transformation by creating a class that inherits from the datasieve `BaseTransform` and implementing your `fit()`, `transform()` and `inverse_transform()` methods:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from datasieve.transforms.base_transform import BaseTransform
|
|
||||||
# import whatever else you need
|
|
||||||
|
|
||||||
class MyCoolTransform(BaseTransform):
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
self.param1 = kwargs.get('param1', 1)
|
|
||||||
|
|
||||||
def fit(self, X, y=None, sample_weight=None, feature_list=None, **kwargs):
|
|
||||||
# do something with X, y, sample_weight, or/and feature_list
|
|
||||||
return X, y, sample_weight, feature_list
|
|
||||||
|
|
||||||
def transform(self, X, y=None, sample_weight=None,
|
|
||||||
feature_list=None, outlier_check=False, **kwargs):
|
|
||||||
# do something with X, y, sample_weight, or/and feature_list
|
|
||||||
return X, y, sample_weight, feature_list
|
|
||||||
|
|
||||||
def inverse_transform(self, X, y=None, sample_weight=None, feature_list=None, **kwargs):
|
|
||||||
# do/dont do something with X, y, sample_weight, or/and feature_list
|
|
||||||
return X, y, sample_weight, feature_list
|
|
||||||
```
|
|
||||||
|
|
||||||
!!! note "Hint"
|
|
||||||
You can define this custom class in the same file as your `IFreqaiModel`.
|
|
||||||
|
|
||||||
### Migrating a custom `IFreqaiModel` to the new Pipeline
|
|
||||||
|
|
||||||
If you have created your own custom `IFreqaiModel` with a custom `train()`/`predict()` function, *and* you still rely on `data_cleaning_train/predict()`, then you will need to migrate to the new pipeline. If your model does *not* rely on `data_cleaning_train/predict()`, then you do not need to worry about this migration.
|
|
||||||
|
|
||||||
More details about the migration can be found [here](strategy_migration.md#freqai---new-data-pipeline).
|
|
||||||
|
|
||||||
## Outlier detection
|
|
||||||
|
|
||||||
Equity and crypto markets suffer from a high level of non-patterned noise in the form of outlier data points. FreqAI implements a variety of methods to identify such outliers and hence mitigate risk.
|
|
||||||
|
|
||||||
### Identifying outliers with the Dissimilarity Index (DI)
|
|
||||||
|
|
||||||
The Dissimilarity Index (DI) aims to quantify the uncertainty associated with each prediction made by the model.
|
|
||||||
|
|
||||||
You can tell FreqAI to remove outlier data points from the training/test data sets using the DI by including the following statement in the config:
|
|
||||||
|
|
||||||
```json
|
|
||||||
"freqai": {
|
|
||||||
"feature_parameters" : {
|
|
||||||
"DI_threshold": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Which will add `DissimilarityIndex` step to your `feature_pipeline` and set the threshold to 1. The DI allows predictions which are outliers (not existent in the model feature space) to be thrown out due to low levels of certainty. To do so, FreqAI measures the distance between each training data point (feature vector), $X_{a}$, and all other training data points:
|
|
||||||
|
|
||||||
$$ d_{ab} = \sqrt{\sum_{j=1}^p(X_{a,j}-X_{b,j})^2} $$
|
|
||||||
|
|
||||||
where $d_{ab}$ is the distance between the normalized points $a$ and $b$, and $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 a new prediction feature vectors, $X_k$ and all the training data:
|
|
||||||
|
|
||||||
$$ d_k = \arg \min d_{k,i} $$
|
|
||||||
|
|
||||||
This enables the estimation of the Dissimilarity Index as:
|
|
||||||
|
|
||||||
$$ DI_k = d_k/\overline{d} $$
|
|
||||||
|
|
||||||
You can tweak the DI through the `DI_threshold` to increase or decrease the extrapolation of the trained model. A higher `DI_threshold` means that the DI is more lenient and allows predictions further away from the training data to be used whilst a lower `DI_threshold` has the opposite effect and hence discards more predictions.
|
|
||||||
|
|
||||||
Below is a figure that describes the DI for a 3D data set.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### Identifying outliers using a Support Vector Machine (SVM)
|
|
||||||
|
|
||||||
You can tell FreqAI to remove outlier data points from the training/test data sets using a Support Vector Machine (SVM) by including the following statement in the config:
|
|
||||||
|
|
||||||
```json
|
|
||||||
"freqai": {
|
|
||||||
"feature_parameters" : {
|
|
||||||
"use_SVM_to_remove_outliers": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Which will add `SVMOutlierExtractor` step to your `feature_pipeline`. The SVM will be trained on the training data and any data point that the SVM deems to be beyond the feature space will be removed.
|
|
||||||
|
|
||||||
You can elect to provide additional parameters for the SVM, such as `shuffle`, and `nu` via the `feature_parameters.svm_params` dictionary in the config.
|
|
||||||
|
|
||||||
The parameter `shuffle` is by default set to `False` to ensure consistent results. If it is set to `True`, running the SVM multiple times on the same data set might result in different outcomes due to `max_iter` being to low for the algorithm to reach the demanded `tol`. Increasing `max_iter` solves this issue but causes the procedure to take longer time.
|
|
||||||
|
|
||||||
The parameter `nu`, *very* broadly, is the amount of data points that should be considered outliers and should be between 0 and 1.
|
|
||||||
|
|
||||||
### Identifying outliers with DBSCAN
|
|
||||||
|
|
||||||
You can configure FreqAI to use DBSCAN to cluster and remove outliers from the training/test data set or incoming outliers from predictions, by activating `use_DBSCAN_to_remove_outliers` in the config:
|
|
||||||
|
|
||||||
```json
|
|
||||||
"freqai": {
|
|
||||||
"feature_parameters" : {
|
|
||||||
"use_DBSCAN_to_remove_outliers": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Which will add the `DataSieveDBSCAN` step to your `feature_pipeline`. This is an unsupervised machine learning algorithm that clusters data without needing to know how many clusters there should be.
|
|
||||||
|
|
||||||
Given a number of data points $N$, and a distance $\varepsilon$, DBSCAN clusters the data set by setting all data points that have $N-1$ other data points within a distance of $\varepsilon$ as *core points*. A data point that is within a distance of $\varepsilon$ from a *core point* but that does not have $N-1$ other data points within a distance of $\varepsilon$ from itself is considered an *edge point*. A cluster is then the collection of *core points* and *edge points*. Data points that have no other data points at a distance $<\varepsilon$ are considered outliers. The figure below shows a cluster with $N = 3$.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
FreqAI uses `sklearn.cluster.DBSCAN` (details are available on scikit-learn's webpage [here](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html) (external website)) with `min_samples` ($N$) taken as 1/4 of the no. of time points (candles) in the feature set. `eps` ($\varepsilon$) is computed automatically as the elbow point in the *k-distance graph* computed from the nearest neighbors in the pairwise distances of all data points in the feature set.
|
|
||||||
|
|
||||||
|
|
||||||
### Data dimensionality reduction with Principal Component Analysis
|
|
||||||
|
|
||||||
You can reduce the dimensionality of your features by activating the principal_component_analysis in the config:
|
|
||||||
|
|
||||||
```json
|
|
||||||
"freqai": {
|
|
||||||
"feature_parameters" : {
|
|
||||||
"principal_component_analysis": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This will perform PCA on the features and reduce their dimensionality so that the explained variance of the data set is >= 0.999. Reducing data dimensionality makes training the model faster and hence allows for more up-to-date models.
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
# Parameter table
|
|
||||||
|
|
||||||
The table below will list all configuration parameters available for FreqAI. Some of the parameters are exemplified in `config_examples/config_freqai.example.json`.
|
|
||||||
|
|
||||||
Mandatory parameters are marked as **Required** and have to be set in one of the suggested ways.
|
|
||||||
|
|
||||||
### General configuration parameters
|
|
||||||
|
|
||||||
| Parameter | Description |
|
|
||||||
|------------|-------------|
|
|
||||||
| | **General configuration parameters within the `config.freqai` tree**
|
|
||||||
| `freqai` | **Required.** <br> The parent dictionary containing all the parameters for controlling FreqAI. <br> **Datatype:** Dictionary.
|
|
||||||
| `train_period_days` | **Required.** <br> Number of days to use for the training data (width of the sliding window). <br> **Datatype:** Positive integer.
|
|
||||||
| `backtest_period_days` | **Required.** <br> Number of days to inference from the trained model before sliding the `train_period_days` window defined above, and retraining the model during backtesting (more info [here](freqai-running.md#backtesting)). This can be fractional days, but beware that the provided `timerange` will be divided by this number to yield the number of trainings necessary to complete the backtest. <br> **Datatype:** Float.
|
|
||||||
| `identifier` | **Required.** <br> A unique ID for the current model. If models are saved to disk, the `identifier` allows for reloading specific pre-trained models/data. <br> **Datatype:** String.
|
|
||||||
| `live_retrain_hours` | Frequency of retraining during dry/live runs. <br> **Datatype:** Float > 0. <br> Default: `0` (models retrain as often as possible).
|
|
||||||
| `expiration_hours` | Avoid making predictions if a model is more than `expiration_hours` old. <br> **Datatype:** Positive integer. <br> Default: `0` (models never expire).
|
|
||||||
| `purge_old_models` | Number of models to keep on disk (not relevant to backtesting). Default is 2, which means that dry/live runs will keep the latest 2 models on disk. Setting to 0 keeps all models. This parameter also accepts a boolean to maintain backwards compatibility. <br> **Datatype:** Integer. <br> Default: `2`.
|
|
||||||
| `save_backtest_models` | Save models to disk when running backtesting. Backtesting operates most efficiently by saving the prediction data and reusing them directly for subsequent runs (when you wish to tune entry/exit parameters). Saving backtesting models to disk also allows to use the same model files for starting a dry/live instance with the same model `identifier`. <br> **Datatype:** Boolean. <br> Default: `False` (no models are saved).
|
|
||||||
| `fit_live_predictions_candles` | Number of historical candles to use for computing target (label) statistics from prediction data, instead of from the training dataset (more information can be found [here](freqai-configuration.md#creating-a-dynamic-target-threshold)). <br> **Datatype:** Positive integer.
|
|
||||||
| `continual_learning` | Use the final state of the most recently trained model as starting point for the new model, allowing for incremental learning (more information can be found [here](freqai-running.md#continual-learning)). Beware that this is currently a naive approach to incremental learning, and it has a high probability of overfitting/getting stuck in local minima while the market moves away from your model. We have the connections here primarily for experimental purposes and so that it is ready for more mature approaches to continual learning in chaotic systems like the crypto market. <br> **Datatype:** Boolean. <br> Default: `False`.
|
|
||||||
| `write_metrics_to_disk` | Collect train timings, inference timings and cpu usage in json file. <br> **Datatype:** Boolean. <br> Default: `False`
|
|
||||||
| `data_kitchen_thread_count` | <br> Designate the number of threads you want to use for data processing (outlier methods, normalization, etc.). This has no impact on the number of threads used for training. If user does not set it (default), FreqAI will use max number of threads - 2 (leaving 1 physical core available for Freqtrade bot and FreqUI) <br> **Datatype:** Positive integer.
|
|
||||||
| `activate_tensorboard` | <br> Indicate whether or not to activate tensorboard for the tensorboard enabled modules (currently Reinforcment Learning, XGBoost, Catboost, and PyTorch). Tensorboard needs Torch installed, which means you will need the torch/RL docker image or you need to answer "yes" to the install question about whether or not you wish to install Torch. <br> **Datatype:** Boolean. <br> Default: `True`.
|
|
||||||
|
|
||||||
### Feature parameters
|
|
||||||
|
|
||||||
| Parameter | Description |
|
|
||||||
|------------|-------------|
|
|
||||||
| | **Feature parameters within the `freqai.feature_parameters` sub dictionary**
|
|
||||||
| `feature_parameters` | A dictionary containing the parameters used to engineer the feature set. Details and examples are shown [here](freqai-feature-engineering.md). <br> **Datatype:** Dictionary.
|
|
||||||
| `include_timeframes` | A list of timeframes that all indicators in `feature_engineering_expand_*()` will be created for. The list is added as features to the base indicators dataset. <br> **Datatype:** List of timeframes (strings).
|
|
||||||
| `include_corr_pairlist` | A list of correlated coins that FreqAI will add as additional features to all `pair_whitelist` coins. All indicators set in `feature_engineering_expand_*()` during feature engineering (see details [here](freqai-feature-engineering.md)) will be created for each correlated coin. The correlated coins features are added to the base indicators dataset. <br> **Datatype:** List of assets (strings).
|
|
||||||
| `label_period_candles` | Number of candles into the future that the labels are created for. This can be used in `set_freqai_targets()` (see `templates/FreqaiExampleStrategy.py` for detailed usage). This parameter is not necessarily required, you can create custom labels and choose whether to make use of this parameter or not. Please see `templates/FreqaiExampleStrategy.py` to see the example usage. <br> **Datatype:** Positive integer.
|
|
||||||
| `include_shifted_candles` | Add features from previous candles to subsequent candles with the intent of adding historical information. If used, FreqAI will duplicate and shift all features from the `include_shifted_candles` previous candles so that the information is available for the subsequent candle. <br> **Datatype:** Positive integer.
|
|
||||||
| `weight_factor` | Weight training data points according to their recency (see details [here](freqai-feature-engineering.md#weighting-features-for-temporal-importance)). <br> **Datatype:** Positive float (typically < 1).
|
|
||||||
| `indicator_max_period_candles` | **No longer used (#7325)**. Replaced by `startup_candle_count` which is set in the [strategy](freqai-configuration.md#building-a-freqai-strategy). `startup_candle_count` is timeframe independent and defines the maximum *period* used in `feature_engineering_*()` for indicator creation. FreqAI uses this parameter together with the maximum timeframe in `include_time_frames` to calculate how many data points to download such that the first data point does not include a NaN. <br> **Datatype:** Positive integer.
|
|
||||||
| `indicator_periods_candles` | Time periods to calculate indicators for. The indicators are added to the base indicator dataset. <br> **Datatype:** List of positive integers.
|
|
||||||
| `principal_component_analysis` | Automatically reduce the dimensionality of the data set using Principal Component Analysis. See details about how it works [here](freqai-feature-engineering.md#data-dimensionality-reduction-with-principal-component-analysis) <br> **Datatype:** Boolean. <br> Default: `False`.
|
|
||||||
| `plot_feature_importances` | Create a feature importance plot for each model for the top/bottom `plot_feature_importances` number of features. Plot is stored in `user_data/models/<identifier>/sub-train-<COIN>_<timestamp>.html`. <br> **Datatype:** Integer. <br> Default: `0`.
|
|
||||||
| `DI_threshold` | Activates the use of the Dissimilarity Index for outlier detection when set to > 0. See details about how it works [here](freqai-feature-engineering.md#identifying-outliers-with-the-dissimilarity-index-di). <br> **Datatype:** Positive float (typically < 1).
|
|
||||||
| `use_SVM_to_remove_outliers` | Train a support vector machine to detect and remove outliers from the training dataset, as well as from incoming data points. See details about how it works [here](freqai-feature-engineering.md#identifying-outliers-using-a-support-vector-machine-svm). <br> **Datatype:** Boolean.
|
|
||||||
| `svm_params` | All parameters available in Sklearn's `SGDOneClassSVM()`. See details about some select parameters [here](freqai-feature-engineering.md#identifying-outliers-using-a-support-vector-machine-svm). <br> **Datatype:** Dictionary.
|
|
||||||
| `use_DBSCAN_to_remove_outliers` | Cluster data using the DBSCAN algorithm to identify and remove outliers from training and prediction data. See details about how it works [here](freqai-feature-engineering.md#identifying-outliers-with-dbscan). <br> **Datatype:** Boolean.
|
|
||||||
| `noise_standard_deviation` | If set, FreqAI adds noise to the training features with the aim of preventing overfitting. FreqAI generates random deviates from a gaussian distribution with a standard deviation of `noise_standard_deviation` and adds them to all data points. `noise_standard_deviation` should be kept relative to the normalized space, i.e., between -1 and 1. In other words, since data in FreqAI is always normalized to be between -1 and 1, `noise_standard_deviation: 0.05` would result in 32% of the data being randomly increased/decreased by more than 2.5% (i.e., the percent of data falling within the first standard deviation). <br> **Datatype:** Integer. <br> Default: `0`.
|
|
||||||
| `outlier_protection_percentage` | Enable to prevent outlier detection methods from discarding too much data. If more than `outlier_protection_percentage` % of points are detected as outliers by the SVM or DBSCAN, FreqAI will log a warning message and ignore outlier detection, i.e., the original dataset will be kept intact. If the outlier protection is triggered, no predictions will be made based on the training dataset. <br> **Datatype:** Float. <br> Default: `30`.
|
|
||||||
| `reverse_train_test_order` | Split the feature dataset (see below) and use the latest data split for training and test on historical split of the data. This allows the model to be trained up to the most recent data point, while avoiding overfitting. However, you should be careful to understand the unorthodox nature of this parameter before employing it. <br> **Datatype:** Boolean. <br> Default: `False` (no reversal).
|
|
||||||
| `shuffle_after_split` | Split the data into train and test sets, and then shuffle both sets individually. <br> **Datatype:** Boolean. <br> Default: `False`.
|
|
||||||
| `buffer_train_data_candles` | Cut `buffer_train_data_candles` off the beginning and end of the training data *after* the indicators were populated. The main example use is when predicting maxima and minima, the argrelextrema function cannot know the maxima/minima at the edges of the timerange. To improve model accuracy, it is best to compute argrelextrema on the full timerange and then use this function to cut off the edges (buffer) by the kernel. In another case, if the targets are set to a shifted price movement, this buffer is unnecessary because the shifted candles at the end of the timerange will be NaN and FreqAI will automatically cut those off of the training dataset.<br> **Datatype:** Integer. <br> Default: `0`.
|
|
||||||
|
|
||||||
### Data split parameters
|
|
||||||
|
|
||||||
| Parameter | Description |
|
|
||||||
|------------|-------------|
|
|
||||||
| | **Data split parameters within the `freqai.data_split_parameters` sub dictionary**
|
|
||||||
| `data_split_parameters` | Include any additional parameters available from scikit-learn `test_train_split()`, which are shown [here](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html) (external website). <br> **Datatype:** Dictionary.
|
|
||||||
| `test_size` | The fraction of data that should be used for testing instead of training. <br> **Datatype:** Positive float < 1.
|
|
||||||
| `shuffle` | Shuffle the training data points during training. Typically, to not remove the chronological order of data in time-series forecasting, this is set to `False`. <br> **Datatype:** Boolean. <br> Default: `False`.
|
|
||||||
|
|
||||||
### Model training parameters
|
|
||||||
|
|
||||||
| Parameter | Description |
|
|
||||||
|------------|-------------|
|
|
||||||
| | **Model training parameters within the `freqai.model_training_parameters` sub dictionary**
|
|
||||||
| `model_training_parameters` | A flexible dictionary that includes all parameters available by the selected model library. For example, if you use `LightGBMRegressor`, this dictionary can contain any parameter available by the `LightGBMRegressor` [here](https://lightgbm.readthedocs.io/en/latest/pythonapi/lightgbm.LGBMRegressor.html) (external website). If you select a different model, this dictionary can contain any parameter from that model. A list of the currently available models can be found [here](freqai-configuration.md#using-different-prediction-models). <br> **Datatype:** Dictionary.
|
|
||||||
| `n_estimators` | The number of boosted trees to fit in the training of the model. <br> **Datatype:** Integer.
|
|
||||||
| `learning_rate` | Boosting learning rate during training of the model. <br> **Datatype:** Float.
|
|
||||||
| `n_jobs`, `thread_count`, `task_type` | Set the number of threads for parallel processing and the `task_type` (`gpu` or `cpu`). Different model libraries use different parameter names. <br> **Datatype:** Float.
|
|
||||||
|
|
||||||
### Reinforcement Learning parameters
|
|
||||||
|
|
||||||
| Parameter | Description |
|
|
||||||
|------------|-------------|
|
|
||||||
| | **Reinforcement Learning Parameters within the `freqai.rl_config` sub dictionary**
|
|
||||||
| `rl_config` | A dictionary containing the control parameters for a Reinforcement Learning model. <br> **Datatype:** Dictionary.
|
|
||||||
| `train_cycles` | Training time steps will be set based on the `train_cycles * number of training data points. <br> **Datatype:** Integer.
|
|
||||||
| `max_trade_duration_candles`| Guides the agent training to keep trades below desired length. Example usage shown in `prediction_models/ReinforcementLearner.py` within the customizable `calculate_reward()` function. <br> **Datatype:** int.
|
|
||||||
| `model_type` | Model string from stable_baselines3 or SBcontrib. Available strings include: `'TRPO', 'ARS', 'RecurrentPPO', 'MaskablePPO', 'PPO', 'A2C', 'DQN'`. User should ensure that `model_training_parameters` match those available to the corresponding stable_baselines3 model by visiting their documentation. [PPO doc](https://stable-baselines3.readthedocs.io/en/master/modules/ppo.html) (external website) <br> **Datatype:** string.
|
|
||||||
| `policy_type` | One of the available policy types from stable_baselines3 <br> **Datatype:** string.
|
|
||||||
| `max_training_drawdown_pct` | The maximum drawdown that the agent is allowed to experience during training. <br> **Datatype:** float. <br> Default: 0.8
|
|
||||||
| `cpu_count` | Number of threads/cpus to dedicate to the Reinforcement Learning training process (depending on if `ReinforcementLearning_multiproc` is selected or not). Recommended to leave this untouched, by default, this value is set to the total number of physical cores minus 1. <br> **Datatype:** int.
|
|
||||||
| `model_reward_parameters` | Parameters used inside the customizable `calculate_reward()` function in `ReinforcementLearner.py` <br> **Datatype:** int.
|
|
||||||
| `add_state_info` | Tell FreqAI to include state information in the feature set for training and inferencing. The current state variables include trade duration, current profit, trade position. This is only available in dry/live runs, and is automatically switched to false for backtesting. <br> **Datatype:** bool. <br> Default: `False`.
|
|
||||||
| `net_arch` | Network architecture which is well described in [`stable_baselines3` doc](https://stable-baselines3.readthedocs.io/en/master/guide/custom_policy.html#examples). In summary: `[<shared layers>, dict(vf=[<non-shared value network layers>], pi=[<non-shared policy network layers>])]`. By default this is set to `[128, 128]`, which defines 2 shared hidden layers with 128 units each.
|
|
||||||
| `randomize_starting_position` | Randomize the starting point of each episode to avoid overfitting. <br> **Datatype:** bool. <br> Default: `False`.
|
|
||||||
| `drop_ohlc_from_features` | Do not include the normalized ohlc data in the feature set passed to the agent during training (ohlc will still be used for driving the environment in all cases) <br> **Datatype:** Boolean. <br> **Default:** `False`
|
|
||||||
| `progress_bar` | Display a progress bar with the current progress, elapsed time and estimated remaining time. <br> **Datatype:** Boolean. <br> Default: `False`.
|
|
||||||
|
|
||||||
### PyTorch parameters
|
|
||||||
|
|
||||||
#### general
|
|
||||||
|
|
||||||
| Parameter | Description |
|
|
||||||
|------------|-------------|
|
|
||||||
| | **Model training parameters within the `freqai.model_training_parameters` sub dictionary**
|
|
||||||
| `learning_rate` | Learning rate to be passed to the optimizer. <br> **Datatype:** float. <br> Default: `3e-4`.
|
|
||||||
| `model_kwargs` | Parameters to be passed to the model class. <br> **Datatype:** dict. <br> Default: `{}`.
|
|
||||||
| `trainer_kwargs` | Parameters to be passed to the trainer class. <br> **Datatype:** dict. <br> Default: `{}`.
|
|
||||||
|
|
||||||
#### trainer_kwargs
|
|
||||||
|
|
||||||
| Parameter | Description |
|
|
||||||
|--------------|-------------|
|
|
||||||
| | **Model training parameters within the `freqai.model_training_parameters.model_kwargs` sub dictionary**
|
|
||||||
| `n_epochs` | The `n_epochs` parameter is a crucial setting in the PyTorch training loop that determines the number of times the entire training dataset will be used to update the model's parameters. An epoch represents one full pass through the entire training dataset. Overrides `n_steps`. Either `n_epochs` or `n_steps` must be set. <br><br> **Datatype:** int. optional. <br> Default: `10`.
|
|
||||||
| `n_steps` | An alternative way of setting `n_epochs` - the number of training iterations to run. Iteration here refer to the number of times we call `optimizer.step()`. Ignored if `n_epochs` is set. A simplified version of the function: <br><br> n_epochs = n_steps / (n_obs / batch_size) <br><br> The motivation here is that `n_steps` is easier to optimize and keep stable across different n_obs - the number of data points. <br> <br> **Datatype:** int. optional. <br> Default: `None`.
|
|
||||||
| `batch_size` | The size of the batches to use during training. <br><br> **Datatype:** int. <br> Default: `64`.
|
|
||||||
|
|
||||||
|
|
||||||
### Additional parameters
|
|
||||||
|
|
||||||
| Parameter | Description |
|
|
||||||
|------------|-------------|
|
|
||||||
| | **Extraneous parameters**
|
|
||||||
| `freqai.keras` | If the selected model makes use of Keras (typical for TensorFlow-based prediction models), this flag needs to be activated so that the model save/loading follows Keras standards. <br> **Datatype:** Boolean. <br> Default: `False`.
|
|
||||||
| `freqai.conv_width` | The width of a neural network input tensor. This replaces the need for shifting candles (`include_shifted_candles`) by feeding in historical data points as the second dimension of the tensor. Technically, this parameter can also be used for regressors, but it only adds computational overhead and does not change the model training/prediction. <br> **Datatype:** Integer. <br> Default: `2`.
|
|
||||||
| `freqai.reduce_df_footprint` | Recast all numeric columns to float32/int32, with the objective of reducing ram/disk usage and decreasing train/inference timing. This parameter is set in the main level of the Freqtrade configuration file (not inside FreqAI). <br> **Datatype:** Boolean. <br> Default: `False`.
|
|
||||||