Forex Positions Aggregate
A consensus long/short reading per currency pair, blending the individual broker sentiment feeds.
forex_positions_aggregate — the dataset name to pass to the Obscura API.
What one row means
One cross-source retail-positioning consensus for a single instrument (FX pair or stock/index CFD) produced by a single run of the `forex_aggregate` task: the mean long%/short% across whichever of the five retail-forex sources (dukascopy, amarkets, oanda, myfxbook, ig) reported a snapshot for that instrument inside the run's look-back window, plus how many sources fed the average.
One row per (pair, event_time) — event_time is the aggregation-run timestamp, identical across every pair produced by a given run..
Derived in-database from forex_positions.
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_positions_aggregate: published: available_date = event_time::date, the compute instant — the row does not exist before the aggregation task runs, so it is public the moment it is written. DERIVED, not collected: forex_aggregate.rs opens no HTTP client and never touches bronze; it averages forex_positions in-database. Its DERIVED_FROM edge is Republishes, not Aggregates — 21,496 of 22,845 rows have sources_count = 1, so most 'averages' are a single source's number verbatim.
Refresh cadence
Obscura refreshes forex_positions_aggregate 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 — 7 columns
The full public column list for forex_positions_aggregate, with the meaning of every field. The same
schema is served unauthenticated at https://api.obscura.trade/v1/catalog/forex_positions_aggregate.
| Column | Type | Description |
|---|---|---|
| pair | text · not null | Instrument key, copied verbatim from the contributing forex_positions.pair values (not restricted to currency pairs; also carries CFD-style stock/index entries). |
| event_time | timestamp with time zone · not null | The aggregation run's timestamp — one Utc::now() captured per forex_aggregate task invocation and reused for every pair row that run produces. `available_date` is generated from this column. |
| available_date | date | PUBLIC-availability date, STORED generated as (event_time AT TIME ZONE 'UTC')::date — the UTC calendar day this consensus row was computed and written. |
| avg_long_pct | double precision | Mean of contributing sources' long_pct (0-100) for this pair across sources with a snapshot in the run's look-back window. |
| avg_short_pct | double precision | Mean of contributing sources' short_pct (0-100), over the same source set as avg_long_pct. |
| sources_count | integer · not null | Count of distinct sources (out of up to 5 retail-forex collectors) whose latest-in-window snapshot fed this row's averages. |
| net_bias | double precision | Net bias = avg_long_pct - avg_short_pct (positive = crowd net long); the FXSSI-style contrarian signal this dataset exists to serve. |
Access forex_positions_aggregate
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_positions_aggregate",
symbols=["NVDA", "AAPL"],
start="2024-01-01",
)
Create a free account Browse all 95 datasets
Frequently asked questions
What is in the forex_positions_aggregate dataset?
A consensus long/short reading per currency pair, blending the individual broker sentiment feeds. One cross-source retail-positioning consensus for a single instrument (FX pair or stock/index CFD) produced by a single run of the `forex_aggregate` task: the mean long%/short% across whichever of the five retail-forex sources (dukascopy, amarkets, oanda, myfxbook, ig) reported a snapshot for that instrument inside the run's look-back window, plus how many sources fed the average.
How do I avoid look-ahead bias with forex_positions_aggregate?
Filter on forex_positions_aggregate.available_date, the day the publisher made the row public. For this dataset that date is derived as follows — published: available_date = event_time::date, the compute instant — the row does not exist before the aggregation task runs, so it is public the moment it is written. DERIVED, not collected: forex_aggregate.rs opens no HTTP client and never touches bronze; it averages forex_positions in-database. Its DERIVED_FROM edge is Republishes, not Aggregates — 21,496 of 22,845 rows have sources_count = 1, so most 'averages' are a single source's number verbatim. 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_positions_aggregate?
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_positions_aggregate". The column schema is public at https://api.obscura.trade/v1/catalog/forex_positions_aggregate.
Can I filter forex_positions_aggregate by company or symbol?
Yes. forex_positions_aggregate carries pair, the column the API's symbols filter resolves against.
How often is forex_positions_aggregate updated?
Obscura refreshes forex_positions_aggregate 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.