Download data

How to get simulation IDs and download output data.

All simulation data is downloaded via get_sim_data(sim_id). To use it you first need a sim_id — where you get one depends on your tier.

Getting simulation IDs

Free tier — cached simulations

Use list_cached() to browse pre-run simulations and pick a sim_id. See Simulations for the full list of available cached data and filtering options.

Pro tier — running a simulation

run() returns queued_sim_ids immediately on submission. You can also retrieve sim_ids from a completed job via get_job_results(). See Simulations for the full submission and job tracking API.

Downloading data

Once you have a sim_id, use get_sim_data() to download any of the output files as a Polars DataFrame.

Single simulation

python
sim_id = client.simulation.list_cached()["simulations"][0]["example_sim_id"]

# Full simulation output (default file)
df = client.simulation.get_sim_data(sim_id)
print(df.shape)
print(df.head())

# Mid-price resampled to 1-minute bars
mid_df = client.simulation.get_sim_data(sim_id, "mid_price_by_min.parquet")

Bulk download

Download multiple simulations at once as a ZIP using get_bulk_data().

python
cached = client.simulation.list_cached(symbol="700.HK", scenario="normal")
sim = cached["simulations"][0]

# example_sim_id is only run 0000 — expand it to the first 5 Monte Carlo
# runs. The run index is the final field: swap it for 0000, 0001, …
base = sim["example_sim_id"].rsplit(":", 1)[0]
sim_ids = [f"{base}:{i:04d}" for i in range(min(sim["n_runs"], 5))]

# get_bulk_data accepts up to 100 sim_ids per call
zip_bytes = client.simulation.get_bulk_data(
    sim_ids=sim_ids,
    include_sim_data=True,
    include_mid_price=True
)

with open("simulation_data.zip", "wb") as f:
    f.write(zip_bytes)

# Or load directly without saving
import zipfile, io, polars as pl

with zipfile.ZipFile(io.BytesIO(zip_bytes)) as zf:
    for name in zf.namelist():
        if name.endswith(".parquet"):
            df = pl.read_parquet(io.BytesIO(zf.read(name)))
            print(f"{name}: {df.shape}")

Output files

See Output format for a full explanation of the L2 and Ticks DataFrames, message types, and side convention inside sim_data.parquet.

FileDescription
sim_data.parquetFull simulation output (order book + orders at tick resolution)
mid_price_by_min.parquetMid-price resampled to 1-minute bars
l2_by_second.parquetLevel 2 order book (all 10 levels) sampled per second
exec_schedule.parquetExecution schedule with order times and quantities (if algo present)
schedule_by_min.parquetAlgo orders aggregated to 1-minute buckets (if algo present)
exec_results.parquetMarket slippage, risk and impact metrics (if algo present)
params.jsonSimulation configuration and parameters
results.jsonSummary metrics from the simulation

mid_price_by_min.parquet

ColumnTypeDescription
timedatetimeMinute timestamp
mid_pricefloatMid-price at end of minute
python
sim_id = client.simulation.list_cached()["simulations"][0]["example_sim_id"]
mid_df = client.simulation.get_sim_data(sim_id, "mid_price_by_min.parquet")

import matplotlib.pyplot as plt
plt.plot(mid_df["time"], mid_df["mid_price"])
plt.title("Simulated Price Path")
plt.show()

l2_by_second.parquet

The full Level 2 order book (10 price levels on each side) sampled at 1-second intervals. Contains the last snapshot within each second.

ColumnTypeDescription
timedatetimeSecond timestamp
bid_price_1..10floatBid prices at levels 1-10
bid_size_1..10intBid sizes at levels 1-10
bid_count_1..10intNumber of orders at bid levels 1-10
ask_price_1..10floatAsk prices at levels 1-10
ask_size_1..10intAsk sizes at levels 1-10
ask_count_1..10intNumber of orders at ask levels 1-10
python
sim_id = client.simulation.list_cached()["simulations"][0]["example_sim_id"]
l2_df = client.simulation.get_sim_data(sim_id, "l2_by_second.parquet")
print(l2_df.columns)  # time + 60 L2 columns

# Plot bid-ask spread over time
spread = l2_df["ask_price_1"] - l2_df["bid_price_1"]
import matplotlib.pyplot as plt
plt.plot(l2_df["time"], spread)
plt.title("Bid-Ask Spread (per second)")
plt.show()

Execution files

Execution files are only present when the simulation was submitted with an exec_algos parameter (Pro tier only).

python
sim_id = client.simulation.list_cached()["simulations"][0]["example_sim_id"]
files = client.simulation.list_sim_files(sim_id)
if files["has_exec_schedule"]:
    exec_df = client.simulation.get_sim_data(sim_id, "exec_schedule.parquet")

Available symbols (Pro tier)

Pro tier users can run simulations across 15,000+ HKEX and LSE symbols. The universe changes over time, so rather than a static list, call client.data.get_available_symbols() to retrieve the current symbols and their calibration dates programmatically — see Available symbols for the full response schema.