Audits › Controls › Model output validation
AI and learning · control 18 of 21
Model output validation: does your trading bot have it?
Does it validate the model's answer (format, existing symbol, side, quantity, price within range) before turning it into an order, and reject malformed or invented answers?
Why it matters
A model that hallucinates a symbol or a price produces a real order.
How to check it in the code
- Search for JSON schema, pydantic, parse, validate near the model call.
- Check unknown symbols and out-of-range prices are rejected, not clamped silently.
- Check a failed parse leads to no trade, not to a default trade.
This is what the audit does for every bot in the list, on public code, without installing or running anything. Verdict values: present, partial, absent, not applicable, not verified. See the method.
Results across audited bots
Across 10 audited bots: 2 present, 5 partial, 0 absent, 2 not applicable, 1 not verified.
| Bot | Verdict | Evidence | Note |
|---|---|---|---|
| HKUDS/Vibe-Trading | Present | agent/src/live/order_guard.py execute(): extractor() returning None denies with 'order intent could not be parsed'; _normalize_intent_notional rejects NaN/non-positive notional fail-closed; enforcement.py check_mandate validates symbol/side/instrument_type/asset_class against whitelists before any order is forwarded | Structural validation happens before any broker call. |
| hummingbot/hummingbot | Not applicable | Same search as above, total_count 0 | No LLM output to validate in this repo. |
| Drakkar-Software/OctoBot | Partial | deep_agent_team.py._parse_result() validates the LLM's JSON via models.DistributionOutput.model_validate()/models.ExecutionPlan.model_validate() (pydantic); ai_index_trading.py.run_with_portfolio() validates portfolio/strategy inputs via models.PortfolioState.model_validate(). | On validation failure, both paths fall back to using the raw/unvalidated data or raw content ('Fall through to create result with raw output', 'Proceeding with raw data') instead of rejecting the response outright — so malformed AI output is not always blocked from continuing downstream. |
| freqtrade/freqtrade | Not verified | ||
| jesse-ai/jesse | Partial | jesse/models/AiModel.py + jesse/controllers/ai_model_controller.py define storage for a generic LLM-style provider (name/provider/base_url/api_key/model_id) but no code path consuming this model at runtime (e.g. to produce an order) was found in the files read | The scikit-learn ml_predict()/ml_predict_proba() pipeline described in README returns a bounded scalar (probability or regression value), which structurally cannot contain an invented symbol/side/price the way a free-text LLM order proposal could; that specific risk (hallucinated order fields) does not apply to it. Could not verify the generative AiModel's consumption path. |
| chrisleekr/binance-trading-bot | Present | apps/web/src/features/backtest/lib/decision-breakdown.ts (ConfigRecommendation.apply as a pure transform over the same TTConfig schema) | AI suggestions compose onto a schema-valid base config through pure, whitelisted patch functions and must still pass the same schema/feasibility validation as any manual edit before they can be saved or backtested — a malformed or hallucinated suggestion cannot become an arbitrary order. |
| alsk1992/CloddsBot | Partial | Claude's tool-use API constrains agent output to the declared JSON tool schema (inherent format validation from the Anthropic SDK, imported in src/agents/index.ts). Once a call reaches the guarded path, enforceMaxOrderSize/enforceExposureLimits bound price*size. No dedicated check for 'does this symbol exist on the target exchange' prior to submission was found within budget. | Format is validated by the SDK; semantic validation of hallucinated symbols/prices is unverified. |
| Lumiwealth/lumibot | Partial | lumibot/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'. | |
| YizhiSong/FriesTrader | Partial | scripts/rank_candidates.py hard-fails (exit 1) on any candidate whose conviction isn't exactly 'high'/'medium'/'low' -- a real code-level whitelist. A hallucinated/nonexistent symbol would very likely fail the mandatory fresh get_equity_quotes/get_equity_positions calls (Step 4-5), which per Step 6's generic rule gets logged and skipped rather than acted on. | No explicit validation found for price-range plausibility or malformed numeric fields (e.g. a thesis_price of 0 or negative) before those values feed entry_gate.py's arithmetic. |
| c9s/bbgo | Not applicable | same search as decision_ia_filtrada | Not applicable: the bot does not use an AI model to generate orders. |
If your bot does not have it
The watchdog enforces daily loss, drawdown, position size and heartbeat limits from outside the bot, with a read-only key, whatever the bot's own code does.