OpenAP Signals
Returns for the long-short equity factor portfolios from the Open Source Asset Pricing project (Chen and Zimmermann), covering a large library of published anomalies.
openap_signals — the dataset name to pass to the Obscura API.
What one row means
One melted (predictor-signal, reference-month) observation from the Chen-Zimmermann Open Source Asset Pricing (OpenAP) long-short portfolio-return dataset: the monthly return earned by going long the top decile / short the bottom decile of stocks sorted on one published cross-sectional anomaly/predictor for one month-end.
One row per (signal, period_end).
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 openap_signals: published: available_date = period_end + 305d, the researched steady-state lag until OpenAP posts its annual full-history CSV restatement to Google Drive (a single shared batch-release date for every row in that run).
Refresh cadence
Obscura refreshes openap_signals 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 — 4 columns
The full public column list for openap_signals, with the meaning of every field. The same
schema is served unauthenticated at https://api.obscura.trade/v1/catalog/openap_signals.
| Column | Type | Description |
|---|---|---|
| signal | text · not null | Chen-Zimmermann predictor/anomaly name, taken verbatim from one column header of the wide source CSV (e.g. `AM`, `AOP`, `Accruals`, `BidAskSpread`). First half of the composite primary key; ~200+ distinct values exist across the full dataset, one per published academic anomaly OpenAP replicates. |
| period_end | date · not null | Month-end reference date the long-short return pertains to (e.g. 2024-12-31 for December 2024), melted from the CSV's own `date` column. Second half of the composite primary key. This is the period/event date, NOT when the return became public — the public availability date is derived from it in `available_date`. |
| value | double precision | Monthly long-short portfolio return for this signal at this month-end, in Chen-Zimmermann's native units (percent, e.g. 1.80 = 1.80% monthly return; not a decimal fraction) — the return from going long the extreme decile predicted to outperform and short the extreme decile predicted to underperform per the signal's published sort. |
| available_date | date | PUBLIC-availability date: DB-generated, STORED column computed as `period_end + 305 days`, the researched steady-state lag until OpenAP's annual full-history CSV restatement is actually posted to Google Drive. The point-in-time column to filter/join/backtest on — NEVER `period_end`, which is the return's own reference month, not its public-availability date. |
Access openap_signals
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="openap_signals",
start="2024-01-01",
)
Create a free account Browse all 95 datasets
Frequently asked questions
What is in the openap_signals dataset?
Returns for the long-short equity factor portfolios from the Open Source Asset Pricing project (Chen and Zimmermann), covering a large library of published anomalies. One melted (predictor-signal, reference-month) observation from the Chen-Zimmermann Open Source Asset Pricing (OpenAP) long-short portfolio-return dataset: the monthly return earned by going long the top decile / short the bottom decile of stocks sorted on one published cross-sectional anomaly/predictor for one month-end.
How do I avoid look-ahead bias with openap_signals?
Filter on openap_signals.available_date, the day the publisher made the row public. For this dataset that date is derived as follows — published: available_date = period_end + 305d, the researched steady-state lag until OpenAP posts its annual full-history CSV restatement to Google Drive (a single shared batch-release date for every row in that run). A query of the form WHERE available_date <= '<as-of date>' never sees a row before it existed.
In what formats can I get openap_signals?
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="openap_signals". The column schema is public at https://api.obscura.trade/v1/catalog/openap_signals.
How often is openap_signals updated?
Obscura refreshes openap_signals 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.