Skip to main content
A market on T+ is a tradeable asset — each asset listed in the T+ registry has a corresponding market with its own order book, price and quantity decimal precision, and real-time data feeds. You interact with markets through two clients: OrderBookClient for authenticated operations (including market creation and user-specific data) and MarketDataClient for read-only public market data such as order book snapshots, klines, and public trades.

Getting Market Details

Before placing any order, fetch the Market object for the asset you want to trade. It contains the decimal precision you need to convert human-readable amounts to book-native integers.
import asyncio
from tplus.client import OrderBookClient
from tplus.model.asset_identifier import AssetIdentifier
from tplus.utils.user import load_user

asset = AssetIdentifier(200)

async def main():
    async with OrderBookClient(user=load_user("alice"), base_url="http://127.0.0.1:8000") as client:
        market = await client.get_market(asset)
        print(f"Price decimals:    {market.book_price_decimals}")
        print(f"Quantity decimals: {market.book_quantity_decimals}")

asyncio.run(main())
book_price_decimals and book_quantity_decimals define the scale of integer values on the book. For example, if book_price_decimals is 6, a book price of 1_500_000 represents a human-readable price of 1.50.
Cache the Market object for each asset rather than re-fetching it on every order. The decimal precision for a given market does not change during normal operations.

Listing All Markets

# Returns a list of all active markets
markets = await client.get_markets()
for m in markets:
    print(m)
Or from the CLI:
tplus markets list
tplus markets get 200

Order Book Snapshots

Use MarketDataClient to fetch a point-in-time snapshot of the order book. The snapshot includes all current bids and asks along with a sequence_number that you can use to synchronise with the real-time depth stream.
import asyncio
from tplus.client import MarketDataClient
from tplus.model.asset_identifier import AssetIdentifier

asset = AssetIdentifier(200)

async def main():
    async with MarketDataClient(base_url="http://localhost:8011") as md_client:
        snapshot = await md_client.get_orderbook_snapshot(asset)
        print(f"Sequence number: {snapshot.sequence_number}")
        print(f"Best bid: {snapshot.bids[0] if snapshot.bids else 'empty'}")
        print(f"Best ask: {snapshot.asks[0] if snapshot.asks else 'empty'}")

asyncio.run(main())
MarketDataClient is a read-only, unauthenticated client. Its default base URL is http://localhost:8011, matching the local market-data-service.

Streaming Depth Updates

For real-time order book maintenance, stream incremental depth diffs and apply them on top of a snapshot:
from tplus.model.orderbook import OrderBookDiff

async for diff in md_client.stream_depth(asset):
    if isinstance(diff, OrderBookDiff):
        print(f"Seq={diff.sequence_number}, asks={len(diff.asks)}, bids={len(diff.bids)}")
Or from the CLI:
tplus markets depth 200
tplus stream depth 200

Klines (Candlestick Data)

Retrieve historical OHLCV candlestick data for charting and strategy backtesting:
async with MarketDataClient(base_url="http://localhost:8011") as md_client:
    klines = await md_client.get_klines(asset)
    for k in klines:
        print(k)
You can also stream klines in real time as new candles close:
async for kline_update in md_client.stream_klines(asset):
    print(kline_update)
CLI equivalent:
tplus markets klines 200
tplus markets klines 200 --page 2 --limit 100
tplus stream klines 200

24-Hour Ticker

Get a 24-hour rolling summary — including open, high, low, close, and volume — for a single asset or all assets at once:
# Single asset ticker
ticker = await md_client.get_ticker(asset)
print(ticker)

# All asset tickers
tickers = await md_client.get_tickers()

Public Trade History

Fetch recent public trades (all participants, no authentication required):
# All recent public trades across all markets
trades = await md_client.get_trades()

# Trades for a specific asset
asset_trades = await md_client.get_trades_for_asset(asset)
for trade in asset_trades:
    print(f"Price: {trade.price}, Qty: {trade.quantity}")
Stream finalized trades in real time:
from tplus.model.trades import Trade

async for trade in md_client.stream_finalized_trades():
    if isinstance(trade, Trade):
        print(f"Trade ID: {trade.trade_id}, Price: {trade.price}, Qty: {trade.quantity}")
CLI equivalent:
tplus trades list
tplus trades list --asset 200
tplus stream trades

Error Handling

Market data queries raise specific exceptions from tplus.exceptions:
from tplus import NotFoundError, RateLimitError, ServerError
from tplus.model.asset_identifier import AssetIdentifier

asset = AssetIdentifier(99999)  # non-existent market

try:
    market = await client.get_market(asset)
except NotFoundError:
    print("Market not found for this asset ID")
except RateLimitError:
    print("Rate limited — back off and retry")
except ServerError as err:
    print(f"Server error: {err}")
Some methods return empty results rather than raising NotFoundError when a resource is absent. For example, get_user_orders() returns ([], {}) for an unknown user. Check the method’s return type before assuming an exception will be raised.

Data Clients at a Glance

OrderBookClient

Authenticated. Use for market creation, fetching market details, and all user-specific queries. Requires a User object.
from tplus.client import OrderBookClient

MarketDataClient

Unauthenticated. Use for public market data: snapshots, klines, tickers, public trades, and their WebSocket streams. No User needed.
from tplus.client import MarketDataClient