Environment Variables¶
LumiBot supports configuring many behaviors via environment variables. This page documents the variables most commonly used for backtesting, ThetaData, and remote caching.
Important
Never commit secrets (API keys, passwords, AWS secret keys) into any repo or docs. Document variable names and semantics only.
ChatGPT subscription profiles¶
LUMIBOT_CHATGPT_HOME selects the private configuration directory (default
~/.config/lumibot-chatgpt). LUMIBOT_CHATGPT_PROFILE selects an existing
profile ID; LUMIBOT_CHATGPT_PROFILE_PATH explicitly selects a protected file
from your own supported SIWC registration. Processes pin their selected
profile, and refresh rotation is serialized across local processes.
These variables authenticate explicit chatgpt/<model> agents and canonical
subscription-funded evaluations. They do not supply an API key, a broker
credential or a BotSpot research grant. Keep all profile files outside source
control. For subscription-only execution, separately disable connected-app
credit fallback in ChatGPT Usage. See Use your ChatGPT subscription for login, model
discovery, sign-out and self-hosted setup.
Backtesting configuration¶
LUMIBOT_DISABLE_DOTENV¶
Purpose: Disable automatic
.envdiscovery and loading at startup.Values: truthy enables (
1,true,yes); unset/0disables.Default: disabled.
Notes: - When dotenv loading is enabled, LumiBot looks upward from the running script directory for the nearest
.envfile. If none is found there, it also checks upward from the current working directory. - LumiBot no longer recursively scans every nested directory under the start path. This reduces startup latency and lowers the chance of loading an unrelated nested repo’s.envfile. - In production/BotManager/BotSpot runs, prefer injected environment variables and setLUMIBOT_DISABLE_DOTENV=1so local files cannot override runtime secrets.
LUMIBOT_DISABLE_DOTENV_LOCAL¶
Purpose: Skip the optional
.env.localoverride file while still allowing the primary.envfile.Values: truthy enables (
1,true,yes,on); unset/0disables.Default: disabled.
Notes: - When dotenv loading is enabled and a
.envfile is found, LumiBot also loads a sibling.env.localafter.envwith override behavior. - Use.env.localonly for local developer overrides. Do not commit it. - SetLUMIBOT_DISABLE_DOTENV_LOCAL=1in repeatable test or deployment contexts where the base.envshould be loaded but local overrides must be ignored.
LUMIBOT_LOG_LEVEL¶
Purpose: Control LumiBot startup logging before full logger setup.
Values:
DEBUG,INFO,WARNING,ERROR,CRITICAL.Default:
INFO.Example: set
LUMIBOT_LOG_LEVEL=ERRORto suppress the import-timeLumiBot v... startingmessage and skip import-time console logger setup.
IS_BACKTESTING¶
Purpose: Signals backtesting mode for code that explicitly reads this value.
Values:
True/False(string).It does not choose a runner by itself: a file that only calls
Strategy.backtest()still backtests when this isFalse. A localIS_BACKTESTINGassignment in an example is independent of this variable. See Backtest, paper, or live: choose the runner.
BACKTESTING_START / BACKTESTING_END¶
Purpose: Default date range used when dates are not passed in code.
Format:
YYYY-MM-DD
BACKTESTING_BUDGET¶
Purpose: Override the starting cash used for backtests (initial portfolio cash).
Format: Positive number. Accepted examples:
500,5000,5k,1_000_000,$10,000.Notes: - When set, this value is preferred over any
budget=passed in strategy code, so it can be controlled per-run via injected environment variables. - Default (when unset and no code budget is provided):100000.
LUMIBOT_STRATEGY_PARAMETERS¶
Purpose: Override or inject strategy parameters without modifying strategy code. The same parameter contract applies to backtests and live strategy execution.
Format: JSON string representing a dictionary. Example:
{"symbol": "AAPL", "quantity": 10}Notes: - When set, the parsed dict is merged on top of the strategy’s existing
parametersdict with highest priority (wins over both class-level defaults and code-level overrides). - Useful for parameter sweeps and for deploying the exact parameter set validated by a backtest. - Nested dicts are supported (e.g.{"ALLOCATION": {"SPY": 0.50, "IWM": 0.50}}). - Invalid JSON or non-dict values are ignored with a warning. -BACKTESTING_PARAMETERSremains a deprecated compatibility alias for older external runners. If both are present,LUMIBOT_STRATEGY_PARAMETERSwins.
BOTSPOT_DATA_ROUTING_POLICY¶
Purpose: Attach the non-secret version of the routing policy that selected a backtest datasource.
Format: JSON object containing a
versionfield.Notes: LumiBot writes the policy version and the adapters actually observed during the run to
logs/data_provenance.json. Credentials, tokens, and signed URLs are never included.
BACKTESTING_DATA_SOURCE¶
Choose your backtest data¶
This setting selects historical market data for a backtest; it does not choose
your paper/live broker. A provider setting overrides the class in code,
including the datasource_class argument to backtest() or run_backtest().
For daily stock and ETF backtests, select Yahoo in your project’s .env:
BACKTESTING_DATA_SOURCE=yahoo
Or set it in the shell before launching your strategy:
# macOS / Linux
export BACKTESTING_DATA_SOURCE=yahoo
python my_strategy.py
# Windows PowerShell
$env:BACKTESTING_DATA_SOURCE = "yahoo"
python my_strategy.py
Other providers may require credentials or a Data Downloader. See the provider setup guides for asset coverage and requirements.
Configuration |
Result |
|---|---|
Provider name or routing JSON is set |
Uses that selection, even when Python supplies a class. |
Unset; Python supplies a class |
Uses the class from code. |
Unset; Python supplies no class |
Defaults to ThetaData, which requires its own setup. |
|
Uses the class from code; raises an error if no class is supplied. |
To keep an explicit data-source class in your code, use
BACKTESTING_DATA_SOURCE=none. This does not disable data requests or make a
backtest offline.
Unexpected provider? Check the variable in your shell, .env, and
.env.local before launching. An exported value takes precedence over the
primary .env file; .env.local can override both. See
LUMIBOT_DISABLE_DOTENV and LUMIBOT_DISABLE_DOTENV_LOCAL above for loading
controls.
Supported values¶
Values (case-insensitive):
thetadata,yahoo,polygon,alpaca,ccxt,databento,polymarket,polymarket_clobibkr/interactivebrokersrest/interactive_brokers_rest(IBKR Client Portal REST)router(multi-provider routing; defaults to Theta for stock/option/index and IBKR for futures/crypto)JSON mapping (multi-provider routing by asset type), e.g.
{"default":"thetadata","stock":"thetadata","option":"thetadata","index":"thetadata","future":"ibkr","crypto":"ibkr"}Provider values are case/whitespace/_/- insensitive.
Supported values include
thetadata,ibkr,polygon,alpaca,ccxt, andpolymarket.For CCXT backtesting, you may use
ccxt(auto-select exchange from existing env/credentials) or specify a supported CCXT backtesting exchange id directly. Documented backtesting examples arekraken,binance,kucoin,bitmex,bybit, andokx.Routing keys are the canonical asset types (
future,cont_future,crypto, etc.). Common plural aliases likefutures/cont_futuresare accepted.
noneto disable the env override and rely on code.
Testing / CI guardrails¶
LUMIBOT_ACCEPTANCE_TRIPWIRE¶
Purpose: Acceptance backtests only — when truthy, a Python startup hook aborts the subprocess the moment it attempts to call a remote data service.
Values: truthy enables (
1,true,yes); unset/0disables.Notes: - This is an engineering/CI guardrail to enforce “warm-cache” acceptance backtests. It should not be used for normal production backtests. - When triggered, it prints a marker and exits the subprocess with a non-zero code so the test fails reliably.
Live scheduled execution (BotSpot/BotManager)¶
LUMIBOT_SCHEDULED_EXECUTION: internal BotManager flag. Truthy values (1,true,yes,y,on) makeStrategy.run_live()run one live iteration and exit.LUMIBOT_LAZY_CREDENTIALS: defers default broker/data-source credential materialization during live startup when truthy. Defaults to enabled whenLUMIBOT_SCHEDULED_EXECUTIONis truthy.LUMIBOT_CONNECT_STREAM: overrides whether live brokers start their stream during broker construction. Truthy values enable stream startup; any other set value disables it. Defaults to disabled for scheduled execution and enabled otherwise.LUMIBOT_START_ORDERS_THREAD: overrides whether live brokers start their orders thread during broker construction. Truthy values enable the orders thread; any other set value disables it. Defaults to disabled for scheduled execution and enabled otherwise. Queue-based brokers that require the worker to submit orders, such as legacy Interactive Brokers, keep the worker enabled even when this flag is false.LUMIBOT_SCHEDULED_TARGET_RUN_AT: UTC ISO-8601 target time for exact scheduled runs. When present, LumiBot initializes the strategy/broker first, waits locally until this timestamp immediately beforeon_trading_iteration(), and skips the iteration if the drift budget is exceeded.LUMIBOT_SCHEDULED_PRE_START_AT: UTC ISO-8601 pre-start time used by BotManager telemetry to compare scheduler launch timing with the requested target.LUMIBOT_SCHEDULED_TARGET_EVENT: internal lifecycle selector for a scheduled task.closed_market_preparerunson_closed_market_iteration()only while the market is closed and blocks supported broker order submission, cancellation, and modification APIs for that lifecycle.LUMIBOT_SCHEDULED_MAX_TARGET_DRIFT_MS: maximum allowed late drift in milliseconds for exact scheduled runs. Defaults to1000.LUMIBOT_SCHEDULED_POST_ITERATION_SECONDS: drain window after the one live iteration. During this window LumiBot continues processing broker/order queue events before exiting.LUMIBOT_SCHEDULED_TIMING_FILE: local JSON timing file written by LumiBot for BotManager bootstrap telemetry.LUMIBOT_SCHEDULED_STATE_BACKEND: external state backend prepared by BotManager:s3,dynamodb, ornone.nonedisables scheduledself.varsfile load/save.LUMIBOT_SCHEDULED_STATE_FILE: local JSON file managed by BotManager/bootstrap code to restore and persistself.varsfor one scheduled live run. State is restored before scheduled lifecycle hooks.
BotSpot managed research¶
BOTSPOT_RESEARCH_MCP_URL: optional BotSpot Research MCP endpoint.BOTSPOT_RESEARCH_MCP_TOKEN: secret bearer credential. External users supply their own scoped BotSpot key; hosted runtimes receive a short-lived deployment-bound capability.BOTSPOT_API_URL: optional BotSpot API origin used bylumibot connect botspotfor its device login (defaulthttps://api.botspot.trade). Point it at another BotSpot environment for testing.BOTSPOT_RESEARCH_MCP_RENEW_URL: optional HTTPS renewal endpoint. Localhost is permitted for local development; otherwise its origin must match the MCP endpoint.The URL and token enable automatic attachment. The renewal URL is optional for an external static key and required only when the hosted capability needs automatic renewal.
Missing or incomplete configuration preserves ordinary LumiBot strategy and agent behavior and emits one deduplicated capability notice. The “not connected” notice appears at most once per process and never in CI.
LUMIBOT_NO_BOTSPOT_HINT: set to1to hide the “BotSpot research is not connected” notice.DO_NOT_TRACK=1also hides it.LUMIBOT_HIDE_BOTSPOT_TIP: set to1to hide the one-time “BotSpot MCP is not connected” tip that LumiBot logs when a backtest or live run starts without a BotSpot connection. The tip is also hidden in CI, withLUMIBOT_NO_BOTSPOT_HINT=1orDO_NOT_TRACK=1, and whenBOTSPOT_RESEARCH_MCP_TOKEN,BOTSPOT_RESEARCH_MCP_RENEW_URLorBOTSPOT_API_KEYis set.lumibot connect botspotchecks a Research key with BotSpot and writes the URL and token to.env. See The lumibot Command.
GITHUB_TOKEN is used only in tagged release CI with repository actions: read permission to restore compatible agent-eval freshness evidence. The source workflow commit must be an ancestor of the exact tagged candidate. If no trustworthy artifact is available, stale cases run normally. Never log or commit token values.
Backtest artifacts + UX flags¶
SHOW_PLOT / SHOW_INDICATORS / SHOW_TEARSHEET¶
Purpose: Enable/disable artifact generation.
Values:
True/False(string).
LUMIBOT_BACKTEST_PARQUET_MODE¶
Purpose: Control parquet export semantics for backtest artifacts (indicators/trades/stats/trade events).
Values: -
best_effort(default): parquet failures log warnings; CSV remains the compatibility layer. -required: parquet export failures raise and should fail the backtest (artifact contract mode).Notes: - This is primarily intended for BotManager/BotSpot backtests where downstream tools depend on Parquet for performance. - When set to
required, a parquet export error should fail the backtest so missing artifacts are never silently ignored.
BACKTESTING_QUIET_LOGS¶
Purpose: Reduce log noise during backtests.
Values:
true/false(string).
BACKTESTING_SHOW_PROGRESS_BAR¶
Purpose: Enable progress bar updates.
Values:
true/false(string).
Backtest progress file (BotSpot/BotManager UI)¶
LOG_BACKTEST_PROGRESS_TO_FILE¶
Purpose: When truthy, write
logs/progress.csvduring backtests so BotManager/BotSpot can show live progress.Values: truthy enables (
1,true,yes); unset/0disables.Notes: - On startup, LumiBot writes an initial
progress.csvrow immediately to reduce “time-to-first-progress” latency for short backtests. - In BotManager, a background thread watches/app/logs/*progress.csvand uploads the most recent row to DynamoDB.
BACKTESTING_PROGRESS_HEARTBEAT¶
Purpose: Enable periodic
progress.csvupdates while a ThetaData download is active (prevents the UI appearing stuck when simulation datetime is not advancing).Values:
true/false(string).Default: enabled (
true).
BACKTESTING_PROGRESS_HEARTBEAT_SECONDS¶
Purpose: Heartbeat interval (seconds) for writing
progress.csvwhile downloading.Values: float seconds (string).
Default:
2.0
Trade audit telemetry (accuracy investigations)¶
LUMIBOT_BACKTEST_AUDIT¶
Purpose: Emit per-fill audit telemetry into the trade-event CSV as
audit.*columns.Values:
1enables (any truthy value); unset/0disables.Output: - Writes a full trade-event export
*_trade_events.csvwithaudit.*columns (for example, quote bid/ask snapshots, bar OHLC, SMART_LIMIT inputs, and multileg linkage).Notes: - This increases CSV width and can add overhead; keep it enabled only when you need a full audit trail.
Profiling (performance + parity investigations)¶
BACKTESTING_PROFILE¶
Purpose: Enable profiling during backtests to attribute runtime (S3 IO vs compute vs artifacts).
Values: -
yappi(supported)Output: - Produces a
*_profile_yappi.csvartifact alongside other backtest artifacts.
LUMIBOT_CACHE_MISS_DEBUG¶
Purpose: Opt-in diagnostic logging for the IBKR history cache path. Emits
[CACHE_MISS](why a cache miss fired) and[FETCH](including a short Python traceback of the caller) at WARNING level.Values: truthy enables (
1,true); unset/0disables.Default: disabled. Zero runtime cost when unset — the check is gated before any logging work.
When to use: diagnosing unexpected IBKR roundtrips in warm-cache backtests (e.g., when profiling shows time in
_fetch_history_between_datesthat you expected to be cached).
ThetaData option-chain building (performance)¶
THETADATA_CHAIN_DEFAULT_MAX_DAYS_OUT¶
Purpose: Bounds the default option-chain expiration window for equity underlyings to reduce strike-list fanout in cold caches/backtests.
Values: integer days.
Default:
730(2 years).Notes: set to
0to disable the default bound (fetch all expirations).
THETADATA_CHAIN_DEFAULT_MAX_DAYS_OUT_INDEX¶
Purpose: Same as
THETADATA_CHAIN_DEFAULT_MAX_DAYS_OUT, but for index-like underlyings (SPX/NDX/VIX/etc) with dense expiration schedules.Values: integer days.
Default:
180.Notes: set to
0to disable the default bound.
THETADATA_CHAIN_RECENT_FILE_TOLERANCE_DAYS¶
Purpose: Local chain cache file reuse window (equities) when no chain hints are in effect.
Values: integer days.
Default:
7.
THETADATA_CHAIN_STRIKES_TIMEOUT¶
Purpose: Downloader wait timeout per strike-list request when building chains.
Values: seconds (float).
Default:
300.
THETADATA_CHAIN_STRIKES_BATCH_SIZE¶
Purpose: Number of in-flight strike-list requests when building chains.
Values: integer.
Default:
0(use queue client concurrency).
ThetaData corporate action normalization (accuracy)¶
THETADATA_APPLY_CORPORATE_ACTIONS_INTRADAY¶
Purpose: Apply split/dividend adjustments to intraday frames (minute/second/hour) in backtests so intraday prices match daily split-adjusted prices and option-chain strike normalization stays consistent.
Values:
1/trueenable;0/falsedisable.Default: - enabled when
IS_BACKTESTINGis truthy - disabled otherwiseNotes: - Disabling can break options strike selection around splits (example: NVDA 10-for-1 split on 2024-06-10).
Remote cache (S3)¶
LUMIBOT_CACHE_BACKEND / LUMIBOT_CACHE_MODE¶
Purpose: Enable remote cache mirroring (for example, mirroring parquet cache files to S3).
Common values: -
LUMIBOT_CACHE_BACKEND=s3-LUMIBOT_CACHE_MODE=readwrite(orreadonly)
LUMIBOT_CACHE_FOLDER¶
Purpose: Override the local cache folder (useful to simulate a fresh container/task).
LUMIBOT_CACHE_S3_BUCKET / LUMIBOT_CACHE_S3_PREFIX / LUMIBOT_CACHE_S3_REGION¶
Purpose: S3 target configuration.
LUMIBOT_CACHE_S3_VERSION¶
Purpose: Namespace/version the remote cache without deleting anything.
Practical use: set a unique version to simulate a “cold S3” run safely.
LUMIBOT_CACHE_S3_ACCESS_KEY_ID / LUMIBOT_CACHE_S3_SECRET_ACCESS_KEY / LUMIBOT_CACHE_S3_SESSION_TOKEN¶
Purpose: Credentials for S3 access when not using an instance/task role.
Values: provided by your runtime environment (do not hardcode).
For cache key layout and validation workflow, see Backtesting and the engineering notes in docs/remote_cache.md.
Strategy configuration¶
STRATEGY_NAME¶
Purpose: Name for the strategy to be used in database logging and identification.
Values: Any string.
MARKET¶
Purpose: Market to be traded (used for market calendar selection).
Values:
NYSE,NASDAQ,24/7(crypto), etc.
HIDE_TRADES / HIDE_POSITIONS¶
Purpose: Hide trade and position information in logs/output.
Values:
true/false(string).Default:
false.
DISCORD_WEBHOOK_URL¶
Purpose: Discord webhook URL for notifications.
Values: Full Discord webhook URL (do not hardcode in public repos).
Database configuration¶
DB_CONNECTION_STR¶
Purpose: PostgreSQL connection string for account history and strategy persistence.
Values:
postgresql://user:password@host:port/database(do not hardcode).Note: Replaces deprecated
ACCOUNT_HISTORY_DB_CONNECTION_STR.
LOG_BACKTEST_PROGRESS_TO_FILE¶
Purpose: Log backtest progress to a file instead of stdout.
Values:
true/false(string).
Broker selection¶
TRADING_BROKER¶
Purpose: Explicitly specify which broker to use for live trading.
Values (case-insensitive): -
alpaca,tradier,ccxt,coinbase,kraken,weex-ib,interactivebrokers,ibrest,interactivebrokersrest-tradovate,schwab,bitunix,polymarket,polymarket_clob-projectx/projectx-topstepxfor TopstepX futures (via ProjectX) - Any other CCXT exchange ID (for exampleokx,binance,hyperliquid), with credentials in<EXCHANGE>_API_KEY,<EXCHANGE>_API_SECRET,<EXCHANGE>_API_PASSPHRASE,<EXCHANGE>_UID,<EXCHANGE>_PRIVATE_KEY,<EXCHANGE>_WALLET_ADDRESS(only the fields that exchange requires) and optional<EXCHANGE>_SANDBOX/<EXCHANGE>_MARGIN. See the CCXT broker guide.Note: If not set, broker is auto-detected based on available credentials.
DATA_SOURCE¶
Purpose: Explicitly specify which data source to use.
Values (case-insensitive): -
alpaca,tradier,polygon,yahoo,thetadata,databento-ccxt,coinbase,kraken,weex,schwab,bitunix,projectx,polymarket,polymarket_clob- Any other CCXT exchange ID (public market data needs no credentials on most exchanges)Note: If not set, uses broker’s default data source.
Alpaca broker¶
ALPACA_API_KEY / ALPACA_API_SECRET¶
Purpose: Alpaca API credentials for trading.
Values: Obtain from Alpaca dashboard (do not hardcode).
ALPACA_OAUTH_TOKEN¶
Purpose: OAuth token (alternative to API key/secret).
Values: OAuth token (do not hardcode).
Note: Either OAuth token OR API key/secret must be provided, not both.
ALPACA_IS_PAPER¶
Purpose: Toggle between paper and live trading.
Values:
true(paper) /false(live).Default:
true(paper trading).
ALPACA_NEWS_API_KEY / ALPACA_NEWS_API_SECRET¶
Purpose: Optional bring-your-own-key credentials for
BuiltinTools.news.alpaca_news()when the active broker is not Alpaca.Values: Alpaca API credentials with news/data access (do not hardcode).
Note: When the active broker is Alpaca, the built-in news tool reuses that broker’s OAuth token or API key/secret instead. If the active broker is not Alpaca and these news-specific variables are absent, the built-in news tool is not exposed to agents.
Polymarket CLOB broker¶
POLYMARKET_PRIVATE_KEY¶
Purpose: Wallet private key or session signer used to sign Polymarket CLOB orders and derive API credentials.
Values: Provider/wallet secret (do not hardcode).
Note: Required for authenticated CLOB reads and trading. Treat this as a high-risk wallet credential.
POLYMARKET_WALLET_ADDRESS¶
Purpose: Polymarket proxy wallet, deposit wallet, Safe, or other funder address passed to the CLOB client.
Values: Wallet address.
POLYMARKET_OWNER_ADDRESS¶
Purpose: Optional owner/signer address for Magic/proxy accounts. LumiBot uses it as a fallback for Data API position and value reads when it differs from
POLYMARKET_WALLET_ADDRESS.Values: Wallet address.
POLYMARKET_SIGNATURE_TYPE¶
Purpose: Polymarket CLOB signature type used by the authenticated client.
Values:
0for EOA,1for existing Polymarket proxy/Magic wallets,2for Gnosis Safe,3for deposit wallet /POLY_1271.Default:
1whenPOLYMARKET_OWNER_ADDRESSandPOLYMARKET_WALLET_ADDRESSdiffer, otherwise3. Set this explicitly for live testing and Bot Manager deployments.
POLYMARKET_CLOB_API_KEY / POLYMARKET_CLOB_API_SECRET / POLYMARKET_CLOB_API_PASSPHRASE¶
Purpose: Optional derived/generated CLOB API credentials for authenticated order, trade, cancel, and balance requests.
Values: CLOB API credentials (do not hardcode).
Note: If omitted, LumiBot attempts to derive/create credentials in memory through
py-clob-client-v2when a private key is available.
POLYMARKET_API_CREDENTIALS_JSON¶
Purpose: Optional JSON wrapper for CLOB API credentials.
Values: JSON object containing key/secret/passphrase fields (do not hardcode).
Note: Prefer separate env vars for readability unless a secret store provides one JSON payload.
POLYMARKET_RELAYER_API_KEY / POLYMARKET_RELAYER_API_KEY_ADDRESS¶
Purpose: Relayer credentials for wallet deployment/approval flows when required by the Polymarket account setup.
Values: Relayer credential fields (do not hardcode).
Note: Relayer credentials are not the same as CLOB trading credentials. The CLOB client still needs L2 API key, secret, and passphrase fields for private order/balance/trade endpoints and WebSocket user streams.
POLYMARKET_BUILDER_CODE¶
Purpose: Optional Polymarket builder attribution code.
Values: Builder code.
POLYMARKET_AUTO_APPROVE¶
Purpose: When truthy, attempt CLOB collateral approval setup before live trading.
Values: truthy enables (
1,true,yes,on); unset disables.Default: disabled.
POLYMARKET_MAX_MARKET_ORDER_NOTIONAL¶
Purpose: Hard cap for Polymarket market BUY order dollar amount.
Values: Positive decimal.
Default:
5.
POLYMARKET_TEST_TOKEN_ID / POLYMARKET_LIVE_TRADING_ENABLED / POLYMARKET_TEST_MAX_NOTIONAL¶
Purpose: Test-only gates for Polymarket live smoke tests.
Values: Explicit CLOB token id;
POLYMARKET_LIVE_TRADING_ENABLED=trueto allow live submit/cancel tests; decimal max notional.Note: Live tests are skipped unless the required env vars are present. Default live-test max notional is capped at
5.Smoke helpers:
scripts/polymarket_smoke.pyandscripts/polymarket_lumibot_smoke.pyload local.env.localvalues, redact output, and only submit live orders when the live gate and caps are present. The LumiBot smoke helper supports explicit order-matrix cases such asfak-buy,fok-buy,fak-sell,fok-sell,gtc-buy,gtd-buy,post-only-buy,cancel-single,cancel-multiple,cancel-all,cancel-market, and--websocket.
Kalshi connection and trading¶
TRADING_BROKER=kalshiselects the native adapter. Standard order, position, quote, historical-price and account methods are implemented. Whole and fractional demo trading and completed-candle backtesting are verified; live settlement reconciliation and advanced execution fidelity remain separate qualification.KALSHI_API_KEY_IDidentifies the separately configured demo or production key.KALSHI_PRIVATE_KEYsupplies PEM text (Ed25519 or RSA); alternatively useKALSHI_PRIVATE_KEY_PATHfor your own protected PEM file. Inline text wins.KALSHI_IS_DEMOdefaults totrue; usefalsefor a production connection.KALSHI_SUBACCOUNTis optional; absence preserves the key’s provider binding.KALSHI_EXCHANGE_INDEXoptionally scopes the account to a fund pool; market metadata routes trading, and a conflicting configured pool produces an error. The adapter does not transfer funds automatically.KALSHI_BASE_URLoptionally replaces the standard REST endpoint. Configured query parameters are retained, and secrets in endpoint configuration are not logged.DATA_SOURCE=kalshioptionally selects the metadata/price/quote source. With the Kalshi broker it reuses that broker’s client.BACKTESTING_DATA_SOURCE=kalshiselectsKalshiBacktestingthrough the existing backtest source override. Preload selected YES/NO assets withassets=and a minute/hour/daytimestep, or pass ordinarypandas_data. Public market history needs no trading keys; orders in a backtest are simulated.Account-only check:
python -m lumibot.example_strategies.kalshi_account_check. It uses the existing Strategy cash/equity methods and submits no orders.
Polymarket CLOB implementation notes¶
Set
TRADING_BROKER=polymarketfor the normal live broker path.DATA_SOURCE=polymarketis only the optional separate public-market-data override.CLOB collateral balances are returned in 6-decimal raw units by balance/allowance reads. LumiBot scales those values into dollars before returning account cash.
The current international CLOB adapter supports read-only account state, market discovery, token resolution, order books, quotes, last price, supported price history, public market WebSockets, and authenticated user WebSocket subscription. Live submit/cancel is implemented and has been proven through the LumiBot broker with a funded deposit wallet, pUSD approvals, and conditional-token sell approvals. Existing Magic/proxy accounts may still be rejected by Polymarket with a deposit-wallet/API-key binding error until migrated through the supported deposit-wallet flow.
SELL orders need conditional-token approvals from the deposit wallet. The local setup helper can submit these approvals with
scripts/polymarket_deposit_wallet_setup.py --approve-conditional.
Tradier broker¶
TRADIER_ACCESS_TOKEN¶
Purpose: Tradier API access token.
Values: Obtain from Tradier dashboard (do not hardcode).
TRADIER_TOKEN_PATH¶
Purpose: Path to a Tradier OAuth token JSON file.
Values: A local file containing provider token fields such as
access_token,refresh_token,expires_in, andissued_at.Note: When LumiBot refreshes an OAuth token, it writes the updated provider token payload back to this file atomically. If the file cannot be written, refresh fails instead of silently continuing with only in-memory token state.
LUMIBOT_OAUTH_REFRESH_MODE¶
Purpose: Controls who calls the broker OAuth refresh endpoint for Schwab and Tradier token-file integrations.
Values:
auto(default) lets LumiBot refresh the provider OAuth token and write the updated token payload back to the configured token file.externalmeans LumiBot does not call the provider OAuth refresh endpoint; a trusted parent process must atomically replace the configured token file, and LumiBot reloads it before broker requests and after auth failures.Note: Use
externalonly when another trusted process owns refresh-token handling. The token file still needs a valid access token for broker API calls.
TRADIER_ACCOUNT_NUMBER¶
Purpose: Tradier account number for trading.
Values: Your Tradier account number.
TRADIER_IS_PAPER¶
Purpose: Toggle between paper and live trading.
Values:
true(paper) /false(live).Default:
true(paper trading).
Interactive Brokers¶
INTERACTIVE_BROKERS_PORT¶
Purpose: Socket port for IB Gateway/TWS connection.
Values: Integer (e.g.,
7497for paper,7496for live).
INTERACTIVE_BROKERS_CLIENT_ID¶
Purpose: Client ID for IB connection (must be unique per connection).
Values: Integer.
INTERACTIVE_BROKERS_IP¶
Purpose: IP address of IB Gateway/TWS.
Values: IP address string.
Default:
127.0.0.1.
IB_SUBACCOUNT¶
Purpose: Sub-account identifier for IB multi-account setups.
Values: Account identifier string.
Interactive Brokers REST¶
IB_USERNAME / IB_PASSWORD¶
Purpose: Individual Client Portal credentials used only by the local IBeam transport.
Values: Secrets; never log, commit, or hardcode them.
IB_ACCOUNT_ID¶
Purpose: Account ID for IB REST API.
Values: Account identifier string.
IB_API_URL¶
Purpose: Base URL for IB REST API endpoint.
Values: URL string.
IB_GATEWAY_PORT¶
Purpose: Host port for local IBeam or externally managed Client Portal Gateway.
Values: Integer from
1through65535.Default:
4234.
IB_GATEWAY_INSTANCE_ID¶
Purpose: Non-secret identifier used to isolate local IBeam container names.
Values: Letters, numbers,
_,-, and..Default: Random value generated for each gateway instance.
IB_USE_PAPER_ACCOUNT¶
Purpose: Select paper login when LumiBot starts local IBeam.
Values: Boolean string.
Default:
true.
IBEAM_DOCKER_TAG¶
Purpose: Select a versioned local IBeam Docker release.
Values: Docker tag only, not an image/repository reference.
Default:
0.5.12.
IB_AUTH_TIMEOUT / IB_AUTH_POLL_INTERVAL¶
Purpose: Bound gateway authentication and control status polling.
Values: Positive seconds.
Defaults:
300/5.
IB_REQUEST_TIMEOUT¶
Purpose: Timeout for one IBKR REST request.
Values: Positive seconds.
Default:
30.
IB_VERIFY_SSL¶
Purpose: Override TLS certificate verification for IBKR REST requests.
Values: Boolean string.
Default: disabled for localhost gateways; enabled for non-local hosts.
IBKR_HISTORY_SOURCE¶
Purpose: Select which IBKR Client Portal history source to use for OHLC bars in IBKR REST backtests.
Values:
Trades/Midpoint/Bid_Ask(case-insensitive; hyphen/underscore variants accepted).Default:
Trades.
IBKR_FUTURES_EXCHANGE¶
Purpose: Fallback futures exchange for IBKR REST when
exchange=is not provided and automatic exchange routing cannot resolve a unique venue.Values: Exchange code string (for example:
CME,CBOT,COMEX,NYMEX).Default:
CME.
IBKR_CRYPTO_VENUE¶
Purpose: Default IBKR crypto venue when backtesting spot crypto via IBKR REST.
Values: Venue/exchange string (for example:
ZEROHASH).Default:
ZEROHASH.
LUMIBOT_IBKR_ENABLE_FUTURES_BID_ASK¶
Purpose: Opt-in derivation of per-bar futures bid/ask quotes using IBKR
Bid_Ask+Midpointhistory sources.Values:
true/false(or1/0).Default: disabled.
Schwab broker¶
SCHWAB_ACCOUNT_NUMBER¶
Purpose: Schwab account number (required).
Values: Account number string.
SCHWAB_APP_KEY / SCHWAB_APP_SECRET¶
Purpose: Schwab API application credentials.
Values: Obtain from Schwab developer portal (do not hardcode).
SCHWAB_TOKEN¶
Purpose: Optional pre-existing OAuth token.
Values: Token string (do not hardcode).
SCHWAB_BACKEND_CALLBACK_URL¶
Purpose: OAuth callback URL for authentication flow.
Values: URL string.
SCHWAB_CANCEL_DIAGNOSTICS¶
Purpose: Re-enable the post-cancel direct order read used for Schwab cancel incident diagnostics.
Values:
true/false(or1/0).Default: disabled. The diagnostic read doubles the round trips on every cancel; enable it only while investigating a cancel issue.
Tradovate broker¶
TRADOVATE_USERNAME / TRADOVATE_DEDICATED_PASSWORD¶
Purpose: Tradovate credentials.
Values: Tradovate credentials (do not hardcode).
TRADOVATE_APP_ID / TRADOVATE_APP_VERSION¶
Purpose: Application identification for Tradovate API.
Values: String identifiers.
Default:
Lumibot/1.0.
TRADOVATE_CID / TRADOVATE_SECRET¶
Purpose: Client credentials for Tradovate OAuth.
Values: Obtain from Tradovate (do not hardcode).
TRADOVATE_IS_PAPER¶
Purpose: Toggle between paper and live trading.
Values:
true(paper) /false(live).Default:
true.
TRADOVATE_MD_URL¶
Purpose: Market data URL override.
Values: URL string.
Default:
https://md.tradovateapi.com/v1.
Crypto brokers (CCXT)¶
KRAKEN_API_KEY / KRAKEN_API_SECRET¶
Purpose: Kraken exchange API credentials.
Values: Obtain from Kraken (do not hardcode).
COINBASE_API_KEY_NAME / COINBASE_PRIVATE_KEY¶
Purpose: Coinbase Advanced Trade API credentials.
Values: Obtain from Coinbase (do not hardcode).
COINBASE_API_PASSPHRASE¶
Purpose: API passphrase (if required by Coinbase).
Values: Passphrase string (do not hardcode).
COINBASE_SANDBOX¶
Purpose: Use Coinbase sandbox environment.
Values:
true/false.Default:
false.
LUMIBOT_CCXT_PARTNER_IDS¶
Purpose: LumiBot’s own exchange partner (broker) IDs for CCXT exchanges. CCXT’s own partner IDs are always removed; these are attached instead. A partner ID does not change what the user pays.
Values: JSON object keyed by CCXT exchange id, for example
{"bybit": "<partner-id>", "kucoin": {"id": "<id>", "key": "<partner-key>"}}.Default: empty (no partner ID is attached).
LUMIBOT_CCXT_BUILDER_FEES¶
Purpose: An extra builder fee on DEXes that support one (Hyperliquid, Lighter, GRVT, Aster, Pacifica, Extended). This costs the user extra on every order. LumiBot logs a warning whenever one is enabled.
Values: JSON object of CCXT option overrides per exchange, for example
{"hyperliquid": {"builder": "0x...", "feeRate": "0.01%", "feeInt": 10}}.Default: empty. CCXT’s own builder fees are turned off.
LUMIBOT_CCXT_REFERRAL_CODES¶
Purpose: Referral code to register when a wallet first connects (Hyperliquid).
Values: JSON object, for example
{"hyperliquid": "<code>"}.Default: empty. CCXT’s own referrer registration is skipped.
PARADEX_L2_PRIVATE_KEY / PARADEX_L2_ADDRESS / PARADEX_L2_PUBLIC_KEY¶
Purpose: Trade Paradex with a subkey (can trade, cannot withdraw) instead of the wallet’s private key.
PARADEX_L2_ADDRESSis the Paradex account address.Values: from Paradex Key Management (do not hardcode).
LIGHTER_API_KEY_PRIVATE_KEY / LIGHTER_API_KEY_INDEX / LIGHTER_ACCOUNT_INDEX / LIGHTER_LIBRARY_PATH¶
Purpose: Trade Lighter with an existing API key instead of the wallet’s private key. All four are needed; the library path points to Lighter’s signer library.
Values: Lighter API key details (do not hardcode the private key).
DYDX_MNEMONIC¶
Purpose: Use the dYdX Chain secret phrase instead of the Ethereum wallet key. It still has full control of the dYdX account.
Values: secret phrase (do not hardcode).
Bitunix broker¶
BITUNIX_API_KEY / BITUNIX_API_SECRET¶
Purpose: Bitunix exchange API credentials.
Values: Obtain from Bitunix (do not hardcode).
BITUNIX_TRADING_MODE¶
Purpose: Trading mode selection.
Values:
FUTURES/SPOT.Default:
FUTURES.
ProjectX brokers¶
ProjectX support is primarily documented for TopstepX futures. The lower-level adapter can read firm-specific ProjectX environment variable prefixes, but new firms should be tested before being treated as production-ready.
PROJECTX_FIRM¶
Purpose: Select which ProjectX firm to use.
Values:
TOPSTEPXfor the documented TopstepX path. Additional ProjectX firm ids may exist in the adapter, but require validation before use.
PROJECTX_{FIRM}_API_KEY¶
Purpose: API key for the specified firm.
Example:
PROJECTX_TOPSTEPX_API_KEY,PROJECTX_TOPONE_API_KEYValues: Obtain from firm’s platform (do not hardcode).
PROJECTX_{FIRM}_USERNAME¶
Purpose: Username for the specified firm.
Example:
PROJECTX_TOPSTEPX_USERNAMEValues: Your username on the firm’s platform.
PROJECTX_{FIRM}_PREFERRED_ACCOUNT_NAME¶
Purpose: Preferred account name when multiple accounts exist.
Example:
PROJECTX_TOPSTEPX_PREFERRED_ACCOUNT_NAMEValues: Account name string.
Data source credentials¶
POLYGON_API_KEY¶
Purpose: Polygon.io API key for market data.
Values: Obtain from Polygon.io (do not hardcode).
POLYGON_MAX_MEMORY_BYTES¶
Purpose: Hard limit on memory Polygon can use for caching.
Values: Integer (bytes).
LUMIBOT_OPTION_CHAIN_MAX_DAYS¶
Purpose: Polygon backtests only. Limits each option chain request to expirations from the simulated date through that many days ahead, which keeps a free Polygon key under its rate limit. A limited chain is cached under its own name (
<SYMBOL>_<date>_max<N>d.parquet) and is only reused on the same day with the same limit, never as a full chain.Values: Positive whole number of days (for example
21). Unset means no limit. Invalid values are ignored with a warning.Example:
LUMIBOT_OPTION_CHAIN_MAX_DAYS=21
THETADATA_USERNAME / THETADATA_PASSWORD¶
Purpose: ThetaData API credentials.
Values: Obtain from ThetaData (do not hardcode).
Note: Required for ThetaData backtesting and live data.
THETADATA_BASE_URL¶
Purpose: Base URL for the local ThetaTerminal REST API.
Default:
http://127.0.0.1:25503Values: URL string.
Note: You typically do not need to set this; LumiBot auto-manages a local ThetaTerminal for ThetaData usage.
DATABENTO_API_KEY¶
Purpose: DataBento API key for market data.
Values: Obtain from DataBento (do not hardcode).
DATABENTO_TIMEOUT¶
Purpose: Request timeout for DataBento API calls.
Values: Integer (seconds).
Default:
30.
DATABENTO_MAX_RETRIES¶
Purpose: Maximum retry attempts for failed DataBento requests.
Values: Integer.
Default:
3.
LUMIWEALTH_API_KEY¶
Purpose: LumiWealth platform API key (for enterprise features).
Values: Obtain from LumiWealth (do not hardcode).
LISTENER_WRITE_URL¶
Purpose: Portfolio-listener write endpoint used by live cloud account updates.
Values: HTTPS URL supplied by the deployment environment.
Default:
https://listener.lumiwealth.com/portfolio_events.Note: Custom or isolated deployments can set this explicitly to keep account observations separate from the default listener.
Runtime telemetry (memory/health)¶
LUMIBOT_TELEMETRY¶
Purpose: Enable/disable runtime telemetry emission (single-line JSON to stdout prefixed with
LUMIBOT_TELEMETRY).Values: truthy enables (
1,true,yes); falsy disables (0,false).Default: enabled for live runs; disabled for backtests and pytest.
LUMIBOT_TELEMETRY_INTERVAL_SECONDS¶
Purpose: Base telemetry cadence.
Values: seconds (float).
Default:
300.
LUMIBOT_TELEMETRY_DEEP¶
Purpose: Enable deep snapshot mode for diagnosing unknown memory sources.
Values: truthy enables; falsy disables.
Default: disabled.
Notes:
Burst mode (more frequent telemetry logs) turns on automatically above ~80% of container memory.
Deep snapshots trigger above ~90% with a ~1 hour cooldown (these thresholds are fixed defaults today).
AI agent model providers¶
LumiBot’s AI agent subsystem (self.agents.create(model=...) or default_model=...) supports multiple LLM providers. You only need the key matching the provider id you pass for each agent. Non-Gemini ids are routed through LiteLLM, which ships as a LumiBot dependency. In BotSpot managed runtimes, an owner-bound managed AI capability may be supplied when no provider key is present. A user-provided key always takes precedence and provider errors never fall back to managed credits.
LUMIBOT_AI_GATEWAY_URL and LUMIBOT_AI_GATEWAY_TOKEN¶
Purpose: BotSpot-managed model access for a specific deployment or backtest.
These values are issued and renewed by BotSpot. Users should not create or save them manually.
The token is short-lived and deployment-bound. LumiBot renews it through the gateway so always-on bots can continue without receiving a long-lived provider credential.
Supported managed providers are Gemini, OpenAI, Anthropic, and xAI. Other providers continue to require their normal provider key.
Any configured provider key below takes precedence for that provider.
GEMINI_API_KEY¶
Purpose: Auth for Gemini models.
Values: Obtain from https://aistudio.google.com/apikey.
Required when
default_modelstarts withgemini-(e.g.gemini-3.1-flash-lite-preview).LumiBot’s public contract is
GEMINI_API_KEY. Do not rely on Google SDK alias names in strategy examples or downstream products that infer required runtime secrets.
OPENAI_API_KEY¶
Purpose: Auth for OpenAI models, including the default
openai/gpt-6-luna.Values: Obtain from https://platform.openai.com/api-keys.
Required for the default model and whenever
default_modelis any otheropenai/...id.
XAI_API_KEY or GROK_API_KEY¶
Purpose: Auth for xAI Grok models.
Values: Obtain from https://console.x.ai/.
Required when
default_modellooks likexai/grok-4.20-0309-reasoningor any otherxai/...id.XAI_API_KEYis the canonical provider env var;GROK_API_KEYis also accepted for user-facing Grok naming.
ANTHROPIC_API_KEY¶
Purpose: Auth for Anthropic Claude models.
Values: Obtain from https://console.anthropic.com/.
Required when
default_modellooks likeanthropic/claude-opus-4-7or any otheranthropic/...id.
Other providers (Groq, Mistral, Cohere, Fireworks, Together, etc.) use the provider-prefixed id format and the corresponding provider env var; see the LiteLLM documentation for the full list.
SEC fundamentals and agent memory¶
LUMIBOT_SEC_USER_AGENT¶
Purpose: Contact-style SEC EDGAR user agent header.
Values: Human-readable app/contact string.
Default: LumiBot support contact.
LUMIBOT_SEC_CACHE_DIR¶
Purpose: Override local SEC fundamentals and filing cache.
Default:
~/.lumibot/cache/sec.
FRED_API_KEY¶
Purpose: Required official FRED/ALFRED API key for macro data tools.
Default: unset.
Notes: When set, LumiBot requests vintage observations with
realtime_startandrealtime_endfor point-in-time backtests. Built-in FRED agent tools are not exposed during backtests without this key because LumiBot does not use revised public CSV fallbacks for macro data.
LUMIBOT_FRED_CACHE_DIR¶
Purpose: Override local FRED macro data cache.
Default:
~/.lumibot/cache/fred.
LUMIBOT_MEMORY_DIR¶
Purpose: Override local SQLite agent memory root.
Default:
.lumibot/memoryunder the current working directory.
LUMIBOT_MEMORY_EXPORT_PARQUET¶
Purpose: Enable or disable best-effort Parquet exports for agent memory events, retrievals, and current state.
Default:
1.Notes: SQLite is still the live memory store. Parquet exports are derived artifacts for DuckDB queries, BotSpot uploads, and post-run inspection.
LUMIBOT_AGENT_MEMORY_NOTE_MAX_CHARS¶
Purpose: Limit how much prior agent-run memory is injected back into the next agent prompt.
Default:
2000.Notes: Full run traces and artifacts are still written separately. This only compacts the lightweight runtime notes so repeated backtest iterations do not blow up the model context window.
LUMIBOT_AGENT_MAX_MODEL_CALLS¶
Purpose: Hard cap uncached agent model calls in a single strategy run.
Default: unset.
Notes: When set, LumiBot raises before making the next provider call once the cap is reached. Use this for expensive AI backtests and smoke runs where accidental spend matters.
LUMIBOT_AGENT_MAX_RUN_ATTEMPTS¶
Purpose: Override the retry budget for a single agent model call.
Default:
2in backtests,10in live trading.Notes: Backtests default to a lower retry budget so a bad provider window does not multiply model spend across many simulated iterations.
Telegram notifications¶
TELEGRAM_BOT_TOKEN¶
Purpose: Telegram Bot API token for
self.notifications.configure_telegram().Values: Bot token from BotFather.
TELEGRAM_CHAT_ID¶
Purpose: Telegram chat/channel/user id for strategy notifications.
Values: Telegram chat id.
Frequently asked questions¶
Where do I put LumiBot environment variables?¶
You can export them in your shell before you start your strategy, or put them
in a .env file. LumiBot looks upward from the folder of the script you run
for the nearest .env file. If it finds none there, it also looks upward
from your current working directory.
If a .env file is found, LumiBot also loads a .env.local file next to
it. Use .env.local only for your own local overrides.
Which value wins: my shell, .env, or .env.local?¶
A value you export in your shell wins over the primary .env file. A
.env.local file can override both. If a backtest picks a provider you did
not expect, check all three places before you launch.
How do I stop LumiBot from loading my .env file?¶
Set LUMIBOT_DISABLE_DOTENV=1 to turn off .env loading. To keep .env
but skip .env.local, set LUMIBOT_DISABLE_DOTENV_LOCAL=1. In hosted or
deployed runs, injected variables plus LUMIBOT_DISABLE_DOTENV=1 keep local
files from overriding runtime secrets.
How do I choose the backtest data source with an environment variable?¶
Set BACKTESTING_DATA_SOURCE, for example BACKTESTING_DATA_SOURCE=yahoo.
This value overrides the data source class in your Python code. Set it to
none if you want LumiBot to use the class from your code instead. See
BACKTESTING_DATA_SOURCE for every supported value.
How do I set the starting cash for a backtest?¶
Set BACKTESTING_BUDGET, for example BACKTESTING_BUDGET=10000. It wins
over a budget= value in your code. If you set neither one, a backtest starts
with 100000.
Which API key do I need for AI agents?¶
It depends on the model. The default model openai/gpt-6-luna needs
OPENAI_API_KEY. Gemini models need GEMINI_API_KEY, Anthropic models
need ANTHROPIC_API_KEY, and xAI Grok models need XAI_API_KEY (or
GROK_API_KEY). You only need a model key if your strategy uses AI agents.
Does LumiBot read EDGAR_USER_AGENT or SEC_EDGAR_USER_AGENT?¶
No. LumiBot reads LUMIBOT_SEC_USER_AGENT for SEC EDGAR requests. If it is
not set, LumiBot sends its own support contact as the user agent. The SEC asks
automated tools to declare a user agent in request headers. See the SEC page on
accessing EDGAR data.
How do I send strategy alerts to Discord or Telegram?¶
For Discord, set DISCORD_WEBHOOK_URL to your full Discord webhook URL. For
Telegram, set TELEGRAM_BOT_TOKEN to the token from BotFather and
TELEGRAM_CHAT_ID to the chat that should get the messages.
Is it safe to keep API keys in a .env file?¶
Keep keys in a .env file, your shell, or a secret manager, and never commit
them to a repository. Do not commit .env.local either. If a key was ever
pushed to a repository, GitHub’s guide says the first step is to revoke or
rotate that secret. See
Removing sensitive data from a repository.
MetaMask Agent Wallet (native Python beta)¶
Set TRADING_BROKER=metamask and optionally DATA_SOURCE=metamask.
See MetaMask for native setup and qualification limits.
METAMASK_SESSION_FILE: explicit private native OAuth session file.METAMASK_STATE_FILE: durable local wallet journal, preserving prior history.METAMASK_AGENT_ID: exact owner-reviewed agent binding ID.METAMASK_PROJECT_ID: expected provider project; required with inline tokens.METAMASK_ACCESS_TOKEN: optional provider access token instead of a session.METAMASK_REFRESH_TOKEN: optional refresh credential; rotation requires a durable session file.METAMASK_WALLET_ADDRESS: exact expected dedicated managed wallet address.METAMASK_NETWORK: explicittestnetormainnet; no default fallback.METAMASK_MODE:perpby default orspotfor exact-input swaps.
METAMASK_BROKER_URL and METAMASK_BROKER_TOKEN are retired. The old
agent-scoped service token is not a provider access token. Constructor settings
CHAIN_RPC_URLS, GAS_LIMITS and explicit legacy-session migration are
covered in the broker guide. Keep credentials in your own secret manager.