> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mecone.trade/llms.txt
> Use this file to discover all available pages before exploring further.

# Factor Lab

> One stock against six prediction-market themes, with company events

Factor Lab relates one stock to six prediction-market themes: its beta to each theme, the current
theme levels, an out-of-sample P\&L comparison, a paper portfolio of theme contracts that tracks the
stock, and the company's earnings, dividends, splits, and material SEC 8-K events.

Every response is research only. Nothing in it is an order, a trade size, or a hedge ratio.
`paper`, `research`, and `official` are always `true`. `executable` is always `false`.

## Request

```
GET /api/v1/factors/stocks/{ticker}
```

```bash theme={null}
curl -H "X-API-Key: $MECONE_API_KEY" https://api.mecone.trade/api/v1/factors/stocks/AAPL
```

### Authentication

Send an API key with the `factors:read` scope (see [API keys](/api-reference#api-keys)) in
either header:

```
Authorization: Bearer mck_…
X-API-Key: mck_…
```

### Ticker

`ticker` is a Yahoo symbol: 1 to 32 letters or digits, with `.` or `-` allowed between them, for
example `AAPL`, `BRK-B`, `0700.HK`, `7203.T`. It is case-insensitive and returned upper-case.

### Errors

Every error is an RFC 9457 problem (`application/problem+json`), the same as the other v1
routes. See the [problem types](/problems). Every error response carries
`Cache-Control: no-store`.

| Status | `type` ends in | When |
| - | - | - |
| 401 | `#credential-invalid` | The API key is unknown, revoked, or expired. |
| 401 | `#credential-required` | No credential was sent. |
| 403 | `#credential-scope` | The key does not carry `factors:read`. |
| 404 | `#unknown-equity` | Yahoo does not know the ticker as an equity. |
| 422 | `#invalid-ticker` | The ticker breaks the rules above. |
| 422 | `#not-an-equity` | The ticker is a fund, index, currency, or other non-equity. |
| 429 | `#rate-limited` | The key is over its per-minute limit. `Retry-After` and `RateLimit-*` headers are set. |
| 429 | `#rate-limit-exceeded` | The client IP is over the v1 per-minute limit. `Retry-After` and `RateLimit-*` headers are set. |
| 503 | `#equity-source-unavailable`, `#equity-history-unavailable`, `#yfinance-unavailable` | Yahoo price data could not be read. |
| 503 | `#factors-unconfigured` | The server has no Factor Lab service credential configured. |

`detail` is a short sentence. It never contains upstream error text.

## Response

`200 OK`, `application/json`, `Cache-Control: no-store`. All timestamps are ISO 8601. All dates
are `YYYY-MM-DD`. Any field documented as nullable is `null` when its data is unavailable.

### Top-level fields

| Field | Type | Meaning |
| - | - | - |
| `schema_version` | string | `mecone-hedgebook-live-v4`. |
| `data_mode` | string | `LIVE_RESEARCH`. |
| `state` | string | `AVAILABLE` when all six themes have a fresh level and both venues are available, `UNAVAILABLE` when no theme has a level, else `PARTIAL`. |
| `as_of` | string | Server time the response was built, UTC. |
| `paper`, `research`, `official` | boolean | Always `true`. |
| `executable` | boolean | Always `false`. |
| `equity` | object | The stock and its daily price history. See [equity](#equity). |
| `calendar` | object | Company events. See [calendar](#calendar). |
| `exposure_model` | object | Direct OLS betas of the stock's daily returns on daily changes in selected Kalshi theme contracts. `fitted` is `false` when the model could not be fitted, for example with fewer than 252 observations. `exposures[]` holds one row per theme with `factor_id`, `status`, `beta`, `standard_error`, `t_stat`, `observations`, and the `proxy` contract. |
| `proxy_model_score` | object | A 0 to 100 score: the absolute-beta-weighted mean of each fitted proxy's current adverse probability for the stock. `status` is `AVAILABLE`, `PARTIAL`, or `UNAVAILABLE`. It is not a forecast. |
| `factors` | array | Six theme levels: `growth_stress`, `higher_for_longer`, `trade_friction`, `energy_shock`, `ai_disruption`, `credit_stress`. Each has `id`, `label`, `status`, `level` (0 to 1 adverse probability, nullable), and its `constituents`. |
| `contracts` | array | Every Kalshi and Polymarket contract behind the themes, with `venue`, `market_id`, `title`, `factor_id`, `bid`, `ask`, `mid`, `probability`, `volume`, `close_time`, and quote freshness fields. `executable` is always `false`. |
| `pnl_comparison` | object | Out-of-sample daily P\&L of the stock with and without the fitted proxy hedge, on a fixed reference notional. `status`, `window`, `metrics`, and `series[]`. |
| `execution_backtest` | object | An offline paper backtest artifact when one exists for the ticker. Otherwise `status` is `UNAVAILABLE`. |
| `execution_validation` | object | The paper and live gates for the backtest. `production_ready` is always `false`. |
| `composite` | object | Equal-weight 0 to 100 mean of the available theme levels. Market-wide, not specific to the stock. |
| `sources` | object | Freshness of each input: `equity`, `kalshi`, `polymarket`. See [sources](#sources). |
| `mimicking_portfolio` | object | A bounded minimum-variance paper portfolio of theme contracts that tracks the stock's P\&L. `status`, `metrics`, `series[]`, and `latest_research_sleeve.positions[]`. |
| `methodology` | object | Fixed labels for the method in use. |

### equity

| Field | Type | Meaning |
| - | - | - |
| `ticker` | string | Upper-case Yahoo symbol. |
| `name` | string | Company name. |
| `exchange` | string | Exchange display name, for example `NasdaqGS`. |
| `currency` | string | Price currency, for example `USD`. |
| `sector`, `industry`, `country` | string | `Unknown` in this version. |
| `quote` | object | `price`, `previous_close`, `change_percent`, `market_cap` (nullable), and `as_of`. |
| `history` | array | Up to 400 daily sessions, oldest first. |

Each `history` row:

| Field | Type | Meaning |
| - | - | - |
| `t` | string | The session's exchange-local midnight, with its UTC offset. |
| `session_date` | string | The session's date on the exchange calendar. |
| `open`, `high`, `low`, `adjusted_close`, `volume` | number or null | Daily values. |
| `close` | number | Daily close. |
| `is_earnings_session` | boolean | `true` when this session equals a `calendar.past_earnings[].reaction_session` on or after `calendar.window.past_start`. `false` on every other row, for non-U.S. tickers, and when the calendar is unavailable. |

### sources

`sources.equity`:

| Field | Type | Meaning |
| - | - | - |
| `status` | string | Always `AVAILABLE`. A failed price read is an error response instead. |
| `as_of` | string | Same as `equity.quote.as_of`. |
| `provider` | string | `yfinance`. |

`sources.kalshi` and `sources.polymarket`:

| Field | Type | Meaning |
| - | - | - |
| `status` | string | `AVAILABLE`, `PARTIAL`, `STALE`, or `UNAVAILABLE`. |
| `as_of` | string or null | Time of the venue's newest market data. |
| `source_object` | string or null | The venue endpoint or stored snapshot the data came from. |
| `reason` | string or null | A fixed snake\_case code when `status` is not `AVAILABLE`, for example `reviewed_thematic_scope_only` or `newest_snapshot_is_stale`. |
| `completeness` | object | `status` is `COMPLETE`, `INCOMPLETE`, `NOT_RECORDED`, or `UNAVAILABLE`. `detail` is a sentence or `null`. |
| `row_count` | integer | Number of contracts read from the venue. |
| `freshness_budget_seconds` | integer or null | The largest data age, in seconds, that still counts as fresh. |

## calendar

Earnings, dividends, splits, and material SEC 8-K events for a U.S. primary listing.

```json theme={null}
{
  "status": "AVAILABLE",
  "reason": null,
  "as_of": "2026-09-29T12:00:00Z",
  "window": { "past_start": "2025-09-29", "upcoming_end": "2026-12-28" },
  "next_earnings": {
    "date": "2026-10-29",
    "window_end": null,
    "eps_estimate": 1.98124,
    "eps_estimate_low": 1.93,
    "eps_estimate_high": 2.07,
    "revenue_estimate": 113624521680.0,
    "revenue_estimate_low": 112248100000.0,
    "revenue_estimate_high": 117219700000.0
  },
  "past_earnings": [
    {
      "fiscal_quarter_end": "2026-06-30",
      "report_date": "2026-07-30",
      "sec_accepted_at": "2026-07-30T16:30:28-04:00",
      "reaction_session": "2026-07-31",
      "eps_estimate": 1.89243,
      "eps_actual": 2.02,
      "surprise_percent": 6.74,
      "sec_filing_url": "https://www.sec.gov/Archives/edgar/data/320193/000032019326000018/aapl-20260730.htm"
    }
  ],
  "next_dividend": null,
  "past_dividends": [{ "ex_date": "2026-08-10", "amount": 0.27 }],
  "splits": [],
  "company_events": [
    {
      "report_date": "2026-04-17",
      "filed_date": "2026-09-01",
      "items": ["5.02"],
      "labels": ["Departure or election of directors or officers"],
      "sec_filing_url": "https://www.sec.gov/Archives/edgar/data/320193/000114036126035325/ef20081427_8ka.htm"
    }
  ]
}
```

### Status

| `status` | Meaning |
| - | - |
| `AVAILABLE` | Every section was built. A section can still be `null` or empty when the company has no such event, for example no upcoming earnings date. |
| `PARTIAL` | One source failed. The sections that need it are `null`. |
| `UNAVAILABLE` | No section was built. Both sources failed, the calendar did not answer within 5 seconds, or the calendar is switched off. |
| `UNSUPPORTED_MARKET` | The ticker is not a U.S. primary listing. Every section is `null`. |

A U.S. primary listing is a USD equity on Nasdaq (`NMS`, `NGM`, `NCM`), NYSE (`NYQ`), or NYSE
American (`ASE`) that trades on the America/New\_York session.

`reason` is `null` when `status` is `AVAILABLE`, else one of these fixed sentences:

* `Company calendar covers U.S. primary listings only.`
* `Yahoo calendar data was unavailable.`
* `SEC EDGAR data was unavailable.`
* `Yahoo and SEC EDGAR data were unavailable.`
* `Company calendar did not respond within the time budget.`
* `Company calendar was unavailable.`
* `Company calendar is disabled.`

Sources by section:

| Section | Source |
| - | - |
| `next_earnings`, `next_dividend`, `past_dividends`, `splits` | Yahoo |
| `company_events` | SEC EDGAR |
| `past_earnings` | Yahoo and SEC EDGAR. `null` if either failed. |

Yahoo data is cached for up to 6 hours and SEC data for up to 24 hours.

### Fields

| Field | Type | Meaning |
| - | - | - |
| `status` | string | See [Status](#status). |
| `reason` | string or null | See [Status](#status). |
| `as_of` | string | Time the calendar was built, UTC. |
| `window.past_start` | string | `as_of` date minus 365 days. Bounds `company_events` and `is_earnings_session`. |
| `window.upcoming_end` | string | `as_of` date plus 90 days. Bounds `next_earnings` and `next_dividend`. |
| `next_earnings` | object or null | The next earnings report. `null` when there is no date, when every date is before today, or when the date is after `upcoming_end`. |
| `past_earnings` | array or null | The last 4 reported quarters, newest first. |
| `next_dividend` | object or null | The next ex-dividend date. `null` when there is none, or when it is before today or after `upcoming_end`. |
| `past_dividends` | array or null | Cash dividends from the last 2 years, newest first, at most 40. |
| `splits` | array or null | Stock splits from the last 2 years, newest first, at most 10. |
| `company_events` | array or null | Material 8-K and 8-K/A filings whose event date is inside the past window, newest first, at most 100. |

`next_earnings`:

| Field | Type | Meaning |
| - | - | - |
| `date` | string | The report date, or the first day of Yahoo's expected window. |
| `window_end` | string or null | The last day of the expected window. `null` when the date is known. |
| `eps_estimate`, `eps_estimate_low`, `eps_estimate_high` | number or null | Consensus EPS mean, low, and high. |
| `revenue_estimate`, `revenue_estimate_low`, `revenue_estimate_high` | number or null | Consensus revenue mean, low, and high, in the listing currency. |

The time of day of the report is not included.

`past_earnings[]`:

| Field | Type | Meaning |
| - | - | - |
| `fiscal_quarter_end` | string | Quarter-end date as Yahoo labels it. It can differ by a few days from the company's own fiscal calendar. |
| `report_date` | string or null | Event date of the earliest 8-K with item 2.02 (results of operations) reported 1 to 60 days after `fiscal_quarter_end`. 8-K/A amendments are not used. |
| `sec_accepted_at` | string or null | When EDGAR accepted that 8-K, in New York time with its UTC offset. |
| `reaction_session` | string or null | The first session that could trade on the release. When EDGAR accepted the 8-K on `report_date` at or after 16:00 New York time, this is the next session after `report_date`. Otherwise it is the first session on or after `report_date`. `null` when that session is outside `equity.history`. |
| `eps_estimate` | number or null | Consensus EPS before the report. |
| `eps_actual` | number or null | Reported EPS. |
| `surprise_percent` | number or null | Yahoo's EPS surprise against the estimate, in percent. `6.74` means 6.74%. |
| `sec_filing_url` | string or null | The 8-K's primary document on `https://www.sec.gov/`. |

When no 8-K matches a quarter, `report_date`, `sec_accepted_at`, `reaction_session`, and
`sec_filing_url` are `null`, and the EPS fields are kept.

EPS values are Yahoo's reported figures, which are usually adjusted (non-GAAP). They can differ
from GAAP EPS in the company's filings. `eps_estimate`, `eps_actual`, and `surprise_percent` come
from the same source, so they are consistent with each other.

`next_dividend`:

| Field | Type | Meaning |
| - | - | - |
| `ex_date` | string | Ex-dividend date. |
| `pay_date` | string or null | Payment date. |

`past_dividends[]`:

| Field | Type | Meaning |
| - | - | - |
| `ex_date` | string | Ex-dividend date. |
| `amount` | number | Cash amount per share in the listing currency. |

`splits[]`:

| Field | Type | Meaning |
| - | - | - |
| `date` | string | Split date. |
| `ratio` | number | New shares per old share. `4.0` is a 4-for-1 split. `0.1` is a 1-for-10 reverse split. |

`company_events[]`:

| Field | Type | Meaning |
| - | - | - |
| `report_date` | string | Date of the event the filing reports. |
| `filed_date` | string or null | Date the filing reached EDGAR. |
| `items` | array of string | 8-K item codes from the table below, in filing order. |
| `labels` | array of string | Label for each code in `items`, same order. |
| `sec_filing_url` | string | The filing's primary document on `https://www.sec.gov/`. |

Only these item codes are kept. A filing with none of them is left out.

| Item | Label |
| - | - |
| 1.01 | Entry into a material agreement |
| 1.02 | Termination of a material agreement |
| 2.01 | Completed acquisition or sale of assets |
| 3.01 | Delisting notice or listing rule failure |
| 5.01 | Change in control |
| 5.02 | Departure or election of directors or officers |
| 5.07 | Shareholder vote results |
| 8.01 | Other events |

## Data sources

* Prices, earnings dates and estimates, EPS, dividends, and splits: Yahoo Finance. Mecone is not
  affiliated with Yahoo. The data is provided as is.
* Earnings report dates and 8-K events: SEC EDGAR.
* Theme contracts: Kalshi and Polymarket public market data.
