Trading Suite API¶
Unified trading interface combining all managers into a single, easy-to-use entry point for complete trading operations.
Overview¶
The TradingSuite is the primary interface for trading operations, combining all managers into a unified interface. It provides automatic component initialization, dependency injection, and configuration management.
project_x_py.trading_suite.TradingSuite
¶
TradingSuite(client: ProjectXBase, realtime_client: ProjectXRealtimeClient, config: TradingSuiteConfig, instrument_contexts: dict[str, InstrumentContext] | None = None)
Unified trading suite providing simplified access to all SDK components.
This class replaces the complex factory functions with a clean, intuitive API that handles all initialization, connection, and dependency management automatically.
Attributes:
-
instrument
(Instrument | None
) –Trading instrument symbol
-
data
(Any
) –Real-time data manager for OHLCV data
-
orders
(Any
) –Order management system
-
positions
(Any
) –Position tracking system
-
orderbook
(Any
) –Level 2 market depth (if enabled)
-
risk_manager
(Any
) –Risk management system (if enabled)
-
client
–Underlying ProjectX API client
-
realtime
–WebSocket connection manager
-
config
–Suite configuration
-
events
–Unified event bus for all components
Initialize TradingSuite with core components.
Note: Use the factory methods (create, from_config, from_env) instead of instantiating directly.
Parameters:
-
client
(ProjectXBase
) –ProjectX API client
-
realtime_client
(ProjectXRealtimeClient
) –WebSocket realtime client
-
config
(TradingSuiteConfig
) –Suite configuration
-
instrument_contexts
(dict[str, InstrumentContext] | None
, default:None
) –Pre-built instrument contexts (for multi-instrument)
Source code in src/project_x_py/trading_suite.py
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 |
|
instrument_id
property
¶
Get the full instrument/contract ID (e.g., 'CON.F.US.MNQ.U25').
__aenter__
async
¶
Async context manager entry.
Source code in src/project_x_py/trading_suite.py
__aexit__
async
¶
__aexit__(exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None) -> None
Async context manager exit with cleanup.
__contains__
¶
__getattr__
¶
Provide backward compatibility for single-instrument access.
This allows existing code to work while providing deprecation warnings. Only works in single-instrument mode.
Parameters:
-
name
(str
) –Attribute name being accessed
Returns:
-
Any
–The requested attribute from the single instrument context
Raises:
-
AttributeError
–If not in single-instrument mode or attribute not found
Source code in src/project_x_py/trading_suite.py
__getitem__
¶
Get InstrumentContext for a specific symbol.
Parameters:
-
symbol
(str
) –The instrument symbol (e.g., "MNQ", "ES")
Returns:
-
InstrumentContext
–InstrumentContext for the specified symbol
Raises:
-
KeyError
–If symbol is not found
Example
Source code in src/project_x_py/trading_suite.py
__iter__
¶
__len__
¶
connect
async
¶
Manually connect all components if auto_connect was disabled.
Example
Source code in src/project_x_py/trading_suite.py
create
async
classmethod
¶
create(instruments: str | list[str] | None = None, instrument: str | None = None, timeframes: list[str] | None = None, features: list[str] | None = None, session_config: SessionConfig | None = None, **kwargs: Any) -> TradingSuite
Create a fully initialized TradingSuite with sensible defaults.
This is the primary way to create a trading environment. It handles: - Authentication with ProjectX - WebSocket connection setup - Component initialization - Historical data loading - Market data subscriptions
Parameters:
-
instruments
(str | list[str] | None
, default:None
) –Trading symbol(s) - str for single, list for multiple
-
instrument
(str | None
, default:None
) –(Deprecated) Single trading symbol for backward compatibility
-
timeframes
(list[str] | None
, default:None
) –Data timeframes (default: ["5min"])
-
features
(list[str] | None
, default:None
) –Optional features to enable
-
session_config
(SessionConfig | None
, default:None
) –Optional session configuration
-
**kwargs
(Any
, default:{}
) –Additional configuration options
Returns:
-
TradingSuite
–Fully initialized and connected TradingSuite
Example
Source code in src/project_x_py/trading_suite.py
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 |
|
disconnect
async
¶
Gracefully disconnect all components and clean up resources.
Source code in src/project_x_py/trading_suite.py
from_config
async
classmethod
¶
Create TradingSuite from a configuration file.
Supports both YAML and JSON configuration files.
Parameters:
-
config_path
(str
) –Path to configuration file
Returns:
-
TradingSuite
–Configured TradingSuite instance
Example
Source code in src/project_x_py/trading_suite.py
from_env
async
classmethod
¶
Create TradingSuite using environment variables for configuration.
This method automatically loads ProjectX credentials from environment variables and applies any additional configuration from kwargs.
Required environment variables: - PROJECT_X_API_KEY - PROJECT_X_USERNAME
Parameters:
-
instrument
(str
) –Trading instrument symbol
-
**kwargs
(Any
, default:{}
) –Additional configuration options
Returns:
-
TradingSuite
–Configured TradingSuite instance
Example
Source code in src/project_x_py/trading_suite.py
get_session_data
async
¶
Get session-filtered market data.
Parameters:
-
timeframe
(str
) –Data timeframe (e.g., "1min", "5min")
-
session_type
(SessionType | None
, default:None
) –Optional session type override
Returns:
-
Any
–Polars DataFrame with session-filtered data
Source code in src/project_x_py/trading_suite.py
get_session_statistics
async
¶
Get session-specific statistics.
Returns:
-
dict[str, Any]
–Dictionary containing session statistics like volume, VWAP, etc.
Example
Source code in src/project_x_py/trading_suite.py
get_stats
async
¶
Get comprehensive statistics from all components using the aggregator.
Returns:
-
TradingSuiteStats
–Structured statistics from all active components with accurate metrics
Source code in src/project_x_py/trading_suite.py
get_stats_sync
¶
Synchronous wrapper for get_stats for backward compatibility.
Returns:
-
TradingSuiteStats
–Structured statistics from all active components
Source code in src/project_x_py/trading_suite.py
items
¶
keys
¶
managed_trade
¶
managed_trade(max_risk_percent: float | None = None, max_risk_amount: float | None = None) -> ManagedTrade
Create a managed trade context manager with automatic risk management.
This provides a high-level interface for executing trades with built-in: - Position sizing based on risk parameters - Trade validation against risk rules - Automatic stop-loss and take-profit attachment - Position monitoring and adjustment - Cleanup on exit
Parameters:
-
max_risk_percent
(float | None
, default:None
) –Override max risk percentage for this trade
-
max_risk_amount
(float | None
, default:None
) –Override max risk dollar amount for this trade
Returns:
-
ManagedTrade
–ManagedTrade context manager
Raises:
-
ValueError
–If risk manager is not enabled
Example
# Enter a risk-managed long position
async with suite.managed_trade(max_risk_percent=0.01) as trade:
result = await trade.enter_long(
stop_loss=current_price - 50,
take_profit=current_price + 100,
)
# Optional: Scale in
if market_conditions_favorable:
await trade.scale_in(additional_size=1)
# Optional: Adjust stop
if price_moved_favorably:
await trade.adjust_stop(new_stop_loss=entry_price)
# Automatic cleanup on exit
Source code in src/project_x_py/trading_suite.py
off
async
¶
Remove event handler(s).
Parameters:
-
event
(EventType | str | None
, default:None
) –Event type to remove handler from (None for all)
-
handler
(Any | None
, default:None
) –Specific handler to remove (None for all)
Source code in src/project_x_py/trading_suite.py
on
async
¶
Register event handler through unified event bus.
This is the single interface for all event handling in the SDK, replacing the scattered callback systems across components.
Parameters:
-
event
(EventType | str
) –Event type to listen for (EventType enum or string)
-
handler
(Any
) –Async callable to handle events
Example
async def handle_new_bar(event):
# event.data contains: {'timeframe': str, 'data': bar_dict}
bar_data = event.data.get("data", {})
timeframe = event.data.get("timeframe", "")
print(f"New {timeframe} bar: ${bar_data.get('close', 0):.2f}")
async def handle_position_closed(event):
# event.data contains the position object
position = event.data
print(f"Position closed: P&L = {position.pnl}")
async def handle_order_filled(event):
# event.data contains the order object
order = event.data
print(f"Order filled at {order.filledPrice}")
# Register handlers
await suite.on(EventType.NEW_BAR, handle_new_bar)
await suite.on(EventType.POSITION_CLOSED, handle_position_closed)
await suite.on(EventType.ORDER_FILLED, handle_order_filled)
Source code in src/project_x_py/trading_suite.py
once
async
¶
Register one-time event handler.
Handler will be automatically removed after first invocation.
Parameters:
-
event
(EventType | str
) –Event type to listen for
-
handler
(Any
) –Async callable to handle event once
Source code in src/project_x_py/trading_suite.py
order_chain
¶
Create an order chain builder for complex order structures.
Provides a fluent API for building multi-part orders (entry + stops + targets) with clean, readable syntax.
Returns:
-
OrderChainBuilder
–OrderChainBuilder instance
Example
# Build a bracket order with stops and targets
# Note: side=0 for BUY, side=1 for SELL
order_chain = (
suite.order_chain()
.market_order(size=2, side=0) # BUY 2 contracts
.with_stop_loss(offset=50)
.with_take_profit(offset=100)
.with_trail_stop(offset=25, trigger_offset=50)
)
result = await order_chain.execute()
# Or use a limit entry
order_chain = (
suite.order_chain()
.limit_order(size=1, price=16000, side=0) # BUY limit
.with_stop_loss(price=15950)
.with_take_profit(price=16100)
)
Source code in src/project_x_py/trading_suite.py
set_session_type
async
¶
Change the active session type for data filtering.
Parameters:
-
session_type
(SessionType
) –Type of session to filter for (RTH/ETH)
Source code in src/project_x_py/trading_suite.py
track_order
¶
Create an OrderTracker for comprehensive order lifecycle management.
This provides automatic order state tracking with async waiting capabilities, eliminating the need for manual order status polling.
Parameters:
-
order
(Any
, default:None
) –Optional order to track immediately (Order, OrderPlaceResponse, or order ID)
Returns:
-
OrderTracker
–OrderTracker instance (use as context manager)
Example
from project_x_py.types.trading import OrderSide
# Track a new order
async with suite.track_order() as tracker:
order = await suite.orders.place_limit_order(
contract_id=suite.instrument_id,
side=OrderSide.BUY,
size=1,
price=current_price - 10,
)
tracker.track(order)
try:
filled = await tracker.wait_for_fill(timeout=60)
print(f"Order filled at {filled.filledPrice}")
except TimeoutError:
await tracker.modify_or_cancel(new_price=current_price - 5)
Source code in src/project_x_py/trading_suite.py
values
¶
wait_for
async
¶
Wait for specific event to occur.
Parameters:
-
event
(EventType | str
) –Event type to wait for
-
timeout
(float | None
, default:None
) –Optional timeout in seconds
Returns:
-
Any
–Event object when received
Raises:
-
TimeoutError
–If timeout expires
Source code in src/project_x_py/trading_suite.py
Quick Start¶
Basic Setup¶
from project_x_py import TradingSuite
async def main():
# Simple one-liner with defaults
suite = await TradingSuite.create(["MNQ"])
# Everything is ready - client authenticated, realtime connected
await suite.disconnect()
asyncio.run(main())
Advanced Configuration¶
async def advanced_setup():
# Single instrument (backward compatible, but list is recommended)
suite_single = await TradingSuite.create(
["MNQ"], # List notation is preferred
timeframes=["1min", "5min", "15min"],
features=["orderbook", "risk_manager"],
initial_days=10,
timezone="America/Chicago"
)
# Multi-instrument (recommended for v3.5.0+)
suite_multi = await TradingSuite.create(
["MNQ", "MES", "MCL"], # List of instruments
timeframes=["1min", "5min", "15min"],
features=["orderbook", "risk_manager"],
initial_days=10,
timezone="America/Chicago"
)
# Access components (single instrument)
if len(suite_single) == 1:
# New recommended access
mnq_context = suite_single["MNQ"]
print(f"Data: {mnq_context.data}")
print(f"Orders: {mnq_context.orders}")
# Access components (multi-instrument - recommended)
for symbol, context in suite_multi.items():
print(f"{symbol} Data: {context.data}")
print(f"{symbol} Orders: {context.orders}")
print(f"{symbol} Positions: {context.positions}")
if context.orderbook: # if enabled
print(f"{symbol} OrderBook: {context.orderbook}")
if context.risk_manager: # if enabled
print(f"{symbol} RiskManager: {context.risk_manager}")
await suite_single.disconnect()
await suite_multi.disconnect()
Session Configuration (v3.4.0+)¶
Experimental Feature
Session filtering is experimental and not thoroughly tested with live data. Use with caution in production.
from project_x_py.sessions import SessionConfig, SessionType, SessionTimes
async def session_setup():
# RTH-only trading (9:30 AM - 4:00 PM ET)
rth_suite = await TradingSuite.create(
instruments=["MNQ"],
timeframes=["1min", "5min"],
session_config=SessionConfig(session_type=SessionType.RTH)
)
# ETH-only analysis (overnight sessions)
eth_suite = await TradingSuite.create(
instruments=["ES"],
session_config=SessionConfig(session_type=SessionType.ETH)
)
# Custom session times
from datetime import time
custom_config = SessionConfig(
session_type=SessionType.RTH,
session_times=SessionTimes(
rth_start=time(9, 0),
rth_end=time(15, 30),
eth_start=time(18, 0),
eth_end=time(17, 0)
)
)
custom_suite = await TradingSuite.create(
instruments=["CL"],
session_config=custom_config
)
await rth_suite.disconnect()
await eth_suite.disconnect()
await custom_suite.disconnect()
Configuration File Setup¶
async def config_file_setup():
# From configuration file
suite = await TradingSuite.from_config("config/trading.yaml")
# Or from dictionary
config = {
"instruments": ["MNQ"],
"timeframes": ["1min", "5min"],
"features": ["orderbook"],
"initial_days": 5
}
suite = await TradingSuite.from_dict(config)
await suite.disconnect()
Multi-Instrument Support (v3.5.0+)¶
Creating Multi-Instrument Suites¶
async def multi_instrument_setup():
# Create suite with multiple instruments
suite = await TradingSuite.create(
["MNQ", "MES", "MCL"], # List of instruments
timeframes=["1min", "5min"],
features=["orderbook", "risk_manager"]
)
# Suite acts as a dictionary
print(f"Managing {len(suite)} instruments")
print(f"Instruments: {list(suite.keys())}")
# Access each instrument context
for symbol in suite:
context = suite[symbol]
print(f"{symbol}: {context.instrument_info.name}")
await suite.disconnect()
Container Protocol Methods¶
async def container_protocol_demo():
suite = await TradingSuite.create(["MNQ", "MES", "MCL"])
# Dictionary-like operations
assert len(suite) == 3 # Number of instruments
assert "MNQ" in suite # Membership test
assert list(suite) == ["MNQ", "MES", "MCL"] # Iteration
# Access methods
symbols = list(suite.keys()) # Get all symbols
contexts = list(suite.values()) # Get all contexts
items = list(suite.items()) # Get (symbol, context) pairs
# Direct access
mnq = suite["MNQ"] # Get specific context
try:
unknown = suite["UNKNOWN"] # Raises KeyError
except KeyError as e:
print(f"Instrument not found: {e}")
await suite.disconnect()
Multi-Instrument Trading¶
async def multi_instrument_trading():
suite = await TradingSuite.create(
["MNQ", "MES", "MCL"],
features=["orderbook", "risk_manager"]
)
# Place orders on multiple instruments
for symbol, context in suite.items():
# Each instrument has its own managers
order = await context.orders.place_market_order(
contract_id=context.instrument_info.id,
side=0, # Buy
size=1
)
print(f"{symbol} order placed: {order.order_id}")
# Monitor positions across all instruments
total_exposure = 0
for symbol, context in suite.items():
positions = await context.positions.get_all_positions()
for pos in positions:
exposure = abs(pos.size * pos.averagePrice)
total_exposure += exposure
print(f"{symbol} position: {pos.size} @ ${pos.averagePrice}")
print(f"Total portfolio exposure: ${total_exposure:,.2f}")
await suite.disconnect()
Session Management with Multi-Instruments¶
from project_x_py.sessions import SessionType
async def multi_instrument_sessions():
suite = await TradingSuite.create(["MNQ", "MES"])
# Set session type for all instruments
await suite.set_session_type(SessionType.RTH)
# Get session data for all instruments (returns dict)
session_data = await suite.get_session_data("5min", SessionType.RTH)
# Returns: {"MNQ": DataFrame, "MES": DataFrame}
for symbol, data in session_data.items():
if data is not None and not data.is_empty():
print(f"{symbol} RTH bars: {len(data)}")
# Get session statistics for all instruments
session_stats = await suite.get_session_statistics("5min")
# Returns: {"MNQ": stats_dict, "MES": stats_dict} for multi-instrument
# or just stats_dict for single instrument
await suite.disconnect()
Features¶
Available Features¶
project_x_py.trading_suite.Features
¶
Bases: str
, Enum
Available feature flags for TradingSuite.
Feature Configuration¶
from project_x_py import Features
# Enable specific features
features = [
Features.ORDERBOOK, # Level 2 market depth
Features.RISK_MANAGER, # Risk management and position sizing
Features.AUTO_RECONNECT, # Automatic reconnection (future)
]
suite = await TradingSuite.create(
["MNQ"],
features=features
)
Configuration¶
TradingSuiteConfig¶
project_x_py.trading_suite.TradingSuiteConfig
¶
TradingSuiteConfig(instrument: str, timeframes: list[str] | None = None, features: list[Features] | None = None, initial_days: int = 5, auto_connect: bool = True, timezone: str = 'America/Chicago', order_manager_config: OrderManagerConfig | None = None, position_manager_config: PositionManagerConfig | None = None, data_manager_config: DataManagerConfig | None = None, orderbook_config: OrderbookConfig | None = None, risk_config: RiskConfig | None = None, session_config: SessionConfig | None = None)
Configuration for TradingSuite initialization.
Source code in src/project_x_py/trading_suite.py
get_data_manager_config
¶
Get configuration for RealtimeDataManager.
Returns:
-
DataManagerConfig
(DataManagerConfig
) –The configuration for the RealtimeDataManager.
Source code in src/project_x_py/trading_suite.py
get_order_manager_config
¶
Get configuration for OrderManager.
Returns:
-
OrderManagerConfig
(OrderManagerConfig
) –The configuration for the OrderManager.
Source code in src/project_x_py/trading_suite.py
get_orderbook_config
¶
Get configuration for OrderBook.
Returns:
-
OrderbookConfig
(OrderbookConfig
) –The configuration for the OrderBook.
Source code in src/project_x_py/trading_suite.py
get_position_manager_config
¶
Get configuration for PositionManager.
Returns:
-
PositionManagerConfig
(PositionManagerConfig
) –The configuration for the PositionManager.
Source code in src/project_x_py/trading_suite.py
get_risk_config
¶
Get configuration for RiskManager.
Returns:
-
RiskConfig
(RiskConfig
) –The configuration for the RiskManager.
Source code in src/project_x_py/trading_suite.py
Component Configuration¶
from project_x_py.types import (
OrderManagerConfig,
PositionManagerConfig,
DataManagerConfig,
OrderbookConfig
)
from project_x_py.risk_manager import RiskConfig
from project_x_py.sessions import SessionConfig, SessionType
async def custom_configuration():
# Custom component configurations
order_config = OrderManagerConfig(
max_concurrent_orders=10,
default_timeout=30.0,
retry_attempts=3
)
position_config = PositionManagerConfig(
track_unrealized=True,
calculate_metrics=True,
update_frequency=1.0
)
risk_config = RiskConfig(
max_position_size=5,
max_daily_loss=1000.0,
max_drawdown_percent=10.0
)
# Session configuration (v3.4.0+)
session_config = SessionConfig(
session_type=SessionType.RTH
)
suite = await TradingSuite.create(
["MNQ"],
order_manager_config=order_config,
position_manager_config=position_config,
risk_config=risk_config,
session_config=session_config # New in v3.4.0
)
await suite.disconnect()
Component Access¶
Core Components¶
async def component_access():
suite = await TradingSuite.create(["MNQ"], features=["orderbook", "risk_manager"])
# Global components (always available)
client = suite.client # ProjectX API client
realtime = suite.realtime # ProjectXRealtimeClient
# Single instrument access (new recommended way)
mnq_context = suite["MNQ"]
orders = mnq_context.orders # OrderManager for MNQ
positions = mnq_context.positions # PositionManager for MNQ
data = mnq_context.data # RealtimeDataManager for MNQ
# Optional components (per instrument)
if mnq_context.orderbook:
orderbook = mnq_context.orderbook # OrderBook for MNQ
if mnq_context.risk_manager:
risk_mgr = mnq_context.risk_manager # RiskManager for MNQ
# Instrument information
instrument_info = mnq_context.instrument_info
instrument_id = mnq_context.instrument_info.id
await suite.disconnect()
Trading Operations¶
Order Management¶
async def order_operations():
suite = await TradingSuite.create(["MNQ"])
mnq_context = suite["MNQ"]
# Place market order
market_order = await mnq_context.orders.place_market_order(
contract_id=mnq_context.instrument_info.id,
side=0, # Buy
size=1
)
# Place limit order
limit_order = await mnq_context.orders.place_limit_order(
contract_id=mnq_context.instrument_info.id,
side=0, # Buy
size=1,
limit_price=21050.0
)
# Place bracket order
bracket_result = await mnq_context.orders.place_bracket_order(
contract_id=mnq_context.instrument_info.id,
side=0, # Buy
size=1,
entry_price=21050.0,
stop_offset=25.0,
target_offset=50.0
)
await suite.disconnect()
Position Management¶
async def position_operations():
suite = await TradingSuite.create(["MNQ"])
mnq_positions = suite["MNQ"].positions
# Get current position
position = await mnq_positions.get_position("MNQ")
if position:
print(f"Size: {position.size}")
print(f"Avg Price: {position.avg_price}")
print(f"Unrealized PnL: {position.unrealized_pnl}")
# Get all positions
positions = await suite["MNQ"].positions.get_all_positions()
# Get position metrics
metrics = await mnq_positions.get_metrics()
print(f"Total PnL: {metrics.get('total_pnl', 0)}")
print(f"Win Rate: {metrics.get('win_rate', 0):.1%}")
await suite.disconnect()
Market Data Access¶
async def data_access():
suite = await TradingSuite.create(["MNQ"], timeframes=["1min", "5min"], features=["orderbook"])
mnq_context = suite["MNQ"]
# Get historical data via client
historical = await suite.client.get_bars("MNQ", days=5, interval=60)
# Get real-time data
current_price = await mnq_context.data.get_current_price()
latest_bars_1min = await mnq_context.data.get_data("1min")
latest_bars_5min = await mnq_context.data.get_data("5min")
# OrderBook data (if enabled)
if mnq_context.orderbook:
depth = await mnq_context.orderbook.get_depth()
trades = await mnq_context.orderbook.get_recent_trades()
await suite.disconnect()
Session-Aware Data Access (v3.4.0+)¶
from project_x_py.sessions import SessionType, SessionConfig
async def session_data_access():
# Create suite with session configuration
suite = await TradingSuite.create(
["MNQ"],
timeframes=["1min", "5min"],
session_config=SessionConfig(session_type=SessionType.RTH)
)
mnq_context = suite["MNQ"]
# Get session-specific data using data manager methods
rth_data = await mnq_context.data.get_session_data("5min", SessionType.RTH)
eth_data = await mnq_context.data.get_session_data("5min", SessionType.ETH)
# Get session statistics from data manager
session_stats = await mnq_context.data.get_session_statistics("5min")
if session_stats:
print(f"RTH Volume: {session_stats.get('rth_volume', 0):,}")
print(f"ETH Volume: {session_stats.get('eth_volume', 0):,}")
print(f"RTH VWAP: ${session_stats.get('rth_vwap', 0):.2f}")
print(f"ETH VWAP: ${session_stats.get('eth_vwap', 0):.2f}")
print(f"RTH Range: ${session_stats.get('rth_range', 0):.2f}")
print(f"ETH Range: ${session_stats.get('eth_range', 0):.2f}")
await suite.disconnect()
Event Handling¶
Real-time Events¶
from project_x_py import EventType
async def event_handling():
suite = await TradingSuite.create(["MNQ"], timeframes=["1min"])
mnq_context = suite["MNQ"]
# Register event handlers
async def on_new_bar(event):
print(f"New {event.timeframe} bar: {event.data}")
async def on_order_filled(event):
print(f"Order filled: {event.order_id}")
async def on_position_changed(event):
print(f"Position changed: {event.data}")
# Register handlers
await mnq_context.on(EventType.NEW_BAR, on_new_bar)
await mnq_context.on(EventType.ORDER_FILLED, on_order_filled)
await mnq_context.on(EventType.POSITION_CHANGED, on_position_changed)
# Keep running to receive events
await asyncio.sleep(60)
await suite.disconnect()
Statistics & Health Monitoring¶
Comprehensive Statistics¶
async def statistics_monitoring():
suite = await TradingSuite.create(["MNQ"], features=["orderbook", "risk_manager"])
mnq_context = suite["MNQ"]
# Get system statistics (async-first API)
stats = await suite.get_statistics()
print(f"System Health: {stats['health_score']:.1f}/100")
print(f"API Success Rate: {stats['api_success_rate']:.1%}")
print(f"Memory Usage: {stats['memory_usage_mb']:.1f} MB")
# Component-specific statistics
order_stats = await mnq_context.orders.get_stats()
position_stats = await mnq_context.positions.get_stats()
data_stats = await mnq_context.data.get_stats()
if mnq_context.orderbook:
orderbook_stats = await mnq_context.orderbook.get_stats()
# Export statistics
prometheus_metrics = await suite.export_stats("prometheus")
csv_data = await suite.export_stats("csv")
await suite.disconnect()
Health Monitoring¶
async def health_monitoring():
suite = await TradingSuite.create(["MNQ"])
# Real-time health monitoring
health_score = await suite.get_health_score()
if health_score < 70:
print(f" System health degraded: {health_score:.1f}/100")
# Get component health breakdown
component_health = await suite.get_component_health()
for name, health in component_health.items():
if health['error_count'] > 0:
print(f" {name}: {health['error_count']} errors")
await suite.disconnect()
Risk Management¶
ManagedTrade Integration¶
from project_x_py.risk_manager import ManagedTrade
from project_x_py import Features
async def risk_managed_trading():
suite = await TradingSuite.create(["MNQ"], features=[Features.RISK_MANAGER])
mnq_context = suite["MNQ"]
# Create a managed trade with risk controls
managed_trade = ManagedTrade(
risk_manager=mnq_context.risk_manager,
order_manager=mnq_context.orders,
position_manager=mnq_context.positions,
instrument_id=mnq_context.instrument_info.id,
data_manager=mnq_context.data # Pass data_manager for ATR calculations etc.
)
# Execute the trade with automatic risk management
result = await managed_trade.execute_trade(
side=0, # Buy
entry_signal="RSI oversold + support level",
stop_loss_type="atr", # ATR-based stop
take_profit_type="fixed" # Fixed target
)
if result.success:
print(f"Trade executed: {result.main_order_id}")
print(f"Stop Loss: {result.stop_order_id}")
print(f"Take Profit: {result.target_order_id}")
await suite.disconnect()
Order Tracking & Lifecycle¶
Order Chain Management¶
async def order_lifecycle():
suite = await TradingSuite.create(["MNQ"])
mnq_context = suite["MNQ"]
# Track order lifecycle
tracker = mnq_context.track_order()
# Create order chain
chain = mnq_context.order_chain()
# Build complex order sequence
entry_order = await chain.add_market_order(
contract_id=mnq_context.instrument_info.id,
side=0,
size=1
)
# Add conditional orders
await chain.add_stop_order(
contract_id=mnq_context.instrument_info.id,
side=1, # Sell to close
size=1,
stop_price=21000.0,
condition=f"when {entry_order.id} filled"
)
# Execute the chain
await chain.execute()
await suite.disconnect()
Connection Management¶
Lifecycle Management¶
Context Manager (Recommended)¶
async def context_manager_usage():
# Recommended: Use context manager for automatic cleanup
async with TradingSuite.create(["MNQ"]) as suite:
mnq_context = suite["MNQ"]
# Suite is automatically connected on entry
current_price = await mnq_context.data.get_current_price()
print(f"Current Price: ${current_price:.2f}")
# Place a trade
order = await mnq_context.orders.place_market_order(
contract_id=mnq_context.instrument_info.id,
side=0, # Buy
size=1
)
# Suite automatically disconnects on exit
Reconnection Handling¶
async def reconnection_handling():
suite = await TradingSuite.create(["MNQ"], features=["auto_reconnect"])
# Check connection status
client_connected = await suite.client.is_connected()
realtime_connected = await suite.realtime.is_connected()
if not client_connected:
await suite.client.reconnect()
if not realtime_connected:
await suite.realtime.reconnect()
await suite.disconnect()
Configuration Examples¶
YAML Configuration¶
# config/trading.yaml
instrument: "MNQ"
timeframes:
- "1min"
- "5min"
- "15min"
features:
- "orderbook"
- "risk_manager"
initial_days: 7
timezone: "America/Chicago"
order_manager:
max_concurrent_orders: 10
default_timeout: 30.0
retry_attempts: 3
position_manager:
track_unrealized: true
calculate_metrics: true
update_frequency: 1.0
risk_config:
max_position_size: 5
max_daily_loss: 1000.0
max_drawdown_percent: 10.0
orderbook:
max_depth_levels: 10
enable_order_flow: true
track_volume_profile: true
JSON Configuration¶
{
"instrument": "MNQ",
"timeframes": ["1min", "5min"],
"features": ["orderbook", "risk_manager"],
"initial_days": 5,
"order_manager": {
"max_concurrent_orders": 5,
"default_timeout": 30.0
},
"risk_config": {
"max_position_size": 3,
"max_daily_loss": 500.0
}
}
Best Practices¶
Initialization¶
# Recommended: Use TradingSuite.create()
suite = await TradingSuite.create(["MNQ"], features=["orderbook"])
# Good: Use context manager for automatic cleanup
async with TradingSuite.create(["MNQ"]) as suite:
# Trading operations
pass
# L Not recommended: Manual component initialization
# client = ProjectX.from_env()
# orders = OrderManager(client) # Too complex
Error Handling¶
Error Handling¶
from project_x_py.exceptions import ProjectXError
async def robust_trading():
try:
suite = await TradingSuite.create(["MNQ"])
mnq_context = suite["MNQ"]
# Trading operations with error handling
try:
order = await mnq_context.orders.place_market_order(
contract_id=mnq_context.instrument_info.id,
side=0,
size=1
)
except ProjectXError as e:
print(f"Order failed: {e}")
except Exception as e:
print(f"Suite creation failed: {e}")
finally:
if 'suite' in locals():
await suite.disconnect()
Resource Management¶
async def resource_management():
# Monitor resource usage
suite = await TradingSuite.create(["MNQ"], features=["orderbook"])
# Periodic health checks
while True:
stats = await suite.get_statistics()
memory_mb = stats.get('memory_usage_mb', 0)
if memory_mb > 100: # MB threshold
print(f"High memory usage: {memory_mb:.1f} MB")
await asyncio.sleep(60) # Check every minute
See Also¶
- Order Manager API - Detailed order management
- Position Manager API - Position tracking
- Statistics API - Health monitoring and analytics
- Client API - Core client functionality
- Risk Management Guide - Risk management concepts