Audits › hummingbot/hummingbot
Open-source trading bot · audit
hummingbot/hummingbot
Open source software that helps you create and deploy high-frequency crypto trading bots
Repository facts
- Repository
- hummingbot/hummingbot
- Stars
- 20,035
- Forks
- 4,932
- Open issues
- 162
- Language
- Python
- License
- Apache-2.0
- Created
- 2019-04-02
- Last push
- 2026-09-17
- README names exchanges
- binance, coinbase, kraken, kucoin, bybit, okx, bitget, gate.io, hyperliquid, dydx
- README mentions an LLM
- yes
- 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 · master @ tre
21 of 21 controls checked: 6 present, 6 partial, 3 absent, 5 not applicable, 1 not verified.
- Main risk
- No global exposure/leverage cap and no exchange-side (only process-dependent) stop-loss: if the bot process dies or loses connection, open positions lose their only protection until it comes back, and nothing stops many small orders from adding up to an oversized total position.
- Summary
- Hummingbot is a large (20k-star, Apache-2.0) open-source Python framework for running automated crypto trading bots across many centralized and decentralized exchanges. Its core execution engine (this repo) has no built-in LLM decision-making; a separate project called Condor plugs LLMs into it. Order sizing is set directly by the user's own config and only checked against available balance, there is no account-wide exposure/leverage cap, and stop-losses are soft (a live-process market order, not a resting exchange stop), so a crashed or disconnected bot can leave a position unprotected.
| Control | Verdict | Evidence | Note |
|---|---|---|---|
| Size and exposure | |||
| Maximum order size | Partial | hummingbot/connector/budget_checker.py (class BudgetChecker, methods adjust_candidate / adjust_candidate_and_lock_available_collateral) | Order size comes from the user's own static strategy config (order_amount / total_amount_quote); BudgetChecker only shrinks it if available balance is insufficient, it never enforces an independent absolute ceiling regardless of config or calculation bugs. |
| Execution paths that skip the cap | Not verified | Would require checking every legacy strategy under hummingbot/strategy/, every V2 controller under hummingbot/strategy_v2/, and every script under scripts/ to confirm each one calls BudgetChecker/OrderCandidate before sending an order. | Not verifiable in this session: repo is 566MB / hundreds of files and GitHub code search is capped at 10 requests/minute, insufficient to cover that full surface with the session budget. |
| Total exposure and leverage | Absent | GET /search/code?q=max_active_positions OR max_position OR position_limit repo:hummingbot/hummingbot -> total_count 0 (2026-09-17) | BudgetChecker only checks available balance for one order at a time; no aggregate exposure cap or account-wide leverage limit across positions/strategies was found. |
| Brakes and stops | |||
| Global circuit breaker | Partial | hummingbot/core/utils/kill_switch.py, class ActiveKillSwitch.check_profitability_loop() | Stops the whole bot (trading_core.shutdown()) once profitability crosses a configured +/- threshold; it is opt-in (PassThroughKillSwitch is a no-op default) and based on % profitability, not on drawdown or a count of consecutive failed orders. |
| Orphaned stop-loss | Absent | hummingbot/strategy_v2/executors/position_executor/position_executor.py, constructor: raises ValueError unless triple_barrier_config.stop_loss_order_type == OrderType.MARKET ("Only market orders are supported for time_limit and stop_loss") | The stop-loss is a soft stop: a market order the live process sends when its own control loop detects the price crossed the level. No native resting stop order is placed on the exchange, so if the process dies or disconnects, the position is unprotected until it comes back. |
| Orderly shutdown | Present | hummingbot/client/command/stop_command.py, StopCommand.stop_loop() | On stop it calls strategy.on_stop(), stop_strategy(), cancel_outstanding_orders() (unless skip_order_cancellation is set), disconnects connectors and stops the clock. |
| Connection and operation | |||
| Websocket and data reconnection | Partial | hummingbot/core/api_throttler/async_throttler.py (AsyncRequestContext.within_capacity, rate-limit waiting); hummingbot/core/web_assistant/connections/ws_connection.py (detects closed socket, raises ConnectionError, handles ping/pong) | HTTP rate-limit handling (429-style) exists at the throttler layer. The base WS connection class detects disconnects but does not itself reconnect; the retry/backoff loop is delegated to each connector's own data source, which was not individually audited (out of budget). |
| Duplicate-process lock | Absent | GET /search/code?q=pid_file OR lockfile OR filelock repo:hummingbot/hummingbot -> total_count 0 (2026-09-17) | No mechanism found to prevent two instances from running against the same account at once. |
| Heartbeat and alerts | Present | hummingbot/remote_iface/mqtt.py, class TopicSpecs: HEARTBEATS = '/hb', NOTIFICATIONS = '/notify'; hummingbot/notifier/notifier_base.py | The bot publishes a heartbeat topic and a notification topic over MQTT that can be watched externally. |
| Accounting and reconciliation | |||
| Position reconciliation with the exchange | Partial | hummingbot/connector/client_order_tracker.py, restore_tracking_states() and process_order_not_found() (lost_order_count_limit=3) | On restart it restores in-flight orders from a locally saved state and re-polls the exchange for those known orders; an order not found after 3 tries is marked lost/failed. No evidence found of a full startup reconciliation that fetches ALL open exchange positions/orders and detects ones the bot never knew about (e.g. opened manually or left over from a crash). |
| Fees and funding in the accounting | Present | hummingbot/core/utils/estimate_fee.py (maker/taker fee estimation); hummingbot/model/funding_payment.py (perpetual funding payment record) | Both trading fees and perpetual funding payments are modeled and recorded. |
| Order rejection handling | Present | hummingbot/connector/client_order_tracker.py, process_order_not_found() | Counts 'order not found' failures with a bounded limit (3) before marking the order FAILED and firing MarketOrderFailureEvent; it does not retry indefinitely. |
| Auditable log | Present | hummingbot/client/command/stop_command.py references self.trading_core.markets_recorder; hummingbot/model/ contains SQL-backed models (e.g. funding_payment.py) persisting trading data locally | A persistent recorder captures market/order/trade data to a local database. |
| Security | |||
| API key permissions | Partial | GET /search/code?q="/withdraw" repo:hummingbot/hummingbot path:connector -> total_count 0 (2026-09-17) | The connector code never calls withdrawal/transfer endpoints. Whether the official docs (hummingbot.org, outside this repo) explicitly instruct users to create a no-withdrawal, IP-restricted API key was not checked in this session (budget). |
| Secrets handling | Present | hummingbot/client/config/security.py, class Security (login/decrypt_all/api_keys); README.md: "hbot connect binance # store API keys (encrypted)" | API keys are stored encrypted under conf/ using a master password (config_crypt.PASSWORD_VERIFICATION_PATH) and decrypted only in memory. |
| Authenticated remote control | Partial | hummingbot/remote_iface/mqtt.py, class MQTTCommands (start/stop/config/import commands over MQTT topics) | The class itself implements no per-user authorization list; access control depends entirely on the external MQTT broker's own authentication (username/password/TLS), which the operator must configure separately. |
| AI and learning | |||
| The model cannot override the brakes | Not applicable | GET /search/code?q=openai OR anthropic OR ChatCompletion repo:hummingbot/hummingbot -> total_count 0 (2026-09-17) | This repo's execution engine does not integrate any LLM decision-maker itself. |
| Model output validation | Not applicable | Same search as above, total_count 0 | No LLM output to validate in this repo. |
| Learns from its mistakes | Not applicable | Same search as above, total_count 0 | No self-adjusting/AI learning loop found in this repo. |
| Model poisoning | Not applicable | Same search as above, total_count 0 | No third-party text is fed into a model within this repo. |
| Behavior without model quota or response | Not applicable | Same search as above, total_count 0 | N/A: no LLM dependency in this repo's execution engine. Note: README.md (2026-09-17) points to a separate sibling project, 'Condor' (github.com/hummingbot/condor), described as 'the AI harness' that connects LLM decision-making to this engine via its API — that project is out of scope for this audit of hummingbot/hummingbot. |
Audit summary — hummingbot/hummingbot (for a non-technical reader)
**What is it:** Hummingbot is a free, open-source (Apache-2.0) software framework, 20,000+ GitHub stars, that lets anyone run automated crypto trading bots — market making, arbitrage, DCA, and custom strategies — connected to their own exchange account.
**Which exchanges:** Dozens of centralized and decentralized exchanges (confirmed: Binance, Hyperliquid, Solana-based DEXs among the repo's listed topics); the full connector list was not enumerated line by line in this audit, as it was out of scope for the risk checklist.
**Audited:** branch `master`, tree commit `2bfaccc48dd49e71a5b6d9b3011808e127dd00cd`, last pushed 2026-09-17 11:30 UTC. Audit performed 2026-09-17, read-only (no install, no clone, no execution).
**What is solid:** API keys are stored encrypted on disk under a master password, never in plain code (`hummingbot/client/config/security.py`). Fees and perpetual funding payments are tracked. A persistent local database records orders and trades. Stopping the bot cleanly cancels open orders. Order-not-found failures are capped (3 tries) before being marked failed instead of retrying forever. A "kill switch" can stop the whole bot once profit/loss crosses a set percentage — but it is optional and off by default in the base class.
**What is missing or weak (the real gaps):**
1. **No account-wide position/exposure cap.** Each order is checked only against available balance for that one order; nothing stops many small orders from adding up to a dangerously large total position or leverage.
2. **Stop-losses are "soft."** In the newer strategy engine, a stop-loss is a market order the live bot process sends when it notices the price crossed a line — it is not a real stop order resting on the exchange. If the bot crashes, loses its internet connection, or the computer restarts, that protection disappears until someone gets it running again.
3. **No lock against running two copies at once** against the same account — nothing in the code was found to prevent duplicate orders from two instances.
4. **Remote control (MQTT) has no built-in user whitelist** inside the bot itself — anyone who can reach the configured MQTT broker with valid broker credentials can send start/stop/config commands; safety depends entirely on how the operator locks down that external broker.
5. **Startup reconciliation is partial.** The bot restores its own saved order list and re-checks those specific orders with the exchange, but there's no evidence it scans the exchange for positions/orders it never knew about (e.g., opened by hand or left over from an earlier crash).
**On AI:** This repository's trading engine does not itself call any AI/LLM model — searches for OpenAI/Anthropic-style integrations returned zero results. The project's own README points to a separate sibling project, "Condor," described as the AI harness that connects LLM decision-making to this engine; Condor is a different repository and was out of scope for this audit.
**Main risk:** with no exposure cap and a stop-loss that depends on the bot process staying alive and connected, a crash, a dropped connection, or simply many small orders piling up can leave real money exposed with nothing automatically limiting the damage.
Badge for the README
<a href="https://saasfactoryagents.com/bots/hummingbot-hummingbot/"><img src="https://saasfactoryagents.com/bots/hummingbot-hummingbot/badge.svg" alt="risk controls audit: 6/21 present"></a>
Fixed a control? Request a free re-audit at the new commit.
Exchanges
Also named in the README: binance, kucoin, bybit, okx, bitget, gate.io, hyperliquid, dydx.
Running hummingbot 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.