Audits › c9s/bbgo

Open-source trading bot · audit

c9s/bbgo

The modern cryptocurrency trading bot framework written in Go.

Repository facts

Repository
c9s/bbgo
Stars
1,661
Forks
382
Open issues
128
Language
Go
License
AGPL-3.0
Created
2020-10-05
Last push
2026-09-17
README names exchanges
binance.us, binance, coinbase, kucoin, bybit, okx, bitget
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 · main @ 26293

21 of 21 controls checked: 5 present, 8 partial, 2 absent, 5 not applicable, 1 not verified.

Main risk
Every meaningful safety control (order-size cap, total exposure limit, circuit breaker) is opt-in per strategy rather than enforced centrally, and there is no lockfile guarding against two instances running at once, so an unconfigured or duplicated deployment has no effective limit on order size, exposure, or loss.
Summary
BBGO is a mature, well-architected open-source Go framework (1661 stars, AGPL-3.0) for building crypto trading bots across 9 exchanges; it is not a ready-to-run bot but a toolkit strategy authors assemble. It ships high-quality risk-control building blocks (order/position caps, three kinds of circuit breaker, graceful shutdown, websocket reconnection, authenticated remote control, fee-aware PnL) but almost all of them are opt-in library components a strategy must explicitly wire in, not defaults applied to every strategy. It does not use any LLM for trading decisions.
ControlVerdictEvidenceNote
Size and exposure
Maximum order sizePartialpkg/risk/riskcontrol/position.go (PositionRiskControl.hardLimit, sliceQuantity)A cap exists (max base-currency position + max order slice) but it is an opt-in library component a strategy must instantiate explicitly, not a default.
Execution paths that skip the capAbsentpkg/risk/riskcontrol/position.go; pkg/bbgo/trader.go (generic OrderExecutor path has no built-in cap)There is no central order gate all strategies pass through; any strategy that does not wire in PositionRiskControl sends orders with no size cap at all.
Total exposure and leveragePartialpkg/risk/dynamicrisk/dynamic_exposure.go; pkg/risk/riskcontrol/position.goDynamicExposureBollBand can shrink/grow the allowed exposure band per strategy and PositionRiskControl caps one symbol's base position, but no account-wide leverage/total-notional cap across all strategies and symbols was found.
Brakes and stops
Global circuit breakerPartialpkg/risk/circuitbreaker/basic.go (MaximumConsecutiveLossTimes, MaximumTotalLoss, HaltDuration); pkg/risk/circuitbreaker/errorbreaker.go; pkg/risk/riskcontrol/circuit_break.goThree well-built halt mechanisms exist (consecutive-loss/total-loss breaker, error-rate breaker, 24h PnL breaker), but each is opt-in and must be instantiated per strategy; there is no bot-wide default breaker.
Orphaned stop-lossPartialpkg/types/order.go (OrderTypeStopMarket, OrderTypeStopLimit, OrderTypeTakeProfitMarket, OrderTypeTrailingStopMarket); pkg/risk/riskcontrol/circuit_break.go and position.go (in-memory halt/reduce logic)The framework supports exchange-native stop order types a strategy can place, but the reviewed risk-control components compute halts/position-reduction in memory and re-submit orders live, so those specific protections stop working if the process dies unless the strategy separately placed a native stop.
Orderly shutdownPresentpkg/cmd/run.go (cmdutil.WaitForSignal(SIGINT, SIGTERM), 30s gracefulShutdownPeriod, bbgo.Shutdown, trader.SaveState, session.MarketDataStream.Close()/UserDataStream.Close())On SIGINT/SIGTERM the process runs registered per-strategy Shutdown() callbacks, saves persistence state and closes streams within a 30s window; whether open orders are cancelled depends on each strategy implementing StrategyShutdown.
Connection and operation
Websocket and data reconnectionPresentpkg/exchange/binance/stream.go (OnListenKeyExpired -> stream.Reconnect(), OnServerShutdownEvent -> stream.Reconnect(), handleDisconnect resets depth buffers)Reconnection on listen-key/token expiry and server-initiated disconnects is implemented via a shared StandardStream abstraction; explicit HTTP 429 backoff handling was not directly located in the time available.
Duplicate-process lockAbsentno relevant match; keyword search for 'flock' across the repo returned only unrelated substring collisions (go.mod, pkg/backtest/report.go)No lockfile/PID-file/single-instance guard was found; nothing in pkg/cmd/run.go prevents two instances from running concurrently.
Heartbeat and alertsPresentpkg/notifier/slacknotifier, pkg/notifier/telegramnotifier, pkg/interact/* (command bot)Dedicated Slack and Telegram notifier packages plus an interactive command bot exist for pushing alerts and querying bot status remotely.
Accounting and reconciliation
Position reconciliation with the exchangePartialpkg/bbgo/environment.go (BindSync -> tradeWriterCreator/orderWriterCreator persist trades/orders to DB; futuresPositionWriterCreator calls SyncService.FuturesService.QueryPositionsAndInsert after each futures trade)The bot syncs historical trades/orders and periodically pulls exchange-side futures position risk into the DB, but no explicit startup routine comparing the strategy's in-memory position against the exchange and auto-resolving drift was found.
Fees and funding in the accountingPartialpkg/types/position.go (Position.TotalFee, FeeAverageCosts, FeeRate, NewProfit() computing NetProfit net of trade fee)Trading fees are deducted when computing PnL, but no explicit funding-rate field or accumulator for perpetual futures funding payments was found in the code reviewed.
Order rejection handlingPartialpkg/types/order.go (OrderStatusRejected); pkg/exchange/binance/stream.go (handleExecutionReportEvent)Order rejection is a modeled, observable status propagated through execution-report stream events, but no universal bounded-retry policy at the framework/OrderExecutor level was found.
Auditable logPartialpkg/bbgo/environment.go (OrderService/TradeService insert filled/canceled orders and trades into SQL DB); .env.local.example (DB_DRIVER/DB_DSN)Logging via logrus is pervasive, and orders/trades are persisted with detail when a database is configured, but the database is optional (only wired up if DB_DRIVER/DB_DSN env vars are set) so there is no guaranteed persistent audit trail out of the box.
Security
API key permissionsNot verifieddoc/README.md index has no dedicated API-key-permissions/security guide; pkg/cmd/withdraw.go does not exist (HTTP 404)No documentation recommending a non-withdrawal, IP-restricted key was found, and there is no funds-withdrawal command in pkg/cmd, but a full check of every one of the 9 exchange clients for calls to withdrawal endpoints was not completed within the time/budget available.
Secrets handlingPresent.env.local.example (BINANCE_API_KEY/SECRET, MAX_API_KEY/SECRET, SLACK_TOKEN, DB_DSN); pkg/bbgo/environment.go (os.LookupEnv for DB credentials)Exchange, database and Slack credentials are read from environment variables, not hardcoded in source.
Authenticated remote controlPresentpkg/interact/auth.go (AuthInteract, /auth command requiring Token + TOTP one-time password before session.SetAuthorized())Telegram/Slack interactive commands require passing a secret token and a time-based one-time password before the session is authorized; unauthenticated users cannot issue commands.
AI and learning
The model cannot override the brakesNot applicableGitHub code search for 'openai', 'package aiagent', 'chat/completions' in repo:c9s/bbgo all returned 0 results (2026-09-17)No LLM-based decision-making was found anywhere in the strategy set.
Model output validationNot applicablesame search as decision_ia_filtradaNot applicable: the bot does not use an AI model to generate orders.
Learns from its mistakesNot applicablesame search as decision_ia_filtradaNot applicable: no self-adjusting/learning decision loop based on a model was found.
Model poisoningNot applicablesame search as decision_ia_filtradaNot applicable: no third-party text (news/tweets) is fed into a model.
Behavior without model quota or responseNot applicablesame search as decision_ia_filtradaNot applicable: no LLM dependency exists to run out of quota.

Risk-control audit: c9s/bbgo

**What it is.** BBGO is an open-source cryptocurrency trading bot framework written in Go (AGPL-3.0 license, 1,661 GitHub stars, active development). It is not a ready-to-run bot: it is a toolkit that developers use to write their own trading strategies (grid, DCA, market-making, and dozens of others).

**Exchanges supported.** Binance, MAX, OKX, KuCoin, Bybit, Bitget, Bitfinex, Coinbase and Backpack — 9 exchanges via a shared abstraction layer, so strategies mostly don't need exchange-specific code.

**What is solid.**

**What is missing or weak.**

**Main risk.** The framework gives you good building blocks, but almost nothing is wired in by default — it is on the strategy author to assemble the safety net, and it is easy to forget a piece (or run it twice by accident, since nothing prevents that).

**Audited:** main branch, commit `262939a994a4b172a349b1735077cec46e258e42`, 2026-09-17. Read-only review of public GitHub source; nothing was installed or executed.

Badge for the README

risk controls audit: 5/21 present

<a href="https://saasfactoryagents.com/bots/c9s-bbgo/"><img src="https://saasfactoryagents.com/bots/c9s-bbgo/badge.svg" alt="risk controls audit: 5/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.

Running bbgo 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.