Client API
The main ProjectX client provides access to market data, account information, and core trading functionality.
ProjectX Client
V3 Async ProjectX Python SDK - Core Async Client Module
Author: @TexasCoding Date: 2025-08-02
This module contains the async version of the ProjectX client class for the ProjectX Python SDK. It provides a comprehensive asynchronous interface for interacting with the ProjectX Trading Platform Gateway API, enabling developers to build high-performance trading applications.
The async client handles authentication, account management, market data retrieval, and basic trading operations using async/await patterns for improved performance and concurrency.
Key Features: - Async multi-account authentication and management - Concurrent API operations with httpx - Async historical market data retrieval with caching - Non-blocking position tracking and trade history - Async error handling and connection management - HTTP/2 support for improved performance
For advanced trading operations, use the specialized managers: - OrderManager: Complete order lifecycle management - PositionManager: Portfolio analytics and risk management - ProjectXRealtimeDataManager: Real-time multi-timeframe OHLCV data - OrderBook: Level 2 market depth and microstructure analysis
- class ProjectX(username, api_key, config=None, account_name=None)[source]
Bases:
ProjectXBaseAsync core ProjectX client for the ProjectX Python SDK.
This class provides the async foundation for building trading applications by offering comprehensive asynchronous access to the ProjectX Trading Platform Gateway API. It handles core functionality including:
Multi-account authentication and JWT token management
Async instrument search and contract selection with caching
High-performance historical market data retrieval
Non-blocking position and trade history access
Automatic retry logic and connection pooling
Rate limiting and error handling
The async client is designed for high-performance applications requiring concurrent operations, real-time data processing, or integration with async frameworks like FastAPI, aiohttp, or Discord.py.
For order management and real-time data, use the specialized async managers from the project_x_py.async_api module which integrate seamlessly with this client.
Example
>>> # V3: Basic async SDK usage with environment variables (recommended) >>> import asyncio >>> from project_x_py import ProjectX >>> >>> async def main(): >>> # V3: Create and authenticate client with context manager >>> async with ProjectX.from_env() as client: >>> await client.authenticate() >>> >>> # V3: Get account info with typed models >>> account = client.account_info # After authentication >>> print(f"Account: {account.name}") >>> print(f"ID: {account.id}") >>> print(f"Balance: ${account.balance:,.2f}") >>> >>> # V3: Search for instruments with smart contract selection >>> instruments = await client.search_instruments("MNQ") >>> mnq = instruments[0] if instruments else None >>> if mnq: >>> print(f"Found: {mnq.name} ({mnq.symbol})") >>> print(f"Contract ID: {mnq.id}") >>> >>> # V3: Get historical data concurrently (returns Polars DataFrames) >>> tasks = [ >>> client.get_bars("MNQ", days=5, interval=5), # 5-min bars >>> client.get_bars("ES", days=1, interval=1), # 1-min bars >>> ] >>> nasdaq_data, sp500_data = await asyncio.gather(*tasks) >>> >>> print(f"Nasdaq bars: {len(nasdaq_data)} (Polars DataFrame)") >>> print(f"S&P 500 bars: {len(sp500_data)} (Polars DataFrame)") >>> print(f"Columns: {nasdaq_data.columns}") >>> >>> asyncio.run(main())
- For advanced async trading applications, use the TradingSuite:
>>> # V3: Advanced trading with the TradingSuite >>> import asyncio >>> from project_x_py import TradingSuite >>> >>> async def trading_app(): >>> # The TradingSuite simplifies setup and integrates all managers >>> suite = await TradingSuite.create( ... "MNQ", ... timeframes=["1min", "5min"], ... features=["orderbook", "risk_manager"] ... ) >>> >>> # Client is authenticated and real-time data is streaming. >>> >>> # Access integrated managers easily >>> order = await suite.orders.place_market_order( ... contract_id=suite.instrument_id, ... side=0, # Buy ... size=1 ... ) >>> >>> position = await suite.positions.get_position("MNQ") >>> bars = await suite.data.get_data("1min") >>> >>> print(f"Placed order {order.id}, current position: {position.netPos}") >>> print(f"Latest 1-min bar: {bars.tail(1)}") >>> >>> asyncio.run(trading_app())
- class ProjectXBase(username, api_key, config=None, account_name=None)[source]
Bases:
AuthenticationMixin,HttpMixin,CacheMixin,MarketDataMixin,TradingMixinBase class combining all ProjectX client functionality.
- async __aenter__()[source]
Async context manager entry.
- Return type:
ProjectXBase
- __init__(username, api_key, config=None, account_name=None)[source]
Initialize async ProjectX client for building trading applications.
- classmethod from_config_file(cls, config_file, account_name=None)[source]
Create async ProjectX client using a configuration file.
Alternative initialization method that loads configuration and credentials from a JSON file instead of environment variables. Useful for managing multiple configurations or environments.
- Parameters:
config_file (str) – Path to JSON configuration file containing: - username: ProjectX account username - api_key: API authentication key - api_url: API endpoint URL (optional) - websocket_url: WebSocket URL (optional) - timezone: Preferred timezone (optional)
account_name (str | None) – Optional account name to select when multiple accounts are available. Overrides any account name specified in the config file.
- Yields:
ProjectX – Configured client instance ready for trading operations
- Raises:
FileNotFoundError – If config file doesn’t exist
json.JSONDecodeError – If config file is invalid JSON
ValueError – If required fields are missing from config
ProjectXAuthenticationError – If authentication fails
- Return type:
AsyncGenerator[ProjectXBase,None]
Example
>>> # V3: Create config file >>> import json >>> config = { ... "username": "your_username", ... "api_key": "your_api_key", ... "api_url": "https://gateway.topstepx.com/api", ... "websocket_url": "wss://gateway.topstepx.com/signalr", ... "timezone": "US/Central", ... } >>> with open("config.json", "w") as f: ... json.dump(config, f) >>> >>> # V3: Use client with config file >>> import asyncio >>> from project_x_py import ProjectX >>> >>> async def main(): >>> async with ProjectX.from_config_file("config.json") as client: >>> await client.authenticate() >>> # Client is ready for trading operations >>> positions = await client.search_open_positions() >>> print(f"Open positions: {len(positions)}") >>> >>> asyncio.run(main())
Note
Config file should not be committed to version control
Consider using environment variables for production
File permissions should restrict access to the config file
- classmethod from_env(cls, config=None, account_name=None)[source]
Create async ProjectX client using environment variables (recommended approach).
This is the preferred method for initializing the async client as it keeps sensitive credentials out of your source code.
- Environment Variables Required:
PROJECT_X_API_KEY: API key for ProjectX authentication PROJECT_X_USERNAME: Username for ProjectX account
- Optional Environment Variables:
PROJECT_X_ACCOUNT_NAME: Account name to select specific account
- Parameters:
config (
ProjectXConfig|None) – Optional configuration object with endpoints and settingsaccount_name (
str|None) – Optional account name (overrides environment variable)
- Yields:
ProjectX – Configured async client instance ready for building trading applications
- Raises:
ValueError – If required environment variables are not set
- Return type:
AsyncGenerator[ProjectXBase,None]
Example
>>> # V3: Set environment variables first >>> import os >>> os.environ["PROJECT_X_API_KEY"] = "your_api_key_here" >>> os.environ["PROJECT_X_USERNAME"] = "your_username_here" >>> os.environ["PROJECT_X_ACCOUNT_NAME"] = ( ... "PRACTICEJUL2415232717" # Optional ... ) >>> >>> # V3: Create async client using context manager (recommended approach) >>> import asyncio >>> from project_x_py import ProjectX >>> >>> async def main(): >>> async with ProjectX.from_env() as client: >>> await client.authenticate() >>> # Client is now ready for use >>> instrument = await client.get_instrument("MNQ") >>> bars = await client.get_bars("MNQ", days=1, interval=5) >>> print(f"Retrieved {len(bars)} bars for {instrument.name}") >>> >>> asyncio.run(main())
- get_account_info()[source]
Get the currently selected account information.
- Returns:
Current account details
- Return type:
- Raises:
ProjectXAuthenticationError – If not authenticated
- get_session_token()[source]
Get the current session JWT token.
- Returns:
JWT token for authentication
- Return type:
- Raises:
ProjectXAuthenticationError – If not authenticated
- class RateLimiter(max_requests, window_seconds)[source]
Bases:
objectAsync rate limiter using sliding window algorithm.
This rate limiter implements a sliding window algorithm that tracks the exact timestamp of each request. It ensures that at any point in time, no more than max_requests have been made in the past window_seconds.
- Features:
Thread-safe using asyncio locks
Accurate sliding window implementation
Automatic cleanup of old request timestamps
Memory-efficient with bounded history
Zero CPU usage while waiting
- Parameters:
Example
>>> # Create a rate limiter for 10 requests per second >>> limiter = RateLimiter(max_requests=10, window_seconds=1) >>> >>> # Use in an async function >>> async def rate_limited_operation(): ... await limiter.acquire() ... # Perform operation here ... return "Success" >>> >>> # The limiter will automatically delay if needed >>> async def bulk_operations(): ... tasks = [rate_limited_operation() for _ in range(50)] ... results = await asyncio.gather(*tasks) ... # This will take ~5 seconds (50 requests / 10 per second)
- __init__(max_requests, window_seconds)[source]
- class ProjectX(username, api_key, config=None, account_name=None)[source]
Bases:
ProjectXBaseAsync core ProjectX client for the ProjectX Python SDK.
This class provides the async foundation for building trading applications by offering comprehensive asynchronous access to the ProjectX Trading Platform Gateway API. It handles core functionality including:
Multi-account authentication and JWT token management
Async instrument search and contract selection with caching
High-performance historical market data retrieval
Non-blocking position and trade history access
Automatic retry logic and connection pooling
Rate limiting and error handling
The async client is designed for high-performance applications requiring concurrent operations, real-time data processing, or integration with async frameworks like FastAPI, aiohttp, or Discord.py.
For order management and real-time data, use the specialized async managers from the project_x_py.async_api module which integrate seamlessly with this client.
Example
>>> # V3: Basic async SDK usage with environment variables (recommended) >>> import asyncio >>> from project_x_py import ProjectX >>> >>> async def main(): >>> # V3: Create and authenticate client with context manager >>> async with ProjectX.from_env() as client: >>> await client.authenticate() >>> >>> # V3: Get account info with typed models >>> account = client.account_info # After authentication >>> print(f"Account: {account.name}") >>> print(f"ID: {account.id}") >>> print(f"Balance: ${account.balance:,.2f}") >>> >>> # V3: Search for instruments with smart contract selection >>> instruments = await client.search_instruments("MNQ") >>> mnq = instruments[0] if instruments else None >>> if mnq: >>> print(f"Found: {mnq.name} ({mnq.symbol})") >>> print(f"Contract ID: {mnq.id}") >>> >>> # V3: Get historical data concurrently (returns Polars DataFrames) >>> tasks = [ >>> client.get_bars("MNQ", days=5, interval=5), # 5-min bars >>> client.get_bars("ES", days=1, interval=1), # 1-min bars >>> ] >>> nasdaq_data, sp500_data = await asyncio.gather(*tasks) >>> >>> print(f"Nasdaq bars: {len(nasdaq_data)} (Polars DataFrame)") >>> print(f"S&P 500 bars: {len(sp500_data)} (Polars DataFrame)") >>> print(f"Columns: {nasdaq_data.columns}") >>> >>> asyncio.run(main())
- For advanced async trading applications, use the TradingSuite:
>>> # V3: Advanced trading with the TradingSuite >>> import asyncio >>> from project_x_py import TradingSuite >>> >>> async def trading_app(): >>> # The TradingSuite simplifies setup and integrates all managers >>> suite = await TradingSuite.create( ... "MNQ", ... timeframes=["1min", "5min"], ... features=["orderbook", "risk_manager"] ... ) >>> >>> # Client is authenticated and real-time data is streaming. >>> >>> # Access integrated managers easily >>> order = await suite.orders.place_market_order( ... contract_id=suite.instrument_id, ... side=0, # Buy ... size=1 ... ) >>> >>> position = await suite.positions.get_position("MNQ") >>> bars = await suite.data.get_data("1min") >>> >>> print(f"Placed order {order.id}, current position: {position.netPos}") >>> print(f"Latest 1-min bar: {bars.tail(1)}") >>> >>> asyncio.run(trading_app())
Configuration Management
- class ConfigManager(config_file=None)[source]
Bases:
objectConfiguration manager for ProjectX client.
Handles loading configuration from: 1. Environment variables 2. Configuration files 3. Default values
Priority order: Environment variables > Config file > Defaults
- load_config()[source]
Load configuration with priority order.
- Return type:
- Returns:
ProjectXConfig instance
- save_config(config, file_path=None)[source]
Save configuration to file.
- Parameters:
config (
ProjectXConfig) – Configuration to savefile_path (
str|Path|None) – Optional path to save to (uses self.config_file if None)
- Return type:
- get_auth_config()[source]
Get authentication configuration from environment variables.
- Return type:
- Returns:
Dictionary with authentication settings
- Raises:
ValueError – If required authentication variables are missing or invalid
- validate_config(config)[source]
Validate configuration settings.
- Parameters:
config (
ProjectXConfig) – Configuration to validate- Return type:
- Returns:
True if configuration is valid
- Raises:
ValueError – If configuration is invalid
Configuration Models
- class ProjectXConfig(api_url='https://api.topstepx.com/api', realtime_url='wss://realtime.topstepx.com/api', user_hub_url='https://rtc.topstepx.com/hubs/user', market_hub_url='https://rtc.topstepx.com/hubs/market', timezone='America/Chicago', timeout_seconds=30, retry_attempts=3, retry_delay_seconds=2.0, requests_per_minute=60, burst_limit=10)[source]
Bases:
objectConfiguration settings for the ProjectX client.
Default URLs are set for TopStepX endpoints. For custom ProjectX endpoints, update the URLs accordingly using create_custom_config() or direct assignment.
TopStepX (Default): - user_hub_url: “https://rtc.topstepx.com/hubs/user” - market_hub_url: “https://rtc.topstepx.com/hubs/market”
- __init__(api_url='https://api.topstepx.com/api', realtime_url='wss://realtime.topstepx.com/api', user_hub_url='https://rtc.topstepx.com/hubs/user', market_hub_url='https://rtc.topstepx.com/hubs/market', timezone='America/Chicago', timeout_seconds=30, retry_attempts=3, retry_delay_seconds=2.0, requests_per_minute=60, burst_limit=10)
Factory Functions
Client Creation
Configuration Helpers
- load_default_config()[source]
Load default configuration with environment variable overrides.
- Return type:
- Returns:
ProjectXConfig instance