Skip to content

Events

The client uses an event-driven architecture. Register handlers with @client.on() to receive real-time updates.

Registering Handlers

from ctrader_api_client.events import SpotEvent, ExecutionEvent

@client.on(SpotEvent, symbol_id=270)  # Filter by symbol
async def on_spot(event: SpotEvent):
    print(f"{event.bid}/{event.ask}")


@client.on(ExecutionEvent, account_id=12345)  # Filter by account
async def on_execution(event: ExecutionEvent):
    print(f"Order {event.order_id}: {event.execution_type}")

Filtering

Different events support different filters:

Event account_id symbol_id
SpotEvent Yes Yes
ExecutionEvent Yes Yes
DepthEvent Yes Yes
ReadyEvent Yes No
OrderErrorEvent Yes No
TraderUpdateEvent Yes No
MarginChangeEvent Yes No
ReconnectedEvent No No
ClientDisconnectEvent No No

Using an unsupported filter raises ValueError at registration time.

Market Data Events

SpotEvent

Price tick event.

Emitted when bid/ask prices update for a subscribed symbol.

Attributes:

Name Type Description
account_id int

The cTID trader account ID.

symbol_id int

The symbol identifier.

bid float | None

Current bid price

ask float | None

Current ask price

trendbar Trendbar | None

Live trend bar. Only populated if subscribed to trendbar updates via MarketDataAPI.subscribe_trendbars

timestamp datetime

Server timestamp of the tick.

SpotEvent contains live trendbar data when subscribed:

from ctrader_api_client.enums import TrendbarPeriod

# Subscribe to both spot prices and M1 trendbars
await client.market_data.subscribe_spots(account_id, [270])
await client.market_data.subscribe_trendbars(account_id, 270, TrendbarPeriod.M1)

@client.on(SpotEvent, symbol_id=270)
async def on_spot(event: SpotEvent):
    # Prices are floats
    print(f"Bid: {event.bid}, Ask: {event.ask}")

    # Trendbar is included when subscribed
    if event.trendbar:
        bar = event.trendbar
        print(f"Candle: O={bar.open} H={bar.high} L={bar.low} C={bar.close}")

DepthEvent

Market depth (order book) event.

Emitted when the order book updates for a subscribed symbol.

Attributes:

Name Type Description
account_id int

The cTID trader account ID.

symbol_id int

The symbol identifier.

new_quotes tuple[DepthQuote, ...]

New or updated quotes.

deleted_quote_ids tuple[int, ...]

IDs of quotes that were removed.

DepthQuote

Single depth of market quote.

Attributes:

Name Type Description
quote_id int

Unique identifier for the quote (used for updates/deletions).

price int

Quote price (raw integer, divide by 10^priceDigits).

size int

Quote size (volume in cents).

is_bid bool

True if this is a bid quote, False if it's an ask quote.

Trading Events

ExecutionEvent

Order execution event.

Emitted when an order is accepted, filled, modified, canceled, etc.

Attributes:

Name Type Description
account_id int

The cTID trader account ID.

execution_type ExecutionType

Type of execution (fill, cancel, etc.).

order_id int

The order identifier.

position_id int | None

The position identifier (if applicable).

symbol_id int

The symbol identifier.

side OrderSide

Order side (buy/sell).

filled_volume int | None

Volume filled in this execution (in cents).

fill_price Decimal | None

Execution price (if filled).

timestamp datetime

Server timestamp of the execution.

is_server_event bool

True if generated by server (e.g., stop-out).

error_code str | None

Error code if execution failed.

OrderErrorEvent

Order error event.

Emitted when an order operation fails.

Attributes:

Name Type Description
account_id int

The cTID trader account ID.

order_id int | None

The order identifier (if available).

position_id int | None

The position identifier (if available).

error_code str

The error code from the server.

description str

Human-readable error description.

Account Events

ReadyEvent

Emitted when an account is authenticated and ready for use.

Fired after both initial authentication and reconnection re-authentication.
Use this to set up subscriptions that should persist across reconnections.

Attributes:

Name Type Description
account_id int

The cTID trader account ID that is now ready.

is_reconnect bool

True if this follows a reconnection, False for initial auth.

Use this to set up subscriptions that persist across reconnections:

@client.on(ReadyEvent)
async def on_ready(event: ReadyEvent):
    await client.market_data.subscribe_spots(event.account_id, [270])

    if event.is_reconnect:
        print("Connection restored!")

TraderUpdateEvent

Trader account update event.

Emitted when account information changes (balance, leverage, etc.).

Attributes:

Name Type Description
account_id int

The cTID trader account ID.

balance int

Current account balance (raw, divide by 10^moneyDigits).

leverage_in_cents int | None

Account leverage in cents (5000 = 1:50).

money_digits int

Exponent for monetary values.

MarginChangeEvent

Position margin change event.

Emitted when the margin allocated to a position changes.

Attributes:

Name Type Description
account_id int

The cTID trader account ID.

position_id int

The position identifier.

used_margin int

New margin value (raw, divide by 10^moneyDigits).

money_digits int

Exponent for monetary values.

MarginCallTriggerEvent

Margin call triggered event.

Emitted when account margin level reaches a configured threshold.
Sent at most once every 10 minutes per threshold to avoid spam.

Attributes:

Name Type Description
account_id int

The cTID trader account ID.

margin_call_type int

Type of margin call (1, 2, or 3 for different thresholds).

margin_level_threshold Decimal

The threshold that was breached (percentage).

PnLChangeEvent

Unrealized PnL change event.

Emitted when unrealized profit/loss changes due to market movement.
Requires subscription via ProtoOAv1PnLChangeSubscribeReq.

Attributes:

Name Type Description
account_id int

The cTID trader account ID.

gross_unrealized_pnl int

Gross unrealized PnL (raw, divide by 10^moneyDigits).

net_unrealized_pnl int

Net unrealized PnL (raw, divide by 10^moneyDigits).

money_digits int

Exponent for monetary values.

TrailingStopChangedEvent

Trailing stop loss level changed event.

Emitted when a trailing stop loss price is updated due to
favorable price movement.

Attributes:

Name Type Description
account_id int

The cTID trader account ID.

position_id int

The position identifier.

order_id int

The stop loss order identifier.

stop_price Decimal

New stop loss price.

timestamp datetime

Server timestamp of the update.

Connection Events

ReconnectedEvent

Emitted after automatic reconnection and re-authentication.

When a connection is lost and automatically restored, the client
re-authenticates the app and all previously authenticated accounts.
Subscriptions (spots, trendbars, depth) are NOT automatically restored
and should be handled using ReadyEvent instead.
Use this event for any custom logic that depends on reconnection, such as logging or alerting.

Attributes:

Name Type Description
app_auth_restored bool

Whether app authentication succeeded.

restored_accounts tuple[int, ...]

Account IDs that were successfully re-authenticated.

failed_accounts tuple[tuple[int, str], ...]

Accounts that failed, as (account_id, error_message) tuples.

Example:

@client.on(ReconnectedEvent)
async def on_reconnected(event: ReconnectedEvent):
    print(f"Reconnected! App auth: {event.app_auth_restored}")
    print(f"Restored accounts: {event.restored_accounts}")
    if event.failed_accounts:
        print(f"Failed accounts: {event.failed_accounts}")

ClientDisconnectEvent

Client disconnect event.

Emitted when the server terminates the client connection.

Attributes:

Name Type Description
reason str

Reason for disconnection.

AccountDisconnectEvent

Account disconnect event.

Emitted when a specific account session is terminated.

Attributes:

Name Type Description
account_id int

The cTID trader account ID.

TokenInvalidatedEvent

Token invalidated event.

Emitted when access tokens are revoked or expired.

Attributes:

Name Type Description
account_ids tuple[int, ...]

List of affected account IDs.

reason str

Reason for invalidation.

Symbol Events

SymbolChangedEvent

Symbol configuration changed event.

Emitted when a symbol's configuration is updated (trading hours,
margin requirements, spreads, etc.).

Attributes:

Name Type Description
account_id int

The cTID trader account ID.

symbol_ids tuple[int, ...]

List of symbol IDs that changed.

Unregistering Handlers

@client.on(SpotEvent)
async def my_handler(event: SpotEvent):
    ...

# Later, unregister
client.off(SpotEvent, my_handler)