Audits › freqtrade/freqtrade
Open-source trading bot · audit
freqtrade/freqtrade
Free, open source crypto trading bot
Repository facts
- Repository
- freqtrade/freqtrade
- Stars
- 54,471
- Forks
- 11,295
- Open issues
- 28
- Language
- Python
- License
- GPL-3.0
- Created
- 2017-05-17
- Last push
- 2026-09-17
- README names exchanges
- binance, kraken, kucoin, bybit, okx, bitget, hyperliquid, ccxt
- README mentions an LLM
- no
- Backtesting mentioned
- yes
- Paper trading / dry run mentioned
- yes
Source: GitHub API, 2026-09-17. Exchange and LLM mentions come from a keyword scan of the README, not from running the bot.
Risk-control audit
Audited 2026-09-17 · 3774521e7028
12 of 21 controls checked: 6 present, 4 partial, 1 absent, 1 not applicable, 0 not verified. The other 9 were added to the checklist after this audit.
- Main risk
- No technical multiple-instance lock (lockfile ausente) combined with reconciliation that only runs at startup (reconciliacion parcial): if a user or a supervisor process accidentally starts a second instance against the same exchange account, or the bot's local DB drifts from the exchange mid-session (e.g. after a long network outage), nothing in freqtrade itself detects or blocks it until the next restart.
- Summary
- Freqtrade is a mature, widely-used open-source crypto trading bot (54k+ GitHub stars) with real per-trade and per-account position-size caps, bounded/backed-off retries for both order placement and network reconnects, an opt-in circuit-breaker style Protections system, and persistent logging/DB of every trade. The two clearest gaps versus the checklist are: no technical lock against running two instances against the same account/DB (pure documentation discipline), and reconciliation between the bot's database and the exchange's real positions/orders happens only at startup, not continuously while running.
| Control | Verdict | Evidence | Note |
|---|---|---|---|
| Size and exposure | |||
| Maximum order size | Present | docs/configuration.md (Parameters table): stake_amount, max_open_trades, tradable_balance_ratio -- https://raw.githubusercontent.com/freqtrade/freqtrade/3774521e7028fa666770e7c7a8da323af5c4cefa/docs/configuration.md | Per-trade size is capped by stake_amount (in quote currency) and total exposure by max_open_trades x tradable_balance_ratio; both are mandatory config fields. |
| Execution paths that skip the cap | Partial | docs/configuration.md, key 'max_entry_position_adjustment' -- same URL as above | Normal entries always size from stake_amount, but the DCA/position-adjustment route (adjust_trade_position callback) is bounded by a separate parameter, not by the same stake cap, so it is a distinct control rather than a shared one. |
| Total exposure and leverage | Not in this audit | Added to the checklist after this audit; covered at the next re-audit. | |
| Brakes and stops | |||
| Global circuit breaker | Present | freqtrade/plugins/protections/{iprotection.py, cooldown_period.py, max_drawdown_protection.py, stoploss_guard.py, low_profit_pairs.py} at commit 3774521e7028fa666770e7c7a8da323af5c4cefa (contents API listing, 2026-09-17) | Opt-in Protections system (must be added to strategy.protections). max_drawdown_protection.py stops new entries after account drawdown; stoploss_guard.py stops after N consecutive stop-losses. It blocks NEW entries only -- it does not force-close already open positions. |
| Orphaned stop-loss | Partial | docs/stoploss.md ('stoploss_on_exchange': False default; note on bot recreating a manually-cancelled exchange stop) -- https://raw.githubusercontent.com/freqtrade/freqtrade/3774521e7028fa666770e7c7a8da323af5c4cefa/docs/stoploss.md | If stoploss_on_exchange is explicitly enabled, the stop lives as a real order on the exchange and survives a bot crash/restart. It is OFF by default; with it off, the stop only exists in the bot's own loop and disappears if the process dies. |
| Orderly shutdown | Not in this audit | Added to the checklist after this audit; covered at the next re-audit. | |
| Connection and operation | |||
| Websocket and data reconnection | Present | freqtrade/exchange/common.py (retrier / retrier_async decorators, API_RETRY_COUNT=4, calculate_backoff); freqtrade/freqtradebot.py (daily self._schedule.every().day.at('00:02').do(self.exchange.ws_connection_reset)) -- both at commit 3774521e7028fa666770e7c7a8da323af5c4cefa | Bounded retries (4 attempts) with exponential backoff on TemporaryError/DDosProtection for both REST and websocket (ccxt.pro) calls, plus a scheduled daily websocket reset. |
| Duplicate-process lock | Absent | GET /search/code?q=flock+repo:freqtrade/freqtrade -> 0 results (2026-09-17); docs/advanced-setup.md 'Running multiple instances' section -- https://raw.githubusercontent.com/freqtrade/freqtrade/3774521e7028fa666770e7c7a8da323af5c4cefa/docs/advanced-setup.md | No PID file, flock or semaphore found in the codebase. The docs rely entirely on manual discipline (separate DB files, ports, Telegram bots) to avoid collisions between instances; nothing technical prevents two processes from trading the same account/DB at once. |
| Heartbeat and alerts | Not in this audit | Added to the checklist after this audit; covered at the next re-audit. | |
| Accounting and reconciliation | |||
| Position reconciliation with the exchange | Partial | freqtrade/freqtradebot.py, FreqtradeBot.startup() calling self.startup_update_open_orders() with code comment 'Only update open orders on startup' -- https://raw.githubusercontent.com/freqtrade/freqtrade/3774521e7028fa666770e7c7a8da323af5c4cefa/freqtrade/freqtradebot.py | Open orders/positions are synced against the exchange once, at startup or on /reload_config. The main process() loop that runs every iteration does not repeat this reconciliation against exchange state. |
| Fees and funding in the accounting | Present | docs/exchanges.md (Gate.io 'unknown_fee_rate' for POINT fee currency, Binance/Kucoin fee-currency notes); freqtrade/freqtradebot.py update_funding_fees()/get_funding_fees() for futures trades; per-exchange fee overrides in freqtrade/exchange/gate.py and freqtrade/exchange/bitpanda.py (code search hit for get_trades_for_order, 2026-09-17) | Maker/taker fees are fetched per exchange from real fills where possible, with a manual fallback rate for unsupported fee currencies; funding fees for futures positions are recalculated on a schedule. |
| Order rejection handling | Present | freqtrade/exchange/common.py, @retrier / @retrier_async decorators (API_RETRY_COUNT=4, calculate_backoff exponential delay, logs 'Retrying still for N times' / 'Giving up.') -- https://raw.githubusercontent.com/freqtrade/freqtrade/3774521e7028fa666770e7c7a8da323af5c4cefa/freqtrade/exchange/common.py | Retries are bounded (default 4 attempts) and logged on every attempt; the RetryableOrderError path is used specifically for order operations. |
| Auditable log | Present | freqtrade/freqtradebot.py (logger.info/warning/exception used throughout); docs/advanced-setup.md docker-compose example with '--logfile /freqtrade/user_data/logs/freqtradeN.log'; freqtrade.persistence Order/Trade models persisted to SQLite -- URLs as above | Standard Python logging to file plus a persistent SQLite database of every Trade/Order (amount, price, fees, timestamps, state) that survives restarts. |
| Security | |||
| API key permissions | Partial | docs/exchanges.md, Gate.io section ('Spot Trade'/'Perpetual Futures' RW + 'Wallet' read-only + 'Account' read-only) and Bybit section ('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.') -- same URL as above | Per-exchange docs list minimal required scopes and none ask for withdrawal permission, but an explicit IP-restriction recommendation is only documented for Bybit, not as a universal rule for every supported exchange. |
| Secrets handling | Not in this audit | Added to the checklist after this audit; covered at the next re-audit. | |
| Authenticated remote control | Not in this audit | Added to the checklist after this audit; covered at the next re-audit. | |
| AI and learning | |||
| The model cannot override the brakes | Not in this audit | Added to the checklist after this audit; covered at the next re-audit. | |
| Model output validation | Not in this audit | Added to the checklist after this audit; covered at the next re-audit. | |
| Learns from its mistakes | Not in this audit | Added to the checklist after this audit; covered at the next re-audit. | |
| Model poisoning | Not in this audit | Added to the checklist after this audit; covered at the next re-audit. | |
| Behavior without model quota or response | Not applicable | docs/index.md feature list (strategy in Python/pandas, backtesting, hyperopt, optional FreqAI machine-learning module) -- https://raw.githubusercontent.com/freqtrade/freqtrade/3774521e7028fa666770e7c7a8da323af5c4cefa/docs/index.md; no LLM (Claude/GPT) client found in the dependency/feature list | Freqtrade's own decision loop does not call an external LLM; strategies are Python/pandas indicator code, with an optional classic-ML module (FreqAI). This checklist point targets bots like the one in the audited video that route decisions through an LLM API -- freqtrade's core does not do that. |
Risk-control audit: freqtrade/freqtrade
**What it is:** Freqtrade is a free, open-source crypto trading bot written in Python (GPL-3.0 license, 54,000+ GitHub stars, actively maintained). Users write a strategy in Python/pandas, connect it to an exchange API key, and the bot places real (or simulated, in dry-run mode) buy/sell orders automatically.
**Exchanges supported:** binance, binanceus, binanceusdm, bingx, bitget, bybit, bybiteu, gate, gateeu, htx, hyperliquid, kraken, krakenfutures, okx, myokx (per freqtrade/exchange/common.py).
**Audited at:** commit `3774521e7028fa666770e7c7a8da323af5c4cefa`, branch `develop`, read on 2026-09-17. Public code and documentation only — nothing was installed or executed.
What is solid
- **Order size caps exist and are mandatory**: every trade is bounded by `stake_amount` (money per trade) and `max_open_trades` (number of concurrent trades) — the bot won't even start without them.
- **Retries are bounded, not infinite**: rejected orders and dropped network/websocket connections retry a fixed number of times (default 4) with growing delays, then give up and log it — this stops a bad connection from spamming the exchange or silently hanging forever.
- **A circuit-breaker exists but is opt-in**: freqtrade ships "Protections" (max-drawdown lock, stop-loss-guard lock, cooldown) that can stop the bot from opening new trades after losses pile up. It has to be turned on in the strategy — it is not on by default, and it does not force-close positions that are already open.
- **Fees are handled**: the bot pulls real trading fees from the exchange per trade where possible, with a documented manual fallback for exchanges with unusual fee currencies.
- **Full logging and trade history**: every trade and order is written to a persistent local database with prices, amounts, fees and timestamps, plus a standard log file.
What is weaker or missing
- **No lock against running two copies at once.** There's no PID file or similar technical guard. The documentation just tells users to manually use separate database files if they run more than one instance — nothing stops two accidental instances from trading the same exchange account and doubling up orders.
- **The bot's local record of open orders/positions is only checked against the exchange once, at startup.** While running, it does not re-verify that what it thinks is open still matches what the exchange actually shows.
- **The stop-loss only lives on the exchange (surviving a crash) if the user explicitly turns on `stoploss_on_exchange`** — it is off by default, in which case the stop only exists inside the running bot process.
- **Required API-key permissions are documented per exchange** (and none of them ask for withdrawal rights), but the advice to also restrict the key to a specific IP address is only spelled out for one exchange (Bybit), not as a rule for all of them.
- **The bot does not use an LLM to decide trades** — strategies are plain Python/pandas rules (with an optional classic machine-learning add-on), so an LLM running out of quota or answering badly is not a risk that applies to freqtrade's own code.
Main risk
The combination of (1) no built-in protection against a second instance accidentally trading the same account, and (2) the bot only double-checking its own records against the real exchange positions at startup, not while running. In practice this means a stale or duplicated bot could keep acting on outdated assumptions about what it already bought or sold until it is manually restarted.
Commit audited: `3774521e7028fa666770e7c7a8da323af5c4cefa` (branch `develop`), read 2026-09-17.
Badge for the README
<a href="https://saasfactoryagents.com/bots/freqtrade-freqtrade/"><img src="https://saasfactoryagents.com/bots/freqtrade-freqtrade/badge.svg" alt="risk controls audit: 6/12 present"></a>
Fixed a control? Request a free re-audit at the new commit.
Exchanges
- Does freqtrade work with Binance.US?
- Does freqtrade work with Coinbase?
- Does freqtrade work with Kraken?
Also named in the README: binance, kucoin, bybit, okx, bitget, hyperliquid, ccxt.
Running freqtrade with real money?
The watchdog runs apart from the bot with a read-only key and alerts you when drawdown, position size or heartbeat cross your limits. Founding price 19 USD/month, early access open.