Real-time XNAS.BASIC
data is included with a Plus or Unlimited subscription through our Databento US Equities service.
Visit our pricing page for more information.
Compare on-exchange and off-exchange trade volume
Overview
In this example, we will stream live data and compare the volume of trades on the different venues that compose the Nasdaq Basic with NLS Plus (XNAS.BASIC
) dataset.
The following venues are included in this dataset:
- Nasdaq (XNAS)
- Nasdaq BX (XBOS)
- Nasdaq PSX (XPSX)
- FINRA/Nasdaq TRF Carteret (FINN)
- FINRA/Nasdaq TRF Chicago (FINC)
The FINRA/Nasdaq TRFs aggregate data from most of the 30 ATSs and account for approximately 45% to 49% of the average daily volume (ADV) in all exchange-listed securities.
As of January 2025, XNAS.BASIC
represented about 63% of ADV, which includes both on-exchange and off-exchange trades.
Trades schema
We will use the trades schema for this example. NLS Plus reports the size, price, and exchange/TRF for every trade. The trade aggressor side is not available on this dataset, so the side
field will always be set to N
.
The side
field is populated on our depth-of-book feeds, such as Nasdaq TotalView-ITCH (XNAS.ITCH
).
Info
Example
import databento as db
# First, create the respective clients
historical_client = db.Historical(key="$YOUR_API_KEY")
live_client = db.Live(key="$YOUR_API_KEY")
# Next, we will subscribe to the trades schema for the designated symbol
symbol = "TSLA"
live_client.subscribe(
dataset="XNAS.BASIC",
schema="trades",
symbols=symbol,
)
# We will stream live data to file for further use
live_client.add_stream(f"{symbol}_trades.dbn")
live_client.start()
# Let the connection run for 15 seconds. All trades in this time will be saved
# to the file above
live_client.block_for_close(timeout=15)
# Now we will open the file for our analysis and create a Pandas DataFrame
dbn_store = db.DBNStore.from_file(f"{symbol}_trades.dbn")
df = dbn_store.to_df(schema="trades")
# Calculate statistics by venue
venue_df = df.groupby("publisher_id", as_index=False)["size"].agg(["sum", "mean"])
venue_df["mean"] = venue_df["mean"].round().astype(int)
total_volume = venue_df["sum"].sum()
venue_df["percentage"] = (venue_df["sum"] / total_volume * 100).round(2)
# Clean up for readability
publishers = historical_client.metadata.list_publishers()
publisher_venues = {x["publisher_id"]: x["description"].partition("-")[2] for x in publishers}
venue_df["publisher_id"] = venue_df["publisher_id"].map(publisher_venues)
venue_df = venue_df.sort_values("sum", ascending=False)
venue_df.columns = ["Venue", "Total Volume", "Average Size", "% of Dataset Total"]
print(venue_df)
Result
InfoIf you do not see any output, it could be because the markets are closed. See the
start
parameter in Live.subscribe for using intraday replay.
Venue Total Volume Average Size % of Dataset Total
1 FINRA/Nasdaq TRF Carteret 86591 56 68.93
0 Nasdaq 36218 48 28.83
2 FINRA/Nasdaq TRF Chicago 2408 51 1.92
3 Nasdaq BX 348 58 0.28
4 Nasdaq PSX 57 11 0.05