Models & Exceptions

Data models and exception classes used throughout the project-x-py package.

Core Models

ProjectX Data Models

Author: @TexasCoding Date: 2025-08-02

Overview:

Contains all data model classes for the ProjectX API client. Provides comprehensive data structures for trading entities, configuration, and real-time events. All models use dataclasses for type safety and automatic serialization/deserialization.

Key Features:
  • Comprehensive trading entity models (Instrument, Order, Position, Trade)

  • Configuration models with default values

  • Real-time event models for WebSocket data

  • Type-safe dataclass implementations

  • Automatic serialization/deserialization

  • Comprehensive field documentation and examples

Data Models:
  • Trading Entities: Instrument, Order, Position, Trade, Account

  • Configuration: ProjectXConfig with default TopStepX endpoints

  • Responses: OrderPlaceResponse, BracketOrderResponse

  • Events: OrderUpdateEvent, PositionUpdateEvent, MarketDataEvent

Example Usage:

```python from project_x_py.models import (

Instrument, Order, Position, Trade, Account, ProjectXConfig, OrderPlaceResponse,

)

# Create instrument model instrument = Instrument(

id=”CON.F.US.MGC.M25”, name=”MGCH25”, description=”Mini Gold Futures March 2025”, tickSize=0.1, tickValue=1.0, activeContract=True,

)

# Create order model order = Order(

id=12345, accountId=1001, contractId=”CON.F.US.MGC.M25”, creationTimestamp=”2024-01-01T10:00:00Z”, updateTimestamp=”2024-01-01T10:00:05Z”, status=OrderStatus.OPEN, type=OrderType.LIMIT, side=OrderSide.BUY, size=5, limitPrice=2050.0,

)

# Create position model position = Position(

id=67890, accountId=1001, contractId=”CON.F.US.MGC.M25”, creationTimestamp=”2024-01-01T10:00:00Z”, type=PositionType.LONG, size=5, averagePrice=2050.0,

)

# Create configuration config = ProjectXConfig(

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”, timezone=”America/Chicago”,

Trading Entity Models:
  • Instrument: Tradeable financial instruments with tick information

  • Order: Trading orders with status, type, and execution details

  • Position: Open trading positions with size and average price

  • Trade: Executed trades with P&L and fee information

  • Account: Trading accounts with balance and permissions

Configuration Models:
  • ProjectXConfig: Client configuration with endpoints and settings

  • Default TopStepX endpoints for production use

  • Customizable for different ProjectX deployments

  • Comprehensive validation and error handling

Event Models:
  • OrderUpdateEvent: Real-time order status updates

  • PositionUpdateEvent: Real-time position changes

  • MarketDataEvent: Real-time market data updates

Model Features:
  • Type-safe dataclass implementations

  • Comprehensive field documentation

  • Automatic serialization/deserialization

  • Validation and error handling

  • Default values for optional fields

  • Enum support for status and type fields

See also

  • config: Configuration management utilities

  • exceptions: Error handling for model validation

  • types: Type definitions and protocols

class Account(id, name, balance, canTrade, isVisible, simulated)[source]

Bases: object

Represents a trading account with balance and permissions.

id

Unique account identifier

Type:

int

name

Account name/label

Type:

str

balance

Current account balance in dollars

Type:

float

canTrade

Whether trading is enabled for this account

Type:

bool

isVisible

Whether the account is visible in the interface

Type:

bool

simulated

Whether this is a simulated/demo account

Type:

bool

Example

>>> print(f"Account: {account.name}")
>>> print(f"Balance: ${account.balance:,.2f}")
>>> print(f"Trading enabled: {account.canTrade}")
id: int
name: str
balance: float
canTrade: bool
isVisible: bool
simulated: bool
__init__(id, name, balance, canTrade, isVisible, simulated)
class BracketOrderResponse(success, entry_order_id, stop_order_id, target_order_id, entry_price, stop_loss_price, take_profit_price, entry_response, stop_response, target_response, error_message)[source]

Bases: object

Response from placing a bracket order with entry, stop loss, and take profit.

success

Whether the bracket order was successfully placed

Type:

bool

entry_order_id

ID of the entry order

Type:

Optional[int]

stop_order_id

ID of the stop loss order

Type:

Optional[int]

target_order_id

ID of the take profit order

Type:

Optional[int]

entry_price

Entry price used

Type:

float

stop_loss_price

Stop loss price used

Type:

float

take_profit_price

Take profit price used

Type:

float

entry_response

Response from entry order

Type:

OrderPlaceResponse

stop_response

Response from stop loss order

Type:

Optional[OrderPlaceResponse]

target_response

Response from take profit order

Type:

Optional[OrderPlaceResponse]

error_message

Error message if bracket order failed

Type:

Optional[str]

Example

>>> if response.success:
...     print(f"Bracket order placed successfully:")
...     print(f"  Entry: {response.entry_order_id} @ ${response.entry_price}")
...     print(f"  Stop: {response.stop_order_id} @ ${response.stop_loss_price}")
...     print(
...         f"  Target: {response.target_order_id} @ ${response.take_profit_price}"
...     )
... else:
...     print(f"Bracket order failed: {response.error_message}")
success: bool
entry_order_id: int | None
stop_order_id: int | None
target_order_id: int | None
entry_price: float
stop_loss_price: float
take_profit_price: float
entry_response: OrderPlaceResponse | None
stop_response: OrderPlaceResponse | None
target_response: OrderPlaceResponse | None
error_message: str | None
__init__(success, entry_order_id, stop_order_id, target_order_id, entry_price, stop_loss_price, take_profit_price, entry_response, stop_response, target_response, error_message)
class Instrument(id, name, description, tickSize, tickValue, activeContract, symbolId=None)[source]

Bases: object

Represents a tradeable financial instrument/contract.

id

Unique contract identifier used in API calls

Type:

str

name

Contract name/symbol (e.g., “MGCH25”)

Type:

str

description

Human-readable description of the contract

Type:

str

tickSize

Minimum price movement (e.g., 0.1)

Type:

float

tickValue

Dollar value per tick movement

Type:

float

activeContract

Whether the contract is currently active for trading

Type:

bool

Example

>>> print(f"Trading {instrument.name}")
>>> print(
...     f"Tick size: ${instrument.tickSize}, Tick value: ${instrument.tickValue}"
... )
id: str
name: str
description: str
tickSize: float
tickValue: float
activeContract: bool
symbolId: str | None = None
__init__(id, name, description, tickSize, tickValue, activeContract, symbolId=None)
class MarketDataEvent(contractId, lastPrice, bid, ask, volume, timestamp)[source]

Bases: object

contractId: str
lastPrice: float
bid: float | None
ask: float | None
volume: int | None
timestamp: str
__init__(contractId, lastPrice, bid, ask, volume, timestamp)
class Order(id, accountId, contractId, creationTimestamp, updateTimestamp, status, type, side, size, symbolId=None, fillVolume=None, limitPrice=None, stopPrice=None, filledPrice=None, customTag=None)[source]

Bases: object

Represents a trading order with all its details.

id

Unique order identifier

Type:

int

accountId

Account that placed the order

Type:

int

contractId

Contract being traded

Type:

str

symbolId

Symbol ID corresponding to the contract

Type:

Optional[str]

creationTimestamp

When the order was created (ISO format)

Type:

str

updateTimestamp

When the order was last updated

Type:

Optional[str]

status

Order status code (OrderStatus enum): 0=None, 1=Open, 2=Filled, 3=Cancelled, 4=Expired, 5=Rejected, 6=Pending

Type:

int

type

Order type (OrderType enum): 0=Unknown, 1=Limit, 2=Market, 3=StopLimit, 4=Stop, 5=TrailingStop, 6=JoinBid, 7=JoinAsk

Type:

int

side

Order side (OrderSide enum): 0=Bid, 1=Ask

Type:

int

size

Number of contracts

Type:

int

fillVolume

Number of contracts filled (partial fills)

Type:

Optional[int]

limitPrice

Limit price (for limit orders)

Type:

Optional[float]

stopPrice

Stop price (for stop orders)

Type:

Optional[float]

filledPrice

The price at which the order was filled, if any

Type:

Optional[float]

customTag

Custom tag associated with the order, if any

Type:

Optional[str]

Example

>>> side_str = "Bid" if order.side == 0 else "Ask"
>>> print(f"Order {order.id}: {side_str} {order.size} {order.contractId}")
id: int
accountId: int
contractId: str
creationTimestamp: str
updateTimestamp: str | None
status: int
type: int
side: int
size: int
symbolId: str | None = None
fillVolume: int | None = None
limitPrice: float | None = None
stopPrice: float | None = None
filledPrice: float | None = None
customTag: str | None = None
property is_open: bool

Check if order is still open.

property is_filled: bool

Check if order is completely filled.

property is_cancelled: bool

Check if order was cancelled.

property is_rejected: bool

Check if order was rejected.

property is_working: bool

Check if order is working (open or pending).

property is_terminal: bool

Check if order is in a terminal state.

property is_buy: bool

Check if this is a buy order.

property is_sell: bool

Check if this is a sell order.

property side_str: str

Get order side as string.

property type_str: str

Get order type as string.

property status_str: str

Get order status as string.

property filled_percent: float

Get percentage of order that has been filled.

property remaining_size: int

Get remaining unfilled size.

property symbol: str

Extract symbol from contract ID.

__init__(id, accountId, contractId, creationTimestamp, updateTimestamp, status, type, side, size, symbolId=None, fillVolume=None, limitPrice=None, stopPrice=None, filledPrice=None, customTag=None)
class OrderPlaceResponse(orderId, success, errorCode, errorMessage)[source]

Bases: object

Response from placing an order.

orderId

ID of the newly created order

Type:

int

success

Whether the order placement was successful

Type:

bool

errorCode

Error code (0 = success)

Type:

int

errorMessage

Error message if placement failed

Type:

Optional[str]

Example

>>> if response.success:
...     print(f"Order placed successfully with ID: {response.orderId}")
... else:
...     print(f"Order failed: {response.errorMessage}")
orderId: int
success: bool
errorCode: int
errorMessage: str | None
__init__(orderId, success, errorCode, errorMessage)
class OrderUpdateEvent(orderId, status, fillVolume, updateTimestamp)[source]

Bases: object

orderId: int
status: int
fillVolume: int | None
updateTimestamp: str
__init__(orderId, status, fillVolume, updateTimestamp)
class Position(id, accountId, contractId, creationTimestamp, type, size, averagePrice)[source]

Bases: object

Represents an open trading position.

id

Unique position identifier

Type:

int

accountId

Account holding the position

Type:

int

contractId

Contract of the position

Type:

str

creationTimestamp

When the position was opened (ISO format)

Type:

str

type

Position type code (PositionType enum): 0=UNDEFINED, 1=LONG, 2=SHORT

Type:

int

size

Position size (number of contracts, always positive)

Type:

int

averagePrice

Average entry price of the position

Type:

float

Note

This model contains only the fields returned by ProjectX API. For P&L calculations, use PositionManager.calculate_position_pnl() method.

Example

>>> direction = "LONG" if position.type == PositionType.LONG else "SHORT"
>>> print(
...     f"{direction} {position.size} {position.contractId} @ ${position.averagePrice}"
... )
id: int
accountId: int
contractId: str
creationTimestamp: str
type: int
size: int
averagePrice: float
property is_long: bool

Check if this is a long position.

property is_short: bool

Check if this is a short position.

property direction: str

Get position direction as string.

property symbol: str

Extract symbol from contract ID (e.g., ‘MNQ’ from ‘CON.F.US.MNQ.H25’).

property signed_size: int

Get size with sign (negative for short positions).

property total_cost: float

Calculate total position cost.

unrealized_pnl(current_price, tick_value=1.0)[source]

Calculate unrealized P&L given current price.

Parameters:
  • current_price (float) – Current market price

  • tick_value (float) – Value per point move (default: 1.0)

Return type:

float

Returns:

Unrealized P&L in dollars

__init__(id, accountId, contractId, creationTimestamp, type, size, averagePrice)
class PositionUpdateEvent(positionId, contractId, size, averagePrice, updateTimestamp)[source]

Bases: object

positionId: int
contractId: str
size: int
averagePrice: float
updateTimestamp: str
__init__(positionId, contractId, size, averagePrice, updateTimestamp)
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: object

Configuration 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

api_url

Base URL for the API endpoints

Type:

str

realtime_url

URL for real-time WebSocket connections

Type:

str

user_hub_url

URL for user hub WebSocket (accounts, positions, orders)

Type:

str

market_hub_url

URL for market hub WebSocket (quotes, trades, depth)

Type:

str

timezone

Timezone for timestamp handling

Type:

str

timeout_seconds

Request timeout in seconds

Type:

int

retry_attempts

Number of retry attempts for failed requests

Type:

int

retry_delay_seconds

Delay between retry attempts

Type:

float

requests_per_minute

Rate limiting - requests per minute

Type:

int

burst_limit

Rate limiting - burst limit

Type:

int

api_url: str = 'https://api.topstepx.com/api'
realtime_url: str = 'wss://realtime.topstepx.com/api'
user_hub_url: str = 'https://rtc.topstepx.com/hubs/user'
market_hub_url: str = 'https://rtc.topstepx.com/hubs/market'
timezone: str = 'America/Chicago'
timeout_seconds: int = 30
retry_attempts: int = 3
retry_delay_seconds: float = 2.0
requests_per_minute: int = 60
burst_limit: int = 10
__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)
class Trade(id, accountId, contractId, creationTimestamp, price, profitAndLoss, fees, side, size, voided, orderId)[source]

Bases: object

Represents an executed trade with P&L information.

id

Unique trade identifier

Type:

int

accountId

Account that executed the trade

Type:

int

contractId

Contract that was traded

Type:

str

creationTimestamp

When the trade was executed (ISO format)

Type:

str

price

Execution price

Type:

float

profitAndLoss

Realized P&L (None for half-turn trades)

Type:

Optional[float]

fees

Trading fees/commissions

Type:

float

side

Trade side: 0=Buy, 1=Sell

Type:

int

size

Number of contracts traded

Type:

int

voided

Whether the trade was voided/cancelled

Type:

bool

orderId

ID of the order that generated this trade

Type:

int

Note

A profitAndLoss value of None indicates a “half-turn” trade, meaning this trade opened or added to a position rather than closing it.

Example

>>> side_str = "Buy" if trade.side == 0 else "Sell"
>>> pnl_str = f"${trade.profitAndLoss}" if trade.profitAndLoss else "Half-turn"
>>> print(f"{side_str} {trade.size} @ ${trade.price} - P&L: {pnl_str}")
id: int
accountId: int
contractId: str
creationTimestamp: str
price: float
profitAndLoss: float | None
fees: float
side: int
size: int
voided: bool
orderId: int
__init__(id, accountId, contractId, creationTimestamp, price, profitAndLoss, fees, side, size, voided, orderId)

Configuration

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: object

Configuration 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

api_url

Base URL for the API endpoints

Type:

str

realtime_url

URL for real-time WebSocket connections

Type:

str

user_hub_url

URL for user hub WebSocket (accounts, positions, orders)

Type:

str

market_hub_url

URL for market hub WebSocket (quotes, trades, depth)

Type:

str

timezone

Timezone for timestamp handling

Type:

str

timeout_seconds

Request timeout in seconds

Type:

int

retry_attempts

Number of retry attempts for failed requests

Type:

int

retry_delay_seconds

Delay between retry attempts

Type:

float

requests_per_minute

Rate limiting - requests per minute

Type:

int

burst_limit

Rate limiting - burst limit

Type:

int

api_url: str = 'https://api.topstepx.com/api'
realtime_url: str = 'wss://realtime.topstepx.com/api'
user_hub_url: str = 'https://rtc.topstepx.com/hubs/user'
market_hub_url: str = 'https://rtc.topstepx.com/hubs/market'
timezone: str = 'America/Chicago'
timeout_seconds: int = 30
retry_attempts: int = 3
retry_delay_seconds: float = 2.0
requests_per_minute: int = 60
burst_limit: int = 10
__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)

Client Models

class Account(id, name, balance, canTrade, isVisible, simulated)[source]

Bases: object

Represents a trading account with balance and permissions.

id

Unique account identifier

Type:

int

name

Account name/label

Type:

str

balance

Current account balance in dollars

Type:

float

canTrade

Whether trading is enabled for this account

Type:

bool

isVisible

Whether the account is visible in the interface

Type:

bool

simulated

Whether this is a simulated/demo account

Type:

bool

Example

>>> print(f"Account: {account.name}")
>>> print(f"Balance: ${account.balance:,.2f}")
>>> print(f"Trading enabled: {account.canTrade}")
id: int
name: str
balance: float
canTrade: bool
isVisible: bool
simulated: bool
__init__(id, name, balance, canTrade, isVisible, simulated)
class Instrument(id, name, description, tickSize, tickValue, activeContract, symbolId=None)[source]

Bases: object

Represents a tradeable financial instrument/contract.

id

Unique contract identifier used in API calls

Type:

str

name

Contract name/symbol (e.g., “MGCH25”)

Type:

str

description

Human-readable description of the contract

Type:

str

tickSize

Minimum price movement (e.g., 0.1)

Type:

float

tickValue

Dollar value per tick movement

Type:

float

activeContract

Whether the contract is currently active for trading

Type:

bool

Example

>>> print(f"Trading {instrument.name}")
>>> print(
...     f"Tick size: ${instrument.tickSize}, Tick value: ${instrument.tickValue}"
... )
id: str
name: str
description: str
tickSize: float
tickValue: float
activeContract: bool
symbolId: str | None = None
__init__(id, name, description, tickSize, tickValue, activeContract, symbolId=None)

Trading Models

class Order(id, accountId, contractId, creationTimestamp, updateTimestamp, status, type, side, size, symbolId=None, fillVolume=None, limitPrice=None, stopPrice=None, filledPrice=None, customTag=None)[source]

Bases: object

Represents a trading order with all its details.

id

Unique order identifier

Type:

int

accountId

Account that placed the order

Type:

int

contractId

Contract being traded

Type:

str

symbolId

Symbol ID corresponding to the contract

Type:

Optional[str]

creationTimestamp

When the order was created (ISO format)

Type:

str

updateTimestamp

When the order was last updated

Type:

Optional[str]

status

Order status code (OrderStatus enum): 0=None, 1=Open, 2=Filled, 3=Cancelled, 4=Expired, 5=Rejected, 6=Pending

Type:

int

type

Order type (OrderType enum): 0=Unknown, 1=Limit, 2=Market, 3=StopLimit, 4=Stop, 5=TrailingStop, 6=JoinBid, 7=JoinAsk

Type:

int

side

Order side (OrderSide enum): 0=Bid, 1=Ask

Type:

int

size

Number of contracts

Type:

int

fillVolume

Number of contracts filled (partial fills)

Type:

Optional[int]

limitPrice

Limit price (for limit orders)

Type:

Optional[float]

stopPrice

Stop price (for stop orders)

Type:

Optional[float]

filledPrice

The price at which the order was filled, if any

Type:

Optional[float]

customTag

Custom tag associated with the order, if any

Type:

Optional[str]

Example

>>> side_str = "Bid" if order.side == 0 else "Ask"
>>> print(f"Order {order.id}: {side_str} {order.size} {order.contractId}")
id: int
accountId: int
contractId: str
creationTimestamp: str
updateTimestamp: str | None
status: int
type: int
side: int
size: int
symbolId: str | None = None
fillVolume: int | None = None
limitPrice: float | None = None
stopPrice: float | None = None
filledPrice: float | None = None
customTag: str | None = None
property is_open: bool

Check if order is still open.

property is_filled: bool

Check if order is completely filled.

property is_cancelled: bool

Check if order was cancelled.

property is_rejected: bool

Check if order was rejected.

property is_working: bool

Check if order is working (open or pending).

property is_terminal: bool

Check if order is in a terminal state.

property is_buy: bool

Check if this is a buy order.

property is_sell: bool

Check if this is a sell order.

property side_str: str

Get order side as string.

property type_str: str

Get order type as string.

property status_str: str

Get order status as string.

property filled_percent: float

Get percentage of order that has been filled.

property remaining_size: int

Get remaining unfilled size.

property symbol: str

Extract symbol from contract ID.

__init__(id, accountId, contractId, creationTimestamp, updateTimestamp, status, type, side, size, symbolId=None, fillVolume=None, limitPrice=None, stopPrice=None, filledPrice=None, customTag=None)
class OrderPlaceResponse(orderId, success, errorCode, errorMessage)[source]

Bases: object

Response from placing an order.

orderId

ID of the newly created order

Type:

int

success

Whether the order placement was successful

Type:

bool

errorCode

Error code (0 = success)

Type:

int

errorMessage

Error message if placement failed

Type:

Optional[str]

Example

>>> if response.success:
...     print(f"Order placed successfully with ID: {response.orderId}")
... else:
...     print(f"Order failed: {response.errorMessage}")
orderId: int
success: bool
errorCode: int
errorMessage: str | None
__init__(orderId, success, errorCode, errorMessage)
class BracketOrderResponse(success, entry_order_id, stop_order_id, target_order_id, entry_price, stop_loss_price, take_profit_price, entry_response, stop_response, target_response, error_message)[source]

Bases: object

Response from placing a bracket order with entry, stop loss, and take profit.

success

Whether the bracket order was successfully placed

Type:

bool

entry_order_id

ID of the entry order

Type:

Optional[int]

stop_order_id

ID of the stop loss order

Type:

Optional[int]

target_order_id

ID of the take profit order

Type:

Optional[int]

entry_price

Entry price used

Type:

float

stop_loss_price

Stop loss price used

Type:

float

take_profit_price

Take profit price used

Type:

float

entry_response

Response from entry order

Type:

OrderPlaceResponse

stop_response

Response from stop loss order

Type:

Optional[OrderPlaceResponse]

target_response

Response from take profit order

Type:

Optional[OrderPlaceResponse]

error_message

Error message if bracket order failed

Type:

Optional[str]

Example

>>> if response.success:
...     print(f"Bracket order placed successfully:")
...     print(f"  Entry: {response.entry_order_id} @ ${response.entry_price}")
...     print(f"  Stop: {response.stop_order_id} @ ${response.stop_loss_price}")
...     print(
...         f"  Target: {response.target_order_id} @ ${response.take_profit_price}"
...     )
... else:
...     print(f"Bracket order failed: {response.error_message}")
success: bool
entry_order_id: int | None
stop_order_id: int | None
target_order_id: int | None
entry_price: float
stop_loss_price: float
take_profit_price: float
entry_response: OrderPlaceResponse | None
stop_response: OrderPlaceResponse | None
target_response: OrderPlaceResponse | None
error_message: str | None
__init__(success, entry_order_id, stop_order_id, target_order_id, entry_price, stop_loss_price, take_profit_price, entry_response, stop_response, target_response, error_message)
class Position(id, accountId, contractId, creationTimestamp, type, size, averagePrice)[source]

Bases: object

Represents an open trading position.

id

Unique position identifier

Type:

int

accountId

Account holding the position

Type:

int

contractId

Contract of the position

Type:

str

creationTimestamp

When the position was opened (ISO format)

Type:

str

type

Position type code (PositionType enum): 0=UNDEFINED, 1=LONG, 2=SHORT

Type:

int

size

Position size (number of contracts, always positive)

Type:

int

averagePrice

Average entry price of the position

Type:

float

Note

This model contains only the fields returned by ProjectX API. For P&L calculations, use PositionManager.calculate_position_pnl() method.

Example

>>> direction = "LONG" if position.type == PositionType.LONG else "SHORT"
>>> print(
...     f"{direction} {position.size} {position.contractId} @ ${position.averagePrice}"
... )
id: int
accountId: int
contractId: str
creationTimestamp: str
type: int
size: int
averagePrice: float
property is_long: bool

Check if this is a long position.

property is_short: bool

Check if this is a short position.

property direction: str

Get position direction as string.

property symbol: str

Extract symbol from contract ID (e.g., ‘MNQ’ from ‘CON.F.US.MNQ.H25’).

property signed_size: int

Get size with sign (negative for short positions).

property total_cost: float

Calculate total position cost.

unrealized_pnl(current_price, tick_value=1.0)[source]

Calculate unrealized P&L given current price.

Parameters:
  • current_price (float) – Current market price

  • tick_value (float) – Value per point move (default: 1.0)

Return type:

float

Returns:

Unrealized P&L in dollars

__init__(id, accountId, contractId, creationTimestamp, type, size, averagePrice)
class Trade(id, accountId, contractId, creationTimestamp, price, profitAndLoss, fees, side, size, voided, orderId)[source]

Bases: object

Represents an executed trade with P&L information.

id

Unique trade identifier

Type:

int

accountId

Account that executed the trade

Type:

int

contractId

Contract that was traded

Type:

str

creationTimestamp

When the trade was executed (ISO format)

Type:

str

price

Execution price

Type:

float

profitAndLoss

Realized P&L (None for half-turn trades)

Type:

Optional[float]

fees

Trading fees/commissions

Type:

float

side

Trade side: 0=Buy, 1=Sell

Type:

int

size

Number of contracts traded

Type:

int

voided

Whether the trade was voided/cancelled

Type:

bool

orderId

ID of the order that generated this trade

Type:

int

Note

A profitAndLoss value of None indicates a “half-turn” trade, meaning this trade opened or added to a position rather than closing it.

Example

>>> side_str = "Buy" if trade.side == 0 else "Sell"
>>> pnl_str = f"${trade.profitAndLoss}" if trade.profitAndLoss else "Half-turn"
>>> print(f"{side_str} {trade.size} @ ${trade.price} - P&L: {pnl_str}")
id: int
accountId: int
contractId: str
creationTimestamp: str
price: float
profitAndLoss: float | None
fees: float
side: int
size: int
voided: bool
orderId: int
__init__(id, accountId, contractId, creationTimestamp, price, profitAndLoss, fees, side, size, voided, orderId)

Exception Classes

Base Exception

class ProjectXError(message, error_code=None, response_data=None)[source]

Bases: Exception

Base exception for ProjectX API errors.

__init__(message, error_code=None, response_data=None)[source]

Initialize ProjectX error.

Parameters:
  • message (str) – Error message

  • error_code (int | None) – Optional error code

  • response_data (dict[str, Any] | None) – Optional response data from API

API Exceptions

class ProjectXConnectionError(message, error_code=None, response_data=None)[source]

Bases: ProjectXError

Connection and network errors.

class ProjectXAuthenticationError(message, error_code=None, response_data=None)[source]

Bases: ProjectXError

Authentication-related errors.

class ProjectXServerError(message, error_code=None, response_data=None)[source]

Bases: ProjectXError

Server-side errors (5xx).

class ProjectXRateLimitError(message, error_code=None, response_data=None)[source]

Bases: ProjectXError

Rate limiting errors.

Data Exceptions

class ProjectXDataError(message, error_code=None, response_data=None)[source]

Bases: ProjectXError

Data validation and processing errors.

class ProjectXInstrumentError(message, error_code=None, response_data=None)[source]

Bases: ProjectXError

Instrument-related errors.

Trading Exceptions

class ProjectXOrderError(message, error_code=None, response_data=None)[source]

Bases: ProjectXError

Order placement and management errors.

class ProjectXPositionError(message, error_code=None, response_data=None)[source]

Bases: ProjectXError

Position management errors.