Setup
Docker
I’m using this docker-compose file
Go to the home directory of your freqtrade bot and create a file docker-compose.yml
services:
freqtradeBot1:
image: freqtradeorg/freqtrade:stable
restart: unless-stopped
container_name: freqtradeBot1
network_mode: bridge
ports:
- "127.0.0.1:8081:8081"
volumes:
- ./user_data:/freqtrade/user_data
environment:
- UVICORN_WORKERS=4
- UVICORN_RELOAD=false
command: >
trade --config /freqtrade/user_data/config.json
and a file dockerfile
with the following content
FROM freqtradeorg/freqtrade:stable
# Most NFI-Versions need these packages
RUN pip install --no-cache-dir technical qtpylib pandas_ta
Create the ‘user_data’ and required directories
# docker compose run --rm freqtradeX7 create-userdir --userdir user_data
# mkdir -p ./user_data/{strategies,backtest_results}
Get your strategies you want to use.
My current favorit is one of the “NostalgiaForInfinity” collection
It is best practice to run a separate docker container for each strategy you want to test/run.
The GUI looks like as you can have multiple bots within one instance, but these are artefacts only. Multibot has been deprecated and removed some time ago!
# cd ./user_data/strategies
# git clone https://github.com/iterativv/NostalgiaForInfinity.git
# cp NostalgiaForInfinity/NostalgiaForInfinityX7.py ./
Create your freqtrade bot config ./user_data/config.json
Example for Bitvavo API in dry-run mode:
{
"strategy": "NostalgiaForInfinityX7",
"dry_run": true,
"dry_run_wallet": 5000,
"timeframe": "5m",
"stake_currency": "EUR",
"stake_amount": 500,
"max_open_trades": 10,
"trading_mode": "spot",
"exchange": {
"name": "bitvavo",
"key": "API-Key",
"secret": "API-SECRET",
"ccxt_config": {},
"ccxt_async_config": {},
"pair_whitelist": [],
"pair_blacklist": []
},
"pairlists": [
{
"method": "VolumePairList",
"number_assets": 100,
"sort_key": "quoteVolume",
"min_value": 200000,
"mandatory_pairs": [
"BTC/EUR",
"ETH/EUR",
"SOL/EUR",
"XRP/EUR",
"LINK/EUR"
],
"refresh_period": 1800
},
{
"method": "AgeFilter",
"min_days_listed": 60
},
{
"method": "SpreadFilter",
"max_spread_ratio": 0.005
},
{
"method": "VolatilityFilter",
"min_volatility": 0.02,
"max_volatility": 0.16,
"lookback_period": 1440
},
],
"entry_pricing": {},
"exit_pricing": {},
"edge": {},
"api_server": {
"enabled": true,
"listen_ip_address": "0.0.0.0",
"listen_port": 8081,
"verbosity": "error",
"jwt_secret_key": "SecretRandomString",
"CORS_origins": [
"https://bot1.trader.domain.de"
],
"username": "admin",
"password": "SuperSecurePassword"
},
"telegram": {
"enabled": true,
"token": "TOKEN",
"chat_id": "CHAT-ID",
"notification_settings": {
"status": "on",
"warning": "on",
"buy": "on",
"buy_cancel": "on",
"buy_fill": "on",
"sell": "on",
"sell_cancel": "on",
"sell_fill": "on",
"protection_trigger": "on",
"strategy_msg": "on"
}
},
"mail": {
"enabled": true,
"smtp_server": "localhost",
"smtp_port": 25,
"from": "Trader <trader@domain.de>",
"to": "recipient@domain.de, recipient2@domain.de"
},
"notification_settings": {
"status": ["telegram", "mail"],
"warning": ["telegram", "mail"],
"buy": ["telegram"],
"buy_cancel": ["telegram"],
"sell": ["telegram", "mail"],
"sell_cancel": ["telegram"],
"protection_trigger": ["telegram", "mail"],
"strategy_msg": ["telegram"]
},
"bot_name": "Bitvavo-Bot1",
"loglevel": "info"
}
Load config into bot
# docker compose run --rm freqtradeBot1 new-config --config user_data/config.json
Startup
Start docker container
# docker compose pull
# docker compose up -d --build
# docker compose down
systemd
Create a systemd service file
(Do not add the ‘-d’ at the end of ‘ExecStart’ command !!)
# /etc/systemd/system/freqtradeBot1.service
[Unit]
Description=Freqtrade Bot1 X7 (NostalgiaForInfinityX7)
After=docker.service
Requires=docker.service
[Service]
Type=simple
WorkingDirectory=/opt/freqTrade/freqtradeBot1
ExecStart=/usr/bin/docker compose up
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=300
TimeoutStopSec=120
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
Start daemon
# systemctl daemon-reload
# systemctl enable --now freqtradeBot1
# systemctl status freqtradeBot1
...
At this point you are generally finished.
You should be able to access the FreqTrade UI through http://127.0.0.1:8081
Anyway, you should enable TLS encryption! And you may wand to access the UI not just through localhost address. So I’m following up here with an NGINX setup secured by LetsEncrypt certificates.
Nginx
- Create a DNS record for *.trade.domain.de
- Create a wildcard certificate with LetsEncrypt for *.trade.domain.de
- Create a virtual host in nginx for your wildcard domain.
- Create a domain to bot-backend map in nginx if running more that one bot instance
See comment above during docker setup of the strategy
map $host $trader_backend {
default 127.0.0.1:9; # discard / Bad gateway
bot1.trade.domain.de 127.0.0.1:8081;
bot2.trade.domain.de 127.0.0.1:8082;
bot-backtrade.trade.domain.de 127.0.0.1:8089;
# add more bots/domains here
}
server {
listen 80;
listen [::]:80;
listen 443 ssl http2; # http2;
listen [::]:443 ssl http2; # http2;
keepalive_timeout 70;
server_name trade.domain.de
*.trade.domain.de;
access_log /var/log/nginx/access.log vhost;
ssl_certificate /etc/letsencrypt/live/trade.domain.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/trade.domain.de/privkey.pem;
# include common ssl parameters
include /etc/nginx/server_ssl.conf;
location / {
proxy_pass http://$trader_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
# WebSocket (for Live-Charts & Notifications)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Timeouts & Buffering
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_buffering off;
}
}
Have fun!
Operational stuff
Backtesting
We already created the required ‘backtest_results’ folder within our ‘user_data’ folder during initial setup.
To enable backtesting in the UI you need to add the following to your config.json
{
...
"backtest_breakdown": ["day", "week", "month"],
"enable_backtesting_ui": true,
...
}
I have a seperate bot in dry-mode and backtesting mode that I only use for backtesting strategies.
After your config.json is ready for the test, restart your bot
systemctl restart freqtrade-Backtest
Now start the backtest
This step takes some time depending on strategy complexity and time range
docker exec -it freqtrade-Backtest freqtrade backtesting --timerange 20230101-20250101
After it has finished find the results printed to your CLI
or open the web ui and navigate to ‘Backtest’ –> ‘Load Results’ find the just created backtest and click the arrow button at the end of its line to get graphical results.