Obscura

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.

Category Markets Columns 4 Refresh Daily Point-in-time available_date

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.

ColumnTypeDescription
signaltext · not nullChen-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_enddate · not nullMonth-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`.
valuedouble precisionMonthly 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_datedatePUBLIC-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.

Related datasets

Cboe IndicesDaily history of Cboe's volatility indices, including VIX, sourced directly from Cboe. Crypto MarketsPer-coin market data from CoinGecko: price, market cap and volume across thousands of cryptocurrencies. DeFiLlama ProtocolsTotal value locked in each DeFi protocol, tracked by DeFiLlama. DeFiLlama StablecoinsCirculating supply of each stablecoin over time, from DeFiLlama. DeFiLlama TVLTotal value locked on each blockchain, from DeFiLlama. Flow MetricsTrade-flow metrics per symbol in fixed time windows: taker (aggressor) buy versus sell volume and trade counts, broken o… Forex OrderbookOANDA's order book and position book by currency pair: where retail traders' open orders and positions sit relative to p… Forex PositionsRetail forex positioning by pair (share of traders long versus short), collected from several broker sentiment feeds.