Obscura

SEC MIDAS Security Metrics

Per-security market-structure metrics from the SEC's MIDAS system: trade sizes, cancellations, and hidden and odd-lot activity.

sec_midas_security_metrics — the dataset name to pass to the Obscura API.

Category Regulatory Columns 20 Refresh Daily Entity key ticker Point-in-time available_date

What one row means

One row is a single security's SEC MIDAS individual-security market-structure metrics for one trading day: market-cap / turnover / volatility / price decile ranks plus lit, hidden, and odd-lot share-volume and trade-count measures, parsed from SEC's free quarterly bulk zip (`individual_security_<YYYY>_q<Q>.zip`), each holding a ~59MB CSV of daily per-security rows. The `_000` fields are in thousands of shares.

One row per (occurred_on, ticker).

Point-in-time availability

Every Obscura dataset carries available_date: the calendar day the publisher made the row available, day-of, with no session rounding. It is the one column a backtest filters on, and it means the same thing on every dataset in the catalog.

For sec_midas_security_metrics: published: available_date is the day SEC posted the QUARTERLY bulk zip that contains the row, identical on every row of the quarter, materialized by the collector from the object's HTTP Last-Modified (m20260702_000199). Availability is a property of the FILE: the whole quarter ships as one zip, so a January row and a March row become knowable at the same instant. The date is SEC's OWN DAY on SEC's own clock (Eastern), day-of and with no advance for the hour: individual_security_2025_q3.zip carries Last-Modified 2026-03-12 02:50 GMT, which is 22:50 ET on 2026-03-11 — SEC published it on the 11th, and reading the UTC date instead would date 18.8M rows a day late. An mtime is only admissible here because the artifacts are excluded BY NAME (see below). The previous occurred_on + 290 generated column was a per-row lag on a per-file event — 290 was never measured against the source at all, only proxied from OUR OWN sec_midas_processed.processed_at — and it cleared SEC's actual 2025-Q4 posting (2026-07-17) by a single day, putting that quarter's first row at 2026-07-18, so one slower quarter would have made it outright look-ahead; 467,191 rows were already dated into the future. Where SEC's server mtime is not a credible publication stamp (the 30 archive quarters it bulk-touched on 2020-12-19, and 3 with no mtime), the measured steady-state schedule (quarter start + 180 days) stands in and errs late.

Known limitation

Six quarters absent at source: 2014 Q2, all of 2016, and 2019 Q4.

Refresh cadence

Obscura refreshes sec_midas_security_metrics daily — the most frequent scheduled job that re-collects or re-exports it. This is Obscura's own pipeline cadence, not the upstream publisher's release schedule; when a row became public is recorded per row in available_date.

Schema — 20 columns

The full public column list for sec_midas_security_metrics, with the meaning of every field. The same schema is served unauthenticated at https://api.obscura.trade/v1/catalog/sec_midas_security_metrics.

ColumnTypeDescription
securitytext · not nullSecurity TYPE from the MIDAS `Security` CSV column — a free-text class label taking exactly two values across the whole corpus, "Stock" and "ETF". NOT an identifier: it does not name the security, and keying on it collapsed ~8,000 securities/day onto 2 rows. An attribute only; the identity is (occurred_on, ticker).
occurred_ondate · not nullTrading day, parsed from the MIDAS `Date` (YYYYMMDD) column; the period/event date these metrics apply to. Half of the composite primary key.
tickertext · not nullTicker symbol from the MIDAS `Ticker` column — the security's identity, and half of the composite primary key alongside the trading day. Rows whose `Ticker` cell is blank cannot be identified and are dropped at parse time rather than stored unkeyed.
mcap_rankbigintMarket-capitalization decile rank (MIDAS `McapRank`, typically 1-10) assigned to this security for this trading day under SEC's MIDAS market-structure methodology; nullable when the source cell is blank.
turn_rankbigintShare-turnover decile rank (MIDAS `TurnRank`) for this security on this trading day.
volatility_rankbigintIntraday-volatility decile rank (MIDAS `VolatilityRank`) for this security on this trading day.
price_rankbigintShare-price decile rank (MIDAS `PriceRank`) for this security on this trading day.
lit_vol_000double precisionLit (publicly displayed, non-hidden) share trading volume for the day, in thousands of shares (MIDAS `LitVol('000)`).
order_vol_000double precisionTotal order share volume submitted for the day, in thousands of shares (MIDAS `OrderVol('000)`) — the order-flow denominator underlying several of the other rate measures.
hiddendouble precisionHidden/dark order rate (MIDAS `Hidden`) — the fraction of order flow executed via non-displayed (reserve/iceberg or dark-pool-style) liquidity for this security-day; a ratio, not a share count.
trades_for_hiddenbigintCount of trades used as the denominator/basis when computing the `hidden` rate for this security-day (MIDAS `TradesForHidden`).
hidden_vol_000double precisionHidden/non-displayed share volume for the day, in thousands of shares (MIDAS `HiddenVol('000)`).
trade_vol_for_hidden_000double precisionTrade share volume forming the basis for the hidden-volume calculation, in thousands of shares (MIDAS `TradeVolForHidden('000)`).
cancelsbigintCount of order cancellations for this security on this trading day (MIDAS `Cancels`) — a market-structure quality/HFT-activity indicator.
lit_tradesbigintCount of lit (displayed) trades executed for this security on this trading day (MIDAS `LitTrades`).
odd_lotsdouble precisionOdd-lot trading rate (MIDAS `OddLots`) — fraction of activity occurring in sub-round-lot (odd-lot) sizes, which historically fell outside consolidated tape reporting; a ratio, not a share count.
trades_for_odd_lotsbigintCount of trades used as the basis when computing the `odd_lots` rate for this security-day (MIDAS `TradesForOddLots`).
odd_lot_vol_000double precisionOdd-lot share volume for the day, in thousands of shares (MIDAS `OddLotVol('000)`).
trade_vol_for_odd_lots_000double precisionTrade share volume forming the basis for the odd-lot volume calculation, in thousands of shares (MIDAS `TradeVolForOddLots('000)`).
available_datedate · not nullPUBLIC-availability date: the day SEC posted the quarterly bulk zip that contains this trading day. Identical for every trading day inside one quarter, because the whole quarter ships as one file that lands at once. Read from the object's HTTP Last-Modified where that is a credible publication stamp, and from SEC's measured steady-state schedule (quarter start + 180 days) where it is not; recorded per quarter in `sec_midas_processed.published_on` so a bronze replay reproduces it. The point-in-time column to filter/join on — NEVER `occurred_on`, which is the trading day itself.

Access sec_midas_security_metrics

Two delivery paths, one identifier. Both require an Obscura account and an active subscription; the catalog entry and the schema above are public.

import obscura

client = obscura.Client("obs_live_…")

df = client.query(
    dataset="sec_midas_security_metrics",
    symbols=["NVDA", "AAPL"],
    start="2024-01-01",
)

Create a free account Browse all 95 datasets

Frequently asked questions

What is in the sec_midas_security_metrics dataset?

Per-security market-structure metrics from the SEC's MIDAS system: trade sizes, cancellations, and hidden and odd-lot activity. One row is a single security's SEC MIDAS individual-security market-structure metrics for one trading day: market-cap / turnover / volatility / price decile ranks plus lit, hidden, and odd-lot share-volume and trade-count measures, parsed from SEC's free quarterly bulk zip (`individual_security_<YYYY>_q<Q>.zip`), each holding a ~59MB CSV of daily per-security rows. The `_000` fields are in thousands of shares.

How do I avoid look-ahead bias with sec_midas_security_metrics?

Filter on sec_midas_security_metrics.available_date, the day the publisher made the row public. For this dataset that date is derived as follows — published: available_date is the day SEC posted the QUARTERLY bulk zip that contains the row, identical on every row of the quarter, materialized by the collector from the object's HTTP Last-Modified (m20260702_000199). Availability is a property of the FILE: the whole quarter ships as one zip, so a January row and a March row become knowable at the same instant. The date is SEC's OWN DAY on SEC's own clock (Eastern), day-of and with no advance for the hour: individual_security_2025_q3.zip carries Last-Modified 2026-03-12 02:50 GMT, which is 22:50 ET on 2026-03-11 — SEC published it on the 11th, and reading the UTC date instead would date 18.8M rows a day late. An mtime is only admissible here because the artifacts are excluded BY NAME (see below). The previous occurred_on + 290 generated column was a per-row lag on a per-file event — 290 was never measured against the source at all, only proxied from OUR OWN sec_midas_processed.processed_at — and it cleared SEC's actual 2025-Q4 posting (2026-07-17) by a single day, putting that quarter's first row at 2026-07-18, so one slower quarter would have made it outright look-ahead; 467,191 rows were already dated into the future. Where SEC's server mtime is not a credible publication stamp (the 30 archive quarters it bulk-touched on 2020-12-19, and 3 with no mtime), the measured steady-state schedule (quarter start + 180 days) stands in and errs late. A query of the form WHERE available_date <= '<as-of date>' never sees a row before it existed.

In what formats can I get sec_midas_security_metrics?

As a Parquet bulk export (POST https://api.obscura.trade/v1/download) or as JSON from the typed query API (POST https://api.obscura.trade/v1/query), both with dataset="sec_midas_security_metrics". The column schema is public at https://api.obscura.trade/v1/catalog/sec_midas_security_metrics.

Can I filter sec_midas_security_metrics by company or symbol?

Yes. sec_midas_security_metrics carries ticker, the column the API's symbols filter resolves against.

Is sec_midas_security_metrics complete?

Not yet, and the limitation is declared rather than hidden: Six quarters absent at source: 2014 Q2, all of 2016, and 2019 Q4.

How often is sec_midas_security_metrics updated?

Obscura refreshes sec_midas_security_metrics on a daily schedule — that is the most frequent scheduled job that re-collects or re-exports the table. It is Obscura's own pipeline cadence, not the upstream publisher's release schedule; when the publisher makes a row available is described by the availability rule above, and is recorded per row in available_date.

Related datasets

CFTC Commitments of TradersThe CFTC's weekly Commitments of Traders report: how commercial, non-commercial and small traders are positioned in each… ECHO Enforcement CasesEnvironmental enforcement actions and penalties from the EPA's ECHO database. ECHO FacilitiesEPA-regulated facilities and their compliance history, from ECHO. EDGAR 13F FilingsMetadata for every 13F report, the quarterly filing where large institutional managers list their U.S. equity holdings. EDGAR 13F HoldingsThe line-item positions inside each 13F: which manager held which security, and how much, each quarter. EDGAR 8-K ItemsThe item numbers reported on each 8-K (5.02 officer changes, 2.01 acquisitions, 1.01 material agreements, and so on), so… EDGAR Dilution MetricsShare-issuance headroom and overhang metrics built from companies' XBRL filings: authorized versus outstanding shares, a… EDGAR Filing TextSignals mined from the text of filings, such as mentions of distress, litigation, going-concern doubt and restructuring.