Available symbols

Discover available symbols and their configuration through the Python SDK.

HTTP endpoints on this page

  • GET/data/calibrated-data

Parameters and response shapes for each are in the API reference.

Use client.data.calibrated_data() to retrieve the instruments that are already calibrated, and therefore simulatable, with their available dates, trading parameters and volume statistics. This is the list to drive a symbol picker from. It also accepts optional filters, so you can ask for one symbol, one exchange, or one date instead of the whole catalog.

The endpoint only ever returns calibrated instrument-days — it filters on pipeline state server-side. So there is no status or stage for you to check: if a date is in the response, you can simulate it. Those two fields are reported for provenance, and always read complete / model_calibration.

Get available symbols

data.calibrated_data(symbol=None, q=None, exchange=None, provider=None, date=None, limit=None, offset=None)Return the calibrated instruments, with their dates, trading parameters and volume statistics.Any tier

Called with no arguments it returns the whole catalog, which is large. Every filter narrows it server-side, and they combine with AND.

Parameters

symbol : str, optional
Exact ticker, e.g. "700.HK". Not a prefix or substring match — use q for that.
q : str, optional
Case-insensitive substring match over the ticker and the company name — the search a symbol picker needs. "angl" finds ANGLO AMERICAN.
exchange : str, optional
Exchange protocol, e.g. "hkex_securities". The same spelling simulation.run() takes.
provider : str, optional
Data provider, e.g. "omd" or "bmll". Pass it alongside symbol whenever you need one specific row — see the note below.
date : str, optional
Calibration date "YYYY-MM-DD". Keeps only symbols calibrated on it, and also narrows each symbol's available_dates to that date — so the two averages then describe that date alone rather than the symbol's whole history.
limit : int, optional
Maximum symbols to return, 1–1000.
offset : int, optional
Symbols to skip, for paging alongside limit.

Returns

dict

{total, limit, offset, symbols} — the same envelope as data.available_data(). total is the match count before paging, so offset + len(symbols) < total means a limit truncated the result. Each entry in symbols is one instrument, carrying every calibrated date for it:

symbol : str
Symbol ticker, e.g. 700.HK.
company_name : str or None
Company name, e.g. KUAISHOU-W. None where the provider reports no company name, so always fall back to symbol.
provider : str
Data provider the row was sourced from.
exchange : str
Exchange protocol.
instrument_type : {"equity", "derivative"}
Type of instrument.
currency : str
Trading currency, e.g. HKD.
tick_size : float
Minimum price increment.
lot_size : int
Minimum order size. Multiply an execution algorithm's order_size, which is denominated in lots, by this to reason in shares.
available_dates : list of dict
Per-date calibration records: date, status, stage, number_of_msgs, volume_traded and reference_price. A date appears at most once per instrument.
avg_number_of_msgs : float
Mean message count over exactly the dates shown.
avg_volume_traded : float
Mean daily volume over exactly the dates shown.

Notes

The endpoint only ever returns calibrated instrument-days — it filters on pipeline state server-side. There is no status or stage for you to check: if a date is in the response, you can simulate it. Both fields are reported for provenance and always read complete / model_calibration.

Paging is by instrument, not by row, so a limit can never cut one instrument's dates in half and misreport what is available.

The same ticker can appear more than once, sourced from different providers or exchange protocols — and those entries carry different dates and different tick sizes. Tencent is 700.HK under omd but 700 under bmll. A row is identified by (symbol, provider, exchange), not by symbol alone — use that triple as the key if you cache the catalog.

Examples

python
catalog = client.data.calibrated_data(limit=5)
print(catalog["total"], "calibrated instruments")

# Every date returned is already calibrated and ready to simulate.
# company_name is null for some providers, so fall back to the ticker.
for sym in catalog["symbols"]:
    label = sym["company_name"] or sym["symbol"]
    dates = [d["date"] for d in sym["available_dates"]]
    print(f"{sym['symbol']} ({label}) on {sym['provider']}: {len(dates)} dates")
    print(f"  {dates[:4]}")
python
# Which dates is this symbol already calibrated for?
tencent = client.data.calibrated_data(symbol="700.HK")["symbols"]
print([d["date"] for d in tencent[0]["available_dates"]])

# Which symbols are ready on a particular date?
ready = client.data.calibrated_data(date="2025-09-02")["symbols"]
print([s["symbol"] for s in ready])

# Search by ticker or company name
hits = client.data.calibrated_data(q="angl")["symbols"]
print([(s["symbol"], s["company_name"]) for s in hits])

Paging through one exchange until total is reached:

python
offset, instruments = 0, []
while True:
    page = client.data.calibrated_data(
        exchange="hkex_securities", limit=50, offset=offset
    )
    instruments += page["symbols"]
    offset += len(page["symbols"])
    if not page["symbols"] or offset >= page["total"]:
        break
print(len(instruments), "of", page["total"])

Example response

One entry in symbols per instrument, each with every calibrated date for it. A date appears at most once per instrument, and the two averages are means over exactly the dates shown.

json
{
  "total": 1,
  "limit": null,
  "offset": 0,
  "symbols": [
    {
      "symbol": "700.HK",
      "company_name": null,
      "provider": "omd",
      "exchange": "hkex_securities",
      "instrument_type": "equity",
      "currency": "HKD",
      "tick_size": 0.5,
      "lot_size": 100,
      "available_dates": [
        {
          "date": "2025-09-02",
          "status": "complete",
          "stage": "model_calibration",
          "number_of_msgs": 252812,
          "volume_traded": 21861323.0,
          "reference_price": 605.0
        },
        {
          "date": "2025-09-03",
          "status": "complete",
          "stage": "model_calibration",
          "number_of_msgs": 263787,
          "volume_traded": 24493985.0,
          "reference_price": 606.0
        },
        {
          "date": "2025-09-04",
          "status": "complete",
          "stage": "model_calibration",
          "number_of_msgs": 274606,
          "volume_traded": 31023758.0,
          "reference_price": 604.5
        }
      ],
      "avg_number_of_msgs": 263735.0,
      "avg_volume_traded": 25793022.0
    }
  ]
}

Get the latest calibrated date

A single call answers “what is the most recent date I can simulate?” — every date the endpoint returns is already calibrated, so the newest one is always safe to pass to run(). Filter server-side rather than pulling the whole catalog, and pass provider when a ticker exists under more than one.

python
def latest_cal_date(client, symbol: str, provider: str = None) -> str | None:
    """Return the most recent calibrated date for *symbol*, or None."""
    rows = client.data.calibrated_data(symbol=symbol, provider=provider)["symbols"]
    dates = [d["date"] for row in rows for d in row["available_dates"]]
    return max(dates) if dates else None

cal_date = latest_cal_date(client, "700.HK", provider="omd")
print(f"Latest ready date: {cal_date}")