Market Data API
Real-time market data subscriptions and historical data retrieval.
Access via client.market_data.
MarketDataAPI
MarketDataAPI
Market data subscriptions and historical data.
Provides methods to subscribe to real-time market data (spots, trendbars,
depth of market) and retrieve historical data.
Example
# Subscribe to spot prices
await client.market_data.subscribe_spots(account_id, [270, 271])
# Handle spot events via decorator
@client.on(SpotEvent, symbol_id=270)
async def on_eurusd(event: SpotEvent) -> None:
print(f"EURUSD: {event.bid}/{event.ask}")
# Get historical candles
trendbars = await client.market_data.get_trendbars(
account_id,
symbol_id=270,
period=TrendbarPeriod.H1,
from_timestamp=start,
to_timestamp=end,
)
subscribe_spots(account_id, symbol_ids, timeout=None)
Subscribe to spot price updates.
After subscribing, spot events will be delivered via the event system.
Use @client.on(SpotEvent) to handle them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
account_id
|
int
|
The cTID trader account ID. |
required |
symbol_ids
|
list[int]
|
Symbols to subscribe to. |
required |
timeout
|
float | None
|
Request timeout (uses default if None). |
None
|
Raises:
| Type | Description |
|---|---|
APIError
|
If request fails. |
CTraderConnectionTimeoutError
|
If request times out. |
unsubscribe_spots(account_id, symbol_ids, timeout=None)
Unsubscribe from spot price updates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
account_id
|
int
|
The cTID trader account ID. |
required |
symbol_ids
|
list[int]
|
Symbols to unsubscribe from. |
required |
timeout
|
float | None
|
Request timeout (uses default if None). |
None
|
Raises:
| Type | Description |
|---|---|
APIError
|
If request fails. |
CTraderConnectionTimeoutError
|
If request times out. |
subscribe_trendbars(account_id, symbol_id, period, timeout=None)
Subscribe to live trendbar (candle) updates.
Requires subscribing to spots for the same symbol beforehand.
After subscribing, trendbar data will be delivered via the event system inside the SpotEvent object.
Use @client.on(SpotEvent) to handle them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
account_id
|
int
|
The cTID trader account ID. |
required |
symbol_id
|
int
|
Symbol to subscribe to. |
required |
period
|
TrendbarPeriod
|
Trendbar period (M1, H1, D1, etc.). |
required |
timeout
|
float | None
|
Request timeout (uses default if None). |
None
|
Raises:
| Type | Description |
|---|---|
APIError
|
If request fails. |
CTraderConnectionTimeoutError
|
If request times out. |
unsubscribe_trendbars(account_id, symbol_id, period, timeout=None)
Unsubscribe from live trendbar updates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
account_id
|
int
|
The cTID trader account ID. |
required |
symbol_id
|
int
|
Symbol to unsubscribe from. |
required |
period
|
TrendbarPeriod
|
Trendbar period. |
required |
timeout
|
float | None
|
Request timeout (uses default if None). |
None
|
Raises:
| Type | Description |
|---|---|
APIError
|
If request fails. |
CTraderConnectionTimeoutError
|
If request times out. |
subscribe_depth(account_id, symbol_ids, timeout=None)
Subscribe to depth of market (order book) updates.
After subscribing, depth events will be delivered via the event system.
Use @client.on(DepthEvent) to handle them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
account_id
|
int
|
The cTID trader account ID. |
required |
symbol_ids
|
list[int]
|
Symbols to subscribe to. |
required |
timeout
|
float | None
|
Request timeout (uses default if None). |
None
|
Raises:
| Type | Description |
|---|---|
APIError
|
If request fails. |
CTraderConnectionTimeoutError
|
If request times out. |
unsubscribe_depth(account_id, symbol_ids, timeout=None)
Unsubscribe from depth of market updates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
account_id
|
int
|
The cTID trader account ID. |
required |
symbol_ids
|
list[int]
|
Symbols to unsubscribe from. |
required |
timeout
|
float | None
|
Request timeout (uses default if None). |
None
|
Raises:
| Type | Description |
|---|---|
APIError
|
If request fails. |
CTraderConnectionTimeoutError
|
If request times out. |
get_trendbars(account_id, symbol_id, period, from_timestamp, to_timestamp, timeout=None)
Get historical trendbars (candles).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
account_id
|
int
|
The cTID trader account ID. |
required |
symbol_id
|
int
|
Symbol to get data for. |
required |
period
|
TrendbarPeriod
|
Trendbar period (M1, H1, D1, etc.). |
required |
from_timestamp
|
datetime
|
Start of time range (inclusive). |
required |
to_timestamp
|
datetime
|
End of time range (inclusive). |
required |
timeout
|
float | None
|
Request timeout (uses default if None). |
None
|
Returns:
| Type | Description |
|---|---|
list[Trendbar]
|
List of Trendbar objects, ordered by timestamp ascending. |
Note
The server may limit the number of bars returned per request.
For large ranges, consider paginating with smaller time windows.
Raises:
| Type | Description |
|---|---|
APIError
|
If request fails. |
CTraderConnectionTimeoutError
|
If request times out. |
get_tick_data(account_id, symbol_id, from_timestamp, to_timestamp, quote_type='BID', timeout=None)
Get historical tick data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
account_id
|
int
|
The cTID trader account ID. |
required |
symbol_id
|
int
|
Symbol to get data for. |
required |
from_timestamp
|
datetime
|
Start of time range (inclusive). |
required |
to_timestamp
|
datetime
|
End of time range (inclusive). |
required |
quote_type
|
str
|
"BID" or "ASK". |
'BID'
|
timeout
|
float | None
|
Request timeout (uses default if None). |
None
|
Returns:
| Type | Description |
|---|---|
Sequence[TickData]
|
List of TickData objects, ordered by newest first. |
Note
Tick data can be voluminous. Use small time windows to avoid
timeout issues and excessive memory usage.
Raises:
| Type | Description |
|---|---|
APIError
|
If request fails. |
CTraderConnectionTimeoutError
|
If request times out. |
Usage Examples
Subscribe to Spot Prices
from ctrader_api_client.events import SpotEvent
# Subscribe to symbols
await client.market_data.subscribe_spots(account_id, [270, 271])
# Handle price updates - bid/ask are floats
@client.on(SpotEvent, symbol_id=270)
async def on_price(event: SpotEvent):
print(f"Bid: {event.bid}, Ask: {event.ask}")
Subscribe to Live Trendbars
from ctrader_api_client.events import SpotEvent
from ctrader_api_client.enums import TrendbarPeriod
# Subscribe to M1 trendbars
await client.market_data.subscribe_trendbars(account_id, symbol_id=270, period=TrendbarPeriod.M1)
# Trendbar data is delivered inside SpotEvent
@client.on(SpotEvent, symbol_id=270)
async def on_spot(event: SpotEvent):
print(f"Price: {event.bid}/{event.ask}")
# Check if this event contains trendbar data
if event.trendbar:
bar = event.trendbar
print(f"Bar: O={bar.open} H={bar.high} L={bar.low} C={bar.close} V={bar.volume}")
Subscribe to Depth of Market
from ctrader_api_client.events import DepthEvent
# Subscribe to order book
await client.market_data.subscribe_depth(account_id, symbol_id=270)
@client.on(DepthEvent, symbol_id=270)
async def on_depth(event: DepthEvent):
for quote in event.new_quotes:
side = "BID" if quote.is_bid else "ASK"
print(f"{side}: {quote.price} x {quote.size}")
Get Historical Trendbars
from datetime import datetime, timedelta, UTC
from ctrader_api_client.enums import TrendbarPeriod
trendbars = await client.market_data.get_trendbars(
account_id,
symbol_id=270,
period=TrendbarPeriod.H1,
from_timestamp=datetime.now(UTC) - timedelta(days=7),
to_timestamp=datetime.now(UTC),
)
# OHLC values are already floats (converted from raw integers)
for bar in trendbars:
print(f"{bar.timestamp}: O={bar.open} H={bar.high} L={bar.low} C={bar.close} V={bar.volume}")
Get Tick Data
from datetime import datetime, timedelta, UTC
ticks = await client.market_data.get_tick_data(
account_id,
symbol_id=270,
from_timestamp=datetime.now(UTC) - timedelta(hours=1),
to_timestamp=datetime.now(UTC),
quote_type="BID", # or "ASK"
)
# Price is already a float
for tick in ticks:
print(f"{tick.timestamp}: {tick.price}")
Unsubscribe
# Unsubscribe from spots
await client.market_data.unsubscribe_spots(account_id, [270])
# Unsubscribe from trendbars
await client.market_data.unsubscribe_trendbars(
account_id,
symbol_id=270,
period=TrendbarPeriod.M1,
)
# Unsubscribe from depth
await client.market_data.unsubscribe_depth(account_id, symbol_id=270)
Note on Subscriptions
Subscriptions are not automatically restored after reconnection.
It is recommended to use ReadyEvent to keep all subscriptions centralized in one place and ensure they are re-established after any disconnects.
from ctrader_api_client.events import ReadyEvent
from ctrader_api_client.enums import TrendbarPeriod
@client.on(ReadyEvent)
async def on_ready(event: ReadyEvent):
# This runs on initial auth AND after reconnection
await client.market_data.subscribe_spots(event.account_id, [270, 271])
await client.market_data.subscribe_trendbars(event.account_id, 270, TrendbarPeriod.M1)