ProjectX / TopstepX¶
Lumibot’s ProjectX path is a futures-only broker integration currently documented for TopstepX. The lower-level adapter contains firm-specific ProjectX environment-variable prefixes, but new firms should be treated as advanced and validation-required until they are tested in Lumibot.
What BotSpot MCP adds
Use Claude, ChatGPT, Codex, Cursor, VS Code or another MCP-compatible assistant? Connect the free BotSpot MCP for:
Skills: build LumiBot strategies.
Free data: news, economics and SEC filings.
Backtests: run tests and read charts.
Cloud hosting: low-cost scheduled bots.
Community: share bots and discuss trades.
Marketplace: discover and publish strategies.
Broker linking: connect accounts through BotSpot.
Features¶
TopstepX-first futures trading: Continuous futures contracts through the documented TopstepX path
ProjectX adapter hooks: Additional firm-specific prefixes may exist in the adapter, but they are not advertised as ready until validated
Real-time Data: Live order and position updates
Order Types: Market, limit, stop orders
Auto-Detection: Automatically connects when environment variables are set
Prerequisites¶
Account: Demo or live futures trading account with TopstepX
API Credentials: Username and API key from your broker
Authenticated streaming requires signalrcore>=1.0.2,<2, installed with
LumiBot. Source checkouts must install requirements.txt as well. If the SDK
is absent, streaming raises an ImportError rather than reporting a connection.
Documented Broker¶
TopstepX¶
PROJECTX_TOPSTEPX_API_KEY=your_api_key
PROJECTX_TOPSTEPX_USERNAME=your_username
PROJECTX_TOPSTEPX_PREFERRED_ACCOUNT_NAME=your_account_name
Advanced Adapter Prefixes¶
The adapter can read other PROJECTX_<FIRM>_* prefixes for testing or future expansion, but those paths are not presented as supported broker docs here. Validate fills, positions, account selection, market data, and order error handling before using any non-TopstepX ProjectX firm in production.
Supported Functionality¶
Feature |
Support |
Notes |
|---|---|---|
Futures trading |
Yes |
Supports CME micro and standard contracts through the documented TopstepX ProjectX path. |
Order types |
Market, Limit, Stop |
Submit bracket-style risk controls directly from strategies. |
Market data |
Real time |
Streams price updates when ProjectX is running alongside Lumibot. |
Account detection |
Automatic |
Reads the configured environment variables to pick the correct broker. |
Usage¶
Set Environment Variables: Configure your broker’s API credentials.
Create Strategy: Import Lumibot and create your trading strategy.
Run: ProjectX will auto-detect and connect.
from lumibot.strategies import Strategy
from lumibot.entities import Asset
class MyStrategy(Strategy):
def initialize(self):
self.sleeptime = "1D"
def on_trading_iteration(self):
# Trade Micro E-mini S&P 500 futures
mes = Asset("MES", asset_type=Asset.AssetType.CONT_FUTURE)
# Get current price
last_price = self.get_last_price(mes)
# Place a limit order
if last_price:
order = self.create_order(
asset=mes,
quantity=1,
side="buy",
order_type="limit",
limit_price=last_price * 0.999
)
self.submit_order(order)
# Run the strategy (ProjectX auto-detects from environment variables)
strategy = MyStrategy()
strategy.run_live()
Supported Features¶
✅ Futures Trading: Continuous futures contracts ✅ Market Orders: Immediate execution ✅ Limit Orders: Execute at specified price ✅ Stop Orders: Stop-loss functionality ✅ Real-time Data: Live market data ✅ Historical Data: Minute, hour, day timeframes
❌ Stock Trading: Futures only ❌ Options Trading: Futures only ❌ Order Modification: Must cancel and re-place
Frequently asked questions¶
What is ProjectX?¶
ProjectX is a futures trading platform that prop firms and evaluation providers use to run trader accounts. TopstepX runs on it. The ProjectX Gateway API documentation describes the REST API that LumiBot talks to.
Does LumiBot work with TopstepX?¶
Yes. TopstepX is the documented ProjectX path in LumiBot. Set PROJECTX_TOPSTEPX_API_KEY, PROJECTX_TOPSTEPX_USERNAME and PROJECTX_TOPSTEPX_PREFERRED_ACCOUNT_NAME, then run your strategy. LumiBot finds the ProjectX settings on its own.
Where do I get a ProjectX API key?¶
Your broker gives you the API key and username. For TopstepX, get them from your TopstepX account, then put the key in PROJECTX_TOPSTEPX_API_KEY and the username in PROJECTX_TOPSTEPX_USERNAME.
Which account does LumiBot trade if I have more than one?¶
LumiBot uses the account named in PROJECTX_TOPSTEPX_PREFERRED_ACCOUNT_NAME. If that configured name does not match an account, selection fails visibly and no other account is chosen. When no name is configured, LumiBot selects the account with the highest balance. Set the name explicitly when the login can access multiple accounts.
Can I use other prop firms that run on ProjectX?¶
The adapter can read other PROJECTX_<FIRM>_* settings, and PROJECTX_FIRM picks the firm. Only TopstepX is documented here. Treat any other firm as a test: check fills, positions, account choice, market data and order errors with small orders before you rely on it.
Which order types does the ProjectX integration support?¶
Market, limit and stop orders. LumiBot rounds your prices to the contract tick size before it sends the order.
Can I trade stocks or options through ProjectX?¶
No. The ProjectX integration is for futures only, such as CME micro and standard contracts. Use a continuous futures asset, for example Asset("MES", asset_type=Asset.AssetType.CONT_FUTURE).
Can ProjectX supply market data while another broker places trades?¶
Yes. Set DATA_SOURCE=projectx to use ProjectX prices with a different trading broker. The Tradovate guide shows this setup, because Tradovate does not supply market data to LumiBot.
Data and backtesting¶
get_quote returns the provider’s actual bid, ask and source timestamp. If
only historical trades are available, bid and ask remain unavailable. A stream
connection alone does not mean a quote is fresh; inspect its source time.
Use ProjectXBacktesting with an account’s existing history entitlement:
from datetime import datetime
from lumibot.backtesting import ProjectXBacktesting
from lumibot.entities import Asset
# Set the usual PROJECTX_<FIRM> credentials in your environment.
MyStrategy.run_backtest(
ProjectXBacktesting,
datetime(2026, 10, 26),
datetime(2026, 10, 30),
assets=[Asset("MES", asset_type="cont_future")],
benchmark_asset=None,
)
The equivalent environment selection is BACKTESTING_DATA_SOURCE=projectx.
The normal backtest engine simulates fills from actual trade bars; historical
spreads, queue position and execution certainty are not supplied by those bars.
Configure trading fees and slippage for the intended account. Data coverage and
historical contract availability are limited by the provider entitlement.
Continuous futures resolve the provider’s current active contract and its available history. They are not a point-in-time reconstructed continuous roll series. A dated futures asset selects its requested expiration; a missing expiration match never silently selects another contract.
Execution and recovery¶
Always set PROJECTX_<FIRM>_PREFERRED_ACCOUNT_NAME when the login can access
multiple accounts. An explicitly configured missing account fails visibly.
Futures quantities must be positive whole contracts. Price multipliers come
from the provider’s tick value divided by tick size.
A request handed to transport stays actively tracked as SUBMITTED when its
acceptance is unknown. This means sent, not accepted or filled. Inspect
order.submission_outcome and reconcile the exact original tag before any
replacement. Within a running broker, repeating the same local identity never
posts another request; changed terms under that identity fail visibly. A new tag is a distinct intent,
so duplicate prevention does not authorize creating a fresh tag after a timeout.
Concurrent callers preparing the same order object share one preparation owner. Other callers receive the original object with unknown certainty until that owner resolves preparation and handoff. A failed preflight confirms rejection without sending an order and releases preparation ownership.
A matching venue receipt updates the original object, preserving its bracket instructions and execution history. Conflicting account, instrument, side or receipt identity stays unresolved. An explicitly unresolved order restored into a fresh broker refuses resubmission; this does not reconstruct its local reservation after restart. Inspect actual venue orders and positions.
Bracket exits with absolute target/stop prices remain synthetic. During a running strategy, LumiBot sizes protection from cumulative entry executions minus observed protective executions. Partial exits retain their own filled quantity when their remaining quantity changes. Later entry fills can receive fresh protective orders after the previous accepted exits are confirmed terminal; filled or canceled order identifiers are never reopened.
A cancellation response acknowledges the request; it does not by itself prove that the order is canceled. Failed cancellations remain pending reconciliation. Explicitly canceling an exit does not authorize LumiBot to re-arm that exit. Canceling all working orders does not create replacement protection.
Restart recovery links accepted exit generations by their persisted tags and retains their execution history. Missing history, an unknown submission result or unknown strategy intent holds new protective submissions and resizes. Cold restart recovery does not infer permission to recreate canceled protection. Known sibling cancellation after a proven exit remains available. Review actual positions and working orders before continuing: later entry fills may remain unprotected while recovery is held.
Sibling cancellation requires the client to be running; these are not atomic server-side OCO orders. A restart cannot reconstruct a protection instruction that never reached the provider.