Skip to content

Order Manager API

Comprehensive async order management with support for market, limit, stop, and bracket orders, plus advanced order lifecycle tracking.

Overview

The OrderManager provides comprehensive order placement, modification, and tracking capabilities with full async support. It handles complex order types including bracket orders, OCO (One Cancels Other) orders, and position-based orders.

Quick Start

from project_x_py import TradingSuite

async def basic_order_management():
    suite = await TradingSuite.create(["MNQ"])
    mnq_context = suite["MNQ"]

    # Access the integrated order manager
    orders = mnq_context.orders

    # Place a simple market order
    response = await orders.place_market_order(
        contract_id=mnq_context.instrument_info.id,
        side=0,  # Buy
        size=1
    )

    print(f"Order placed: {response.order_id}")
    await suite.disconnect()

Order Types

Market Orders

async def market_orders():
    suite = await TradingSuite.create(["MNQ"])
    mnq_orders = suite["MNQ"].orders
    mnq_instrument_id = suite["MNQ"].instrument_info.id

    # Simple market order
    buy_order = await mnq_orders.place_market_order(
        contract_id=mnq_instrument_id,
        side=0,  # Buy
        size=1
    )

    # Market order with additional parameters
    sell_order = await mnq_orders.place_market_order(
        contract_id=mnq_instrument_id,
        side=1,  # Sell
        size=2,
        time_in_force="IOC",  # Immediate or Cancel
        reduce_only=True      # Position reducing only
    )

    await suite.disconnect()

Limit Orders

async def limit_orders():
    suite = await TradingSuite.create(["MNQ"])
    mnq_orders = suite["MNQ"].orders
    mnq_instrument_id = suite["MNQ"].instrument_info.id

    # Buy limit order
    buy_limit = await mnq_orders.place_limit_order(
        contract_id=mnq_instrument_id,
        side=0,  # Buy
        size=1,
        limit_price=21000.0
    )

    # Sell limit order with time in force
    sell_limit = await mnq_orders.place_limit_order(
        contract_id=mnq_instrument_id,
        side=1,  # Sell
        size=1,
        limit_price=21100.0,
        time_in_force="GTC"  # Good Till Cancelled
    )

    await suite.disconnect()

Stop Orders

async def stop_orders():
    suite = await TradingSuite.create(["MNQ"])
    mnq_orders = suite["MNQ"].orders
    mnq_instrument_id = suite["MNQ"].instrument_info.id

    # Stop loss order
    stop_loss = await mnq_orders.place_stop_order(
        contract_id=mnq_instrument_id,
        side=1,  # Sell (to close long position)
        size=1,
        stop_price=20950.0
    )

    # Stop limit order
    stop_limit = await mnq_orders.place_stop_limit_order(
        contract_id=mnq_instrument_id,
        side=1,  # Sell
        size=1,
        stop_price=20950.0,
        limit_price=20940.0  # Limit price after stop triggered
    )

    await suite.disconnect()

Advanced Order Types

Bracket Orders

async def bracket_orders():
    suite = await TradingSuite.create(["MNQ"])
    mnq_orders = suite["MNQ"].orders
    mnq_instrument_id = suite["MNQ"].instrument_info.id

    # Complete bracket order with stop and target
    bracket_result = await mnq_orders.place_bracket_order(
        contract_id=mnq_instrument_id,
        side=0,  # Buy
        size=1,
        entry_price=21050.0,    # Entry limit price
        stop_offset=25.0,       # $25 stop loss
        target_offset=50.0      # $50 profit target
    )

    print(f"Main Order: {bracket_result.main_order_id}")
    print(f"Stop Loss: {bracket_result.stop_order_id}")
    print(f"Take Profit: {bracket_result.target_order_id}")

    # Market bracket order (immediate entry)
    market_bracket = await mnq_orders.place_bracket_order(
        contract_id=mnq_instrument_id,
        side=0,  # Buy
        size=1,
        entry_price=None,       # Market entry
        stop_offset=30.0,
        target_offset=60.0
    )

    await suite.disconnect()

OCO (One Cancels Other) Orders

async def oco_orders():
    suite = await TradingSuite.create(["MNQ"])
    mnq_orders = suite["MNQ"].orders
    mnq_instrument_id = suite["MNQ"].instrument_info.id

    # OCO order: Either stop loss OR take profit
    oco_result = await mnq_orders.place_oco_order(
        contract_id=mnq_instrument_id,
        size=1,
        first_order={
            "type": "limit",
            "side": 1,  # Sell
            "price": 21100.0  # Take profit
        },
        second_order={
            "type": "stop",
            "side": 1,  # Sell
            "stop_price": 20950.0  # Stop loss
        }
    )

    await suite.disconnect()

Position-Based Orders

async def position_based_orders():
    suite = await TradingSuite.create(["MNQ"])
    mnq_orders = suite["MNQ"].orders

    # Close entire position
    close_result = await mnq_orders.close_position(
        instrument="MNQ",
        method="market"  # or "limit"
    )

    # Reduce position by 50%
    reduce_result = await mnq_orders.reduce_position(
        instrument="MNQ",
        percentage=0.5,  # Reduce by 50%
        method="limit",
        limit_price=21075.0
    )

    # Scale out of position in stages
    scale_result = await mnq_orders.scale_out_position(
        instrument="MNQ",
        levels=[
            {"percentage": 0.33, "price": 21060.0},  # Take 1/3 at 21060
            {"percentage": 0.33, "price": 21080.0},  # Take 1/3 at 21080
            {"percentage": 0.34, "price": 21100.0}   # Take remaining at 21100
        ]
    )

    await suite.disconnect()

Order Modification & Management

Modify Orders

async def modify_orders():
    suite = await TradingSuite.create(["MNQ"])
    mnq_orders = suite["MNQ"].orders
    mnq_instrument_id = suite["MNQ"].instrument_info.id

    # Place initial order
    order = await mnq_orders.place_limit_order(
        contract_id=mnq_instrument_id,
        side=0,
        size=1,
        limit_price=21000.0
    )

    # Modify price
    modified = await mnq_orders.modify_order(
        order_id=order.order_id,
        limit_price=21010.0  # New price
    )

    # Modify quantity
    modified_qty = await mnq_orders.modify_order(
        order_id=order.order_id,
        size=2  # Increase size
    )

    await suite.disconnect()

Cancel Orders

async def cancel_orders():
    suite = await TradingSuite.create(["MNQ"])
    mnq_orders = suite["MNQ"].orders
    mnq_instrument_id = suite["MNQ"].instrument_info.id

    # Place some orders
    order1 = await mnq_orders.place_limit_order(
        contract_id=mnq_instrument_id,
        side=0, size=1, limit_price=21000.0
    )
    order2 = await mnq_orders.place_limit_order(
        contract_id=mnq_instrument_id,
        side=0, size=1, limit_price=21010.0
    )

    # Cancel single order
    await mnq_orders.cancel_order(order1.order_id)

    # Cancel multiple orders
    await mnq_orders.cancel_orders([order1.order_id, order2.order_id])

    # Cancel all orders for instrument
    await mnq_orders.cancel_all_orders(instrument="MNQ")

    # Cancel all orders (all instruments)
    await suite.orders.cancel_all_orders()

    await suite.disconnect()

Order Tracking & Status

Order Status Monitoring

async def order_status():
    suite = await TradingSuite.create(["MNQ"])
    mnq_orders = suite["MNQ"].orders
    mnq_instrument_id = suite["MNQ"].instrument_info.id

    # Place order
    order = await mnq_orders.place_limit_order(
        contract_id=mnq_instrument_id,
        side=0, size=1, limit_price=21000.0
    )

    # Get order status
    status = await mnq_orders.get_order_status(order.order_id)
    print(f"Order Status: {status.status}")
    print(f"Filled Quantity: {status.filled_quantity}")
    print(f"Remaining: {status.remaining_quantity}")

    # Get detailed order info
    order_info = await mnq_orders.get_order(order.order_id)

    # Wait for fill
    filled_order = await mnq_orders.wait_for_fill(
        order.order_id,
        timeout=60.0
    )

    await suite.disconnect()

Order History

async def order_history():
    suite = await TradingSuite.create(["MNQ"])
    mnq_orders = suite["MNQ"].orders

    # Get all orders
    all_orders = await mnq_orders.get_orders()

    # Get orders by status
    pending_orders = await mnq_orders.get_orders(status="pending")
    filled_orders = await mnq_orders.get_orders(status="filled")

    # Get orders by instrument
    mnq_orders_filtered = await mnq_orders.get_orders(instrument="MNQ")

    # Get recent orders
    recent_orders = await mnq_orders.get_recent_orders(limit=10)

    await suite.disconnect()

Order Lifecycle Tracking

async def order_lifecycle():
    suite = await TradingSuite.create(["MNQ"])
    mnq_context = suite["MNQ"]

    # Track order lifecycle with events
    async def on_order_update(event):
        print(f"Order {event.order_id} status: {event.status}")

    async def on_order_filled(event):
        print(f"Order {event.order_id} filled at {event.fill_price}")

    # Register event handlers
    await mnq_context.orders.on_order_update(on_order_update)
    await mnq_context.orders.on_order_filled(on_order_filled)

    # Place order with tracking
    order = await mnq_context.orders.place_limit_order(
        contract_id=mnq_context.instrument_info.id,
        side=0, size=1, limit_price=21000.0
    )

    # Wait for events
    await asyncio.sleep(60)
    await suite.disconnect()

Order Templates & Strategies

Order Templates

from project_x_py.order_templates import get_template

async def order_templates():
    suite = await TradingSuite.create(["MNQ"])
    mnq_context = suite["MNQ"]

    # Use predefined templates
    scalping_template = get_template("scalping")
    breakout_template = get_template("breakout")
    risk_reward_template = get_template("risk_reward")

    # Apply scalping template
    scalp_order = await scalping_template.create_order(
        context=mnq_context,
        side=0,  # Buy
        current_price=21050.0,
        atr_value=15.0
    )

    # Apply breakout template
    breakout_order = await breakout_template.create_order(
        context=mnq_context,
        side=0,  # Buy
        breakout_price=21075.0,
        support_level=21000.0,
        resistance_level=21150.0
    )

    await suite.disconnect()

Custom Templates

from project_x_py.order_templates import OrderTemplate

class CustomTemplate(OrderTemplate):
    """Custom order template for specific strategy."""

    async def create_order(self, context, side, **kwargs):
        # Custom logic here
        entry_price = kwargs.get('entry_price')
        risk_amount = kwargs.get('risk_amount', 100.0)

        # Calculate position size based on risk
        stop_distance = kwargs.get('stop_distance', 25.0)
        position_size = risk_amount / stop_distance

        # Place bracket order
        return await context.orders.place_bracket_order(
            contract_id=context.instrument_info.id,
            side=side,
            size=int(position_size),
            entry_price=entry_price,
            stop_offset=stop_distance,
            target_offset=stop_distance * 2  # 1:2 RR
        )

async def custom_template():
    suite = await TradingSuite.create(["MNQ"])
    mnq_context = suite["MNQ"]
    template = CustomTemplate()

    order = await template.create_order(
        context=mnq_context,
        side=0,
        entry_price=21050.0,
        risk_amount=200.0,
        stop_distance=30.0
    )

    await suite.disconnect()

Error Recovery

async def error_recovery():
    suite = await TradingSuite.create(["MNQ"])
    mnq_orders = suite["MNQ"].orders
    mnq_instrument_id = suite["MNQ"].instrument_info.id

    try:
        # Attempt order placement
        order = await mnq_orders.place_limit_order(
            contract_id=mnq_instrument_id,
            side=0, size=1, limit_price=21000.0
        )
    except InsufficientMarginError:
        print("Insufficient margin - reducing position size")
        # Retry with smaller size
        order = await mnq_orders.place_limit_order(
            contract_id=mnq_instrument_id,
            side=0, size=0.5, limit_price=21000.0
        )
    except OrderRejectedError as e:
        print(f"Order rejected: {e}")
        # Handle rejection (adjust price, etc.)

    await suite.disconnect()

Order Statistics

async def order_statistics():
    suite = await TradingSuite.create(["MNQ"])
    mnq_orders = suite["MNQ"].orders

    # Get order manager statistics
    stats = await mnq_orders.get_stats()

    print(f"Total Orders: {stats['total_orders']}")
    print(f"Fill Rate: {stats['fill_rate']:.1%}")
    print(f"Average Fill Time: {stats['avg_fill_time_ms']:.0f}ms")
    print(f"Rejected Orders: {stats['rejected_orders']}")
    print(f"Error Rate: {stats['error_rate']:.1%}")

    # Performance metrics
    performance = stats.get('performance_metrics', {})
    print(f"Orders per Second: {performance.get('orders_per_second', 0):.1f}")
    print(f"Average Response Time: {performance.get('avg_response_time_ms', 0):.0f}ms")

    await suite.disconnect()

Configuration

OrderManagerConfig

from project_x_py.types import OrderManagerConfig

async def configure_order_manager():
    # Custom order manager configuration
    order_config = OrderManagerConfig(
        max_concurrent_orders=10,      # Max simultaneous orders
        default_timeout=30.0,          # Default timeout in seconds
        retry_attempts=3,              # Retry attempts on failure
        enable_order_tracking=True,    # Enable lifecycle tracking
        track_performance=True,        # Track performance metrics
        auto_cancel_on_disconnect=True # Cancel orders on disconnect
    )

    suite = await TradingSuite.create(
        ["MNQ"],
        order_manager_config=order_config
    )

    await suite.disconnect()

Best Practices

Order Placement

# Good: Use proper error handling
try:
    suite = await TradingSuite.create(["MNQ"])
    mnq_context = suite["MNQ"]
    order = await mnq_context.orders.place_limit_order(
        contract_id=mnq_context.instrument_info.id,
        side=0, size=1, limit_price=21000.0
    )
except ProjectXOrderError as e:
    print(f"Order failed: {e}")

# Good: Validate parameters
if suite["MNQ"].instrument_info.min_tick_size:
    # Round price to tick size
    rounded_price = round_to_tick_size(price, suite["MNQ"].instrument_info.min_tick_size)

# Good: Use bracket orders for risk management
bracket_order = await suite["MNQ"].orders.place_bracket_order(
    contract_id=suite["MNQ"].instrument_info.id,
    side=0, size=1,
    entry_price=21050.0,
    stop_offset=25.0,    # Risk management
    target_offset=50.0   # Profit target
)

Resource Management

# Good: Cancel orders on shutdown
async def cleanup_orders(suite):
    try:
        # Cancel pending orders
        await suite["MNQ"].orders.cancel_all_orders()
    except Exception as e:
        print(f"Cleanup failed: {e}")
    finally:
        await suite.disconnect()

# Good: Monitor order limits
stats = await suite["MNQ"].orders.get_stats()
if stats['pending_orders'] > 50:
    print("Warning: High number of pending orders")

See Also