Audits › Lumiwealth/lumibot

Open-source trading bot · audit

Lumiwealth/lumibot

Backtestable AI trading agents and Python algorithmic trading strategies for stocks, options, crypto, futures, forex, SEC filings, FRED macro data, and real brokers.

Repository facts

Repository
Lumiwealth/lumibot
Stars
2,074
Forks
401
Open issues
91
Language
Python
License
GPL-3.0
Created
2020-09-10
Last push
2026-09-14
README names exchanges
binance, coinbase, kraken, kucoin, bybit, okx, alpaca, ccxt
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 · branch dev @

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

Main risk
An AI trading agent with allow_trading=True can call the built-in order-submission tool directly; outside Polymarket's broker-specific $5 default market-buy cap, no framework-enforced size limit, exposure limit or circuit breaker was found to stop an oversized or manipulated (e.g. news-injected) model decision from becoming a real order on any other supported broker.
Summary
Lumibot is an open-source (GPL-3.0) Python framework, 2,074 GitHub stars, that lets strategies place real orders on Alpaca, Interactive Brokers, Schwab, Tradier, Tradovate, ProjectX, Bitunix, several CCXT crypto exchanges and Polymarket, and now lets an LLM agent (OpenAI, Anthropic, Gemini, Grok, etc.) reason and submit those orders itself inside the same backtest-to-live pipeline. Paper-trading defaults and environment-variable-based secret handling are solid and confirmed. The gap is risk containment around the AI agent: there is no framework-wide circuit breaker, order-size cap, or exposure limit that applies by default across brokers -- only one broker (Polymarket) ships a hard $5 default cap on market buys -- and third-party text fed to an agent (e.g. news headlines) is not isolated from being read as instructions.
ControlVerdictEvidenceNote
Size and exposure
Maximum order sizePartialdocs/ENV_VARS.md: 'POLYMARKET_MAX_MARKET_ORDER_NOTIONAL: hard cap for market BUY dollar amount; defaults to 5' (raw.githubusercontent.com/Lumiwealth/lumibot/dev/docs/ENV_VARS.md, read 2026-09-17)
Execution paths that skip the capAbsentSame ENV_VARS.md entry: the only cap found is scoped to 'market BUY dollar amount' on one broker; no single control point shared by all order-submission paths (agent tools orders.submit, strategy.submit_order, all broker adapters) was found in the docs reviewed.
Total exposure and leverageAbsentNo env var, doc or code hit for a portfolio-wide exposure/leverage/position-count limit was found across docs/ENV_VARS.md, docs/AI_AGENT_FLOWS.md or the code-search terms tried.
Brakes and stops
Global circuit breakerAbsentGET /search/code?q=circuit_breaker+OR+kill_switch+OR+max_daily_loss+repo:Lumiwealth/lumibot -> total_count: 0 (2026-09-17). GET /search/code?q=drawdown+repo:Lumiwealth/lumibot -> 70 hits, dominated by docs/TEARSHEET_METRICS.md (a post-hoc backtest reporting metric, not a live trading halt).
Orphaned stop-lossNot verifiedNo queried directly: would require reading each broker adapter's order-submission code (alpaca.py 84 KB, schwab.py 158 KB, tradier.py 104 KB, etc.) to see whether stop-loss orders are placed as broker-native conditional orders or simulated in-process.
Orderly shutdownPartialraw.githubusercontent.com/.../lumibot/traders/trader.py: `signal.signal(signal.SIGINT, self._stop_pool)` is registered for both live and backtest runs; `_stop_pool` calls `strategy_thread.stop()` for every non-abruptly-closed strategy.
Connection and operation
Websocket and data reconnectionPartialdocs/FAST_ORDER_LIFECYCLE_GUIDE.md, section 'Schwab Profile': 'uses account-activity WebSocket messages as a wake-up signal... performs an active-order reconciliation after login or reconnect and retains a 30-second broad order-history poll only as a healing fallback' and 'Schwab 429 responses suppress more reads... for the server's Retry-After interval, or bounded exponential backoff with jitter when that header is absent.'
Duplicate-process lockAbsentGET /search/code?q=lockfile+OR+pidfile+OR+flock+repo:Lumiwealth/lumibot -> total_count: 0 (2026-09-17).
Heartbeat and alertsPartialdocs/AI_AGENT_NOTIFICATIONS.md: native `self.notify(...)` / `self.notifications.configure_telegram(...)` outbound alerting exists, but 'Backtests disable notifications by default' and it must be called explicitly by the strategy author. The only 'heartbeat' hits found (docs/ENV_VARS.md, BACKTESTING_PROGRESS_HEARTBEAT*) are for a backtest progress-bar UI, not a live health/watchdog signal.
Accounting and reconciliation
Position reconciliation with the exchangePartialdocs/FAST_ORDER_LIFECYCLE_GUIDE.md: the order state machine includes 'a bounded exact-order reconciliation read after a missed callback, restart, reconnect, or ambiguous mutation result', confirmed implemented for Schwab ('performs an active-order reconciliation after login or reconnect').
Fees and funding in the accountingPartiallumibot/example_strategies/agent_news_sentiment.py passes `TradingFee(percent_fee=0.001)` as buy/sell fees into `.backtest(...)`, showing a fee-modeling entity (`lumibot.entities.TradingFee`) exists for backtesting.
Order rejection handlingPartialdocs/FAST_ORDER_LIFECYCLE_GUIDE.md testing matrix explicitly lists 'rejected hedge and bounded retry' as something a regression suite 'should cover', and states 'the strategy still owns its deadline, replacement, hedge, and conflict policy. Do not turn one strategy's timeout or risk rule into a global LumiBot default.'
Auditable logPresentlumibot/traders/trader.py `_set_logger()`: 'Live trades should always have full logging for both console and file' (file handler added via add_file_handler). docs/FAST_ORDER_LIFECYCLE_GUIDE.md recommends a structured telemetry contract (order.submit.request, order.cancel.response, etc.). docs/ENV_VARS.md documents `LUMIBOT_BACKTEST_AUDIT` per-fill audit columns for backtests.
Security
API key permissionsNot verifiedGET /search/code?q=withdraw+repo:Lumiwealth/lumibot+path:lumibot/brokers -> 3 hits (alpaca.py, broker.py, and one more), not individually inspected line-by-line within the session budget.
Secrets handlingPresent.secrets/lumi_secrets.env.example and .env.local.example (raw.githubusercontent.com, read 2026-09-17) contain only placeholders and the header 'THIS IS AN EXAMPLE FILE, DO NOT ADD YOUR KEYS HERE, THEY WILL BE CHECKED IN TO GIT... This file is not stored in GitHub'. AGENTS.md and SECURITY.md both state the repo uses 'GitHub secret scanning with push protection plus a lightweight public-hygiene CI check for instruction files'.
Authenticated remote controlNot applicabledocs/AI_AGENT_NOTIFICATIONS.md describes Telegram only as an OUTBOUND notification channel (bot -> user messages); no inbound command/control feature (e.g. a Telegram command that stops the bot or closes a position) was found in the docs reviewed.
AI and learning
The model cannot override the brakesPartialdocs/AI_AGENT_FLOWS.md documents a 'Risk gate' pattern ('Python applies hard limits after an agent recommendation, such as max position size, no shorting, symbol allowlists, drawdown stops, or per-trade dollar limits') and a safety default ('LumiBot defaults the whole-agent retry budget to one attempt' when mutating order tools are available, to avoid duplicate order submission on retry).
Model output validationPartiallumibot/components/agents/asset_resolution.py is a dedicated symbol-resolution module. docs/AGENT_EVALS.md release-gate cases include 'stock_price_before_order' (price evidence required before ordering) and 'options_single_leg_chain_and_quote' (exact-contract verification before ordering); docs/AI_TRADING_AGENTS.md describes the options-trading skill doing 'exact-contract verification... signed package pricing'.
Learns from its mistakesPartialdocs/AI_AGENT_MEMORY.md: agents can call `remember_lesson` ('stores proposed lessons by default. Pass outcome metadata with validated=True when a lesson has been validated by later outcome data') and theses receive daily 'thesis.outcome_observed' events.
Model poisoningAbsentlumibot/example_strategies/agent_news_sentiment.py: the canonical `search_news` @agent_tool returns raw third-party headline/summary text directly as the tool result with no sanitization, delimiting, or 'treat as data not instruction' wrapper. GET /search/code?q=sanitize+OR+untrusted+OR+injection+repo:Lumiwealth/lumibot -> 1 hit, in CHANGELOG.md, unrelated to a defense mechanism.
Behavior without model quota or responseNot verifieddocs/AGENT_EVALS.md documents a `--max-cost-usd` flag for the local CI eval runner (a cost ceiling for automated testing), but this governs test runs, not live-strategy behavior.

Risk Controls Audit: Lumiwealth/lumibot

**What it is:** Lumibot is a free, open-source Python framework (GPL-3.0 license, 2,074 GitHub stars) for building trading bots. It connects to real brokers -- Alpaca, Interactive Brokers, Charles Schwab, Tradier, Tradovate, ProjectX/TopstepX futures, the crypto exchange Bitunix, several exchanges via the generic CCXT library, and Polymarket -- so a strategy written in it can place real orders with real money, in both paper and live modes.

**The new part:** Lumibot now lets you plug in an AI model (OpenAI, Anthropic, Google Gemini, Grok, etc.) that reads market data, calls tools, and decides what to buy or sell on its own, every trading cycle, using the exact same code in backtests and in live trading.

**What's solid:** Paper-trading (practice-money) mode is the documented default. API keys and secrets are meant to be kept in environment variables and local files that are never committed to the public code, and the project's automated checks specifically scan for leaked keys before anything is published.

**What's missing:** There is no single, framework-wide "stop everything" switch. We searched the entire codebase for a daily-loss circuit breaker, a kill switch, or a maximum-drawdown trading halt, and found none -- drawdown is only calculated afterward, in performance reports, not used to stop trading. Only one of the nine supported brokers (Polymarket) has a hard dollar cap on order size, and it only covers one order type (market buys), defaulting to $5. For every other broker -- including the AI-agent path -- there is no built-in ceiling on how large an order the AI (or a buggy strategy) can place. There is also no lock file to stop two copies of the same bot running at once, and no automatic "the bot died silently" alert; notifications exist but only if the person coding the strategy wires them up.

**The AI-specific risk:** the framework lets an AI agent submit real orders directly. It documents an optional "risk gate" pattern (Python code double-checking the AI's decision before it executes), but does not force anyone to use it. We also found the reference example that feeds live news headlines to the AI does so as raw, unfiltered text -- there is no protection against a manipulated or fake headline talking the AI into a bad trade.

**Bottom line / main risk:** an AI agent connected to a live broker account can decide on its own to buy or sell, and -- aside from a $5 cap that only exists for one niche prediction-market broker -- nothing in Lumibot automatically stops it from sizing that order too large, and nothing automatically halts trading after a string of losses.

**Audited:** GitHub repository `Lumiwealth/lumibot`, default branch `dev`, tree snapshot `f987da3e2c81a5ae2cb6edf35457d2aa54aacf8b`, read on 2026-09-17. Public code, documentation, and example strategies only; nothing was installed or executed.

Badge for the README

risk controls audit: 2/21 present

<a href="https://saasfactoryagents.com/bots/lumiwealth-lumibot/"><img src="https://saasfactoryagents.com/bots/lumiwealth-lumibot/badge.svg" alt="risk controls audit: 2/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, alpaca, ccxt.

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