Forex Orderbook
OANDA's order book and position book by currency pair: where retail traders' open orders and positions sit relative to price.
forex_orderbook — the dataset name to pass to the Obscura API.
What one row means
One price bucket within one OANDA order-book or position-book snapshot for one instrument at one 20-minute grid time: the percent of pending orders (`book_type = 'order'`) or open positions (`book_type = 'position'`) sitting at that price level, expressed as long/short shares of the book. This preserves OANDA's rich structure; the net long/short it implies is also written to `forex_positions` for cross-source aggregation.
One row per (source, pair, event_time, book_type, price_bucket).
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 forex_orderbook: snapshot: available_date = captured_date, a STORED GENERATED column (migration 000205). WHY THAT IS THE DAY IT BECAME AVAILABLE: OANDA exposes only its CURRENT 20-minute grid bucket and offers no archive endpoint, so a past book cannot be fetched — every row exists because we polled, and the day we polled is the day the book was obtainable. There is nothing the vendor disseminates for this to lag behind. captured_date replaced a generated `(event_time AT TIME ZONE 'UTC')::date`; same day, but a poll instant cannot NAME itself a capture day, which is how one label came to cover six expressions. Existing rows were backfilled from exactly that expression, so no stored value moved.
Refresh cadence
Obscura refreshes forex_orderbook every 30 minutes — 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 — 11 columns
The full public column list for forex_orderbook, with the meaning of every field. The same
schema is served unauthenticated at https://api.obscura.trade/v1/catalog/forex_orderbook.
| Column | Type | Description |
|---|---|---|
| source | text · not null | Vendor discriminator for this shared forex-positioning table family; always `oanda` for now. Part of the composite primary key so other vendors could share the table without colliding. |
| pair | text · not null | Currency pair (or metal), underscore form normalized to a pair, e.g. `EUR_USD` -> `EURUSD`. |
| event_time | timestamp with time zone · not null | The book's own snapshot instant (aligns to OANDA's fixed 20-minute grid); `available_date` derives from it. |
| book_type | text · not null | `order` (pending-order book) or `position` (open-position book). |
| price_bucket | text · not null | Bucket lower-edge price, kept as OANDA delivers it (string keeps float PKs exact). |
| captured_date | date · not null | The UTC calendar day the collector POLLED the book — the date-part of the grid instant on a live run, the bronze object's capture day on a replay. available_date is generated directly from it. |
| available_date | date | PUBLIC-availability date = captured_date. STORED generated column, read-only; not settable directly. For this source the poll instant IS the only instant the book was obtainable — there is no archive and no embargo. |
| long_count_percent | double precision | Percent of the book's order/position count at this bucket that are long; nullable when OANDA omits it. |
| short_count_percent | double precision | Percent of the book's order/position count at this bucket that are short. |
| snapshot_price | double precision | Mid price + bucket width for the whole snapshot (repeated per row). |
| bucket_width | double precision | Width in price units of each bucket in this book snapshot, repeated on every row. |
Access forex_orderbook
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="forex_orderbook",
symbols=["NVDA", "AAPL"],
start="2024-01-01",
)
Create a free account Browse all 95 datasets
Frequently asked questions
What is in the forex_orderbook dataset?
OANDA's order book and position book by currency pair: where retail traders' open orders and positions sit relative to price. One price bucket within one OANDA order-book or position-book snapshot for one instrument at one 20-minute grid time: the percent of pending orders (`book_type = 'order'`) or open positions (`book_type = 'position'`) sitting at that price level, expressed as long/short shares of the book. This preserves OANDA's rich structure; the net long/short it implies is also written to `forex_positions` for cross-source aggregation.
How do I avoid look-ahead bias with forex_orderbook?
Filter on forex_orderbook.available_date, the day the publisher made the row public. For this dataset that date is derived as follows — snapshot: available_date = captured_date, a STORED GENERATED column (migration 000205). WHY THAT IS THE DAY IT BECAME AVAILABLE: OANDA exposes only its CURRENT 20-minute grid bucket and offers no archive endpoint, so a past book cannot be fetched — every row exists because we polled, and the day we polled is the day the book was obtainable. There is nothing the vendor disseminates for this to lag behind. captured_date replaced a generated `(event_time AT TIME ZONE 'UTC')::date`; same day, but a poll instant cannot NAME itself a capture day, which is how one label came to cover six expressions. Existing rows were backfilled from exactly that expression, so no stored value moved. A query of the form WHERE available_date <= '<as-of date>' never sees a row before it existed.
In what formats can I get forex_orderbook?
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="forex_orderbook". The column schema is public at https://api.obscura.trade/v1/catalog/forex_orderbook.
Can I filter forex_orderbook by company or symbol?
Yes. forex_orderbook carries pair, the column the API's symbols filter resolves against.
How often is forex_orderbook updated?
Obscura refreshes forex_orderbook on a every 30 minutes 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.