Migration Guide: v3.x to v4.0¶
v4.0 is a major release for the TopstepX-only ProjectX Gateway. It removes long-deprecated surfaces, aligns HTTP and WebSocket clients with the current Gateway, and ships the order and realtime fixes that accumulated while the SDK was unmaintained.
What actually shipped¶
- Tolerant
Order.from_api(),Position.from_api(), andTrade.from_api() - Native Gateway brackets (
stopLossBracket/takeProfitBracket) OrderSubmissionUncertainErrorwhen an HTTP cancel is interrupted- REST
/Trade/searchand/Order/searchwith official timestamps - pysignalr instead of signalrcore
- Stale-feed watchdog (
EventType.FEED_STALE) and REST price fallback - Diagonal Polars concat so live bars can append onto wider historical frames
TradingSuite.export_stats()(json, prometheus, csv, datadog)projectx-check/projectx-configCLI entry points- Official TopstepX URLs:
https://api.topstepx.comandhttps://rtc.topstepx.com
Breaking changes¶
| v3.x | v4.0 |
|---|---|
suite.get_stats_sync() |
await suite.get_stats() or await suite.export_stats() |
get_positions() deprecation warning |
get_positions() is a documented alias of search_open_positions() |
suite.data / suite.orders deprecation warnings |
Official single-instrument accessors. Multi-instrument still uses suite["MNQ"] |
| signalrcore + websocket-client | pysignalr (websockets) |
| uvloop installed at import | Optional extra: pip install project-x-py[uvloop] |
Auth TypedDict field jwt |
Gateway field is token |
Instrument search TypedDict instruments |
Gateway field is contracts |
User-Agent ProjectX-Python-SDK/2.0.0 |
ProjectX-Python-SDK/4.0.0 |
Placeholder suite.journal / suite.analytics |
Removed. Features.TRADE_JOURNAL and Features.AUTO_RECONNECT warn and have no effect |
OrderTracker and create_orderbook() remain available. Prefer
TradingSuite.track_order() / TradingSuite.create(..., features=["orderbook"]).
Authentication and URLs¶
ProjectX is Topstep-exclusive. Defaults are:
api_url = "https://api.topstepx.com/api"
user_hub_url = "https://rtc.topstepx.com/hubs/user"
market_hub_url = "https://rtc.topstepx.com/hubs/market"
realtime_url is a legacy config field and is not used for hub connections.
Credentials still come from PROJECT_X_API_KEY and PROJECT_X_USERNAME, or
from TradingSuite.create(username=..., api_key=...).
Orders¶
Prefer native Gateway brackets when placing an entry:
await suite.orders.place_order(
contract_id=contract_id,
side=0,
size=1,
order_type=1,
limit_price=21000.0,
stop_loss_bracket={"ticks": 16, "type": 4},
take_profit_bracket={"ticks": 32, "type": 1},
)
If the Gateway rejects native brackets, the SDK still falls back to the
client-side OCO path. Fill detection now reconciles through /Order/search
and trades instead of treating “not in open orders” as unfilled.
If a place/cancel HTTP call is cancelled, times out, or gets a 5xx after the
request may have been sent, the SDK raises OrderSubmissionUncertainError
and does not retry. Reconcile with get_order_by_id() before retrying.
Realtime¶
The SignalR client is now pysignalr. HubConnectionBuilder is still the
public construction API used by tests and extensions.
connect()captures the running event loop before hub setupGatewayLogoutis handled on both hubs- Market silence longer than
stale_feed_seconds(default 30s) emitsEventType.FEED_STALEand forces a health reconnect get_current_price()falls back to REST bars when ticks are stale
Statistics¶
get_stats_sync() is gone. Do not call sync wrappers from an async context.
Dependencies removed from the default extra¶
requests(HTTP is httpx)plotlymsgpack-pythonsignalrcore/websocket-clientuvloop(install[uvloop]if you want it; the SDK will not install it as an import-time side effect)
Upgrade checklist¶
- Upgrade:
pip install -U project-x-pyoruv add project-x-py==4.0.0 - Replace
get_stats_sync()withawait get_stats() - Confirm env vars still point at TopstepX (
api.topstepx.com/rtc.topstepx.com) - Catch
OrderSubmissionUncertainErroraround place/cancel - Subscribe to
EventType.FEED_STALEif you need stale-feed alerts - Drop any code that imported
signalrcorethrough this package