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
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().
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.
| File | Description |
|---|---|
| sim_data.parquet | Full simulation output (order book + orders at tick resolution) |
| mid_price_by_min.parquet | Mid-price resampled to 1-minute bars |
| l2_by_second.parquet | Level 2 order book (all 10 levels) sampled per second |
| exec_schedule.parquet | Execution schedule with order times and quantities (if algo present) |
| schedule_by_min.parquet | Algo orders aggregated to 1-minute buckets (if algo present) |
| exec_results.parquet | Market slippage, risk and impact metrics (if algo present) |
| params.json | Simulation configuration and parameters |
| results.json | Summary metrics from the simulation |
mid_price_by_min.parquet
| Column | Type | Description |
|---|---|---|
| time | datetime | Minute timestamp |
| mid_price | float | Mid-price at end of minute |
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.
| Column | Type | Description |
|---|---|---|
| time | datetime | Second timestamp |
| bid_price_1..10 | float | Bid prices at levels 1-10 |
| bid_size_1..10 | int | Bid sizes at levels 1-10 |
| bid_count_1..10 | int | Number of orders at bid levels 1-10 |
| ask_price_1..10 | float | Ask prices at levels 1-10 |
| ask_size_1..10 | int | Ask sizes at levels 1-10 |
| ask_count_1..10 | int | Number of orders at ask levels 1-10 |
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).
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.