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

  1. Create a DNS record for *.trade.domain.de
  2. Create a wildcard certificate with LetsEncrypt for *.trade.domain.de
  3. Create a virtual host in nginx for your wildcard domain.
  4. 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.

Leave a Reply