# Market Data

> Read-only market data across 14 African exchanges — ETFs, currency-correct price charts, 50-symbol batch quotes, exchange open/closed status, top movers, holiday calendars, the exchange directory, and EOD OHLCV candles. Data-key safe.

Everything here is read-only and **data-key safe** (`pk_data_`). Expand your product with ETFs listed
across African markets (e.g. Satrix on the JSE) and render rich price charts for both stocks and ETFs.

<Callout type="info">
  Examples use the production base `https://mystocks.africa/api/v1/partner`. To run any of them against
  the sandbox, swap the base for `https://mystocks.africa/api/sandbox/v1/partner` and use your
  `sk_sandbox_` key.
</Callout>

## ETFs catalog

Query listed ETFs via the `/etfs` endpoints. Responses carry fund-specific metadata such as expense
ratios, asset classes, geographical focus, risk levels, and top holdings.

```bash
curl "https://mystocks.africa/api/v1/partner/etfs?exchange=JSE" \
  -H "Authorization: Bearer pk_live_<your_key>"
```

```json
{
  "etfs": [
    {
      "id": "STXEME.ZA",
      "symbol": "STXEME.ZA",
      "name": "Satrix MSCI Emerging Markets ETF",
      "exchange": "JSE",
      "currency": "ZAR",
      "price": 75.0,
      "usdPrice": 4.55,
      "assetType": "ETF",
      "fundMetadata": {
        "brand": "Satrix",
        "expenseRatio": 0.38,
        "geographicalFocus": "Global Emerging Markets",
        "indexTracked": "MSCI Emerging Markets Index",
        "riskLevel": "HIGH",
        "managementStyle": "PASSIVE"
      }
    }
  ],
  "count": 1
}
```

## Mapped price charts

Retrieve pre-computed, currency-correct charts via the `/chart` endpoints — no manual date-grid math.
Price values are returned in their **native local trading currency** for precise UI alignment,
alongside converted USD histories. Works for both stocks (`GET /stocks/SCOM.KE/chart?period=1y`) and
ETFs (`GET /etfs/STXEME.ZA/chart?period=3m`).

```bash
curl "https://mystocks.africa/api/v1/partner/etfs/STXEME.ZA/chart?period=3m" \
  -H "Authorization: Bearer pk_live_<your_key>"
```

```json
{
  "symbol": "STXEME.ZA",
  "currency": "ZAR",
  "period": "3m",
  "labels": ["2026-03-01", "2026-04-01", "2026-05-23"],
  "prices": [73.5, 74.2, 75.0],
  "priceHistory": [
    { "date": "2026-05-23T19:59:41.000Z", "open": 74.6, "high": 75.2, "low": 74.3, "price": 75.0, "close": 75.0, "usdPrice": 4.55, "volume": 24000 }
  ]
}
```

## Batch quotes (up to 50 symbols)

Query up to 50 comma-separated stock or ETF symbols in a single roundtrip with `?symbols=A,B,C`. Use
`?symbol=X&exchange=Y` for a single symbol — the response unwraps to a plain object in `data` and
returns `404` if not found. In batch mode, unresolved symbols are listed in `not_found` rather than
failing the whole request. Sending more than 50 returns `400 BATCH_LIMIT_EXCEEDED` with `max` and
`received`. `volume` is always an integer — `0` for instruments with no trades today, never `null`.

```bash
curl "https://mystocks.africa/api/v1/partner/market/quotes?symbols=SCOM.KE,GLD.ZA,INVALID_XYZ" \
  -H "Authorization: Bearer pk_live_<your_key>"
```

```json
{
  "data": [
    { "symbol": "SCOM.KE", "name": "Safaricom PLC", "exchange": "NSE", "currency": "KES", "price": 16.5, "usd_price": 0.0126, "change": 0.25, "change_pct": 0.015385, "volume": 4210000, "market_status": "OPEN" },
    { "symbol": "GLD.ZA", "name": "NewGold Issuer ETF", "exchange": "JSE", "currency": "ZAR", "price": 410.0, "usd_price": 24.85, "change": -1.5, "change_pct": -0.003643, "volume": 0, "market_status": "OPEN" }
  ],
  "not_found": ["INVALID_XYZ"],
  "meta": { "request_id": "4a3f9c1e-7b2d-4e8a-9f06-1c5d3e2b7a04", "timestamp": "2026-06-04T09:42:00.000Z" }
}
```

## Market status & holidays

`GET /market/status` tells you whether an exchange is currently open and when it next opens. Status is
computed from live exchange schedules **and** the holiday calendar; when an exchange is closed for a
public holiday the response includes a `holiday` reason string. Omit `?exchange=` to receive status for
all 14 supported exchanges plus a top-level `anyOpen` boolean.

```bash
curl "https://mystocks.africa/api/v1/partner/market/status?exchange=NSE" \
  -H "Authorization: Bearer pk_live_<your_key>"
```

```jsonc
// Public holiday — forced closed
{ "exchange": "NSE", "name": "Nairobi Securities Exchange", "currency": "KES", "isOpen": false, "status": "CLOSED", "localOpen": "09:00", "localClose": "15:00", "timezone": "Africa/Nairobi", "nextOpen": "2026-06-02T06:00:00.000Z", "holiday": "Madaraka Day", "checkedAt": "2026-06-01T10:00:00.000Z" }
```

`GET /market/holidays` returns forward-looking closure dates for any exchange and range (`from`, `to`;
defaults to today through +12 months, max 2 years). Combine the two: status tells you if the market is
open _right now_, holidays gives you the calendar for scheduling logic.

```json
{
  "data": [
    { "exchange": "NSE", "date": "2026-10-20", "reason": "Mashujaa Day" },
    { "exchange": "NSE", "date": "2026-12-25", "reason": "Christmas Day" }
  ],
  "count": 2,
  "from": "2026-06-06",
  "to": "2026-12-31"
}
```

## Top movers

Top price-change movers for any exchange — sorted by `change_pct` descending (gainers) or ascending
(losers). Paginated via `page` and `limit`. Only instruments with a recorded `changePct` appear.

<ParamTable fields={[
  { name: 'exchange',  type: 'string',  required: true,  desc: 'Exchange code, e.g. NSE.' },
  { name: 'direction', type: 'string',  required: false, desc: 'gainers | losers (default: gainers).' },
  { name: 'limit',     type: 'integer', required: false, desc: '1–100, default 10.' },
  { name: 'page',      type: 'integer', required: false, desc: '1-based, default 1.' },
]} />

```bash
curl "https://mystocks.africa/api/v1/partner/market/movers?exchange=NSE&direction=gainers&limit=5&page=1" \
  -H "Authorization: Bearer pk_live_<your_key>"
```

```json
{
  "data": [
    { "symbol": "EABL.KE", "name": "East African Breweries", "exchange": "NSE", "currency": "KES", "price": 185.0, "change_pct": 0.057143, "volume": 312000, "market_status": "OPEN" }
  ],
  "meta": { "exchange": "NSE", "direction": "gainers", "page": 1, "totalCount": 48, "perPage": 5, "hasNext": true }
}
```

The snake_case meta aliases (`total_count`, `per_page`, `has_next`) are deprecated — removal 2026-10-01.

## Exchange directory

Returns all supported exchanges with trading hours, currencies, settlement cycles, and live
OPEN/CLOSED status in one call. `mic` is the ISO 10383 operating Market Identifier Code; `settlement`
summarizes the cycle (T+2 for EGX, T+3 for all others). The same `mic` appears on
`GET /stocks/{symbol}` and `GET /companies/{symbol}` as `exchangeMic`.

```bash
curl "https://mystocks.africa/api/v1/partner/market/exchanges" \
  -H "Authorization: Bearer pk_live_<your_key>"
```

```json
{
  "data": [
    { "code": "NSE", "mic": "XNAI", "name": "Nairobi Securities Exchange", "country": "KE", "currency": "KES", "timezone": "Africa/Nairobi", "trading_hours": { "open": "09:00", "close": "15:00" }, "settlement": { "cycle": "T+3", "cycleDays": 3 }, "market_status": "OPEN" },
    { "code": "EGX", "mic": "XCAI", "name": "Egyptian Exchange", "country": "EG", "currency": "EGP", "timezone": "Africa/Cairo", "trading_hours": { "open": "10:00", "close": "14:30" }, "settlement": { "cycle": "T+2", "cycleDays": 2 }, "market_status": "CLOSED" }
  ]
}
```

## EOD OHLCV candles

End-of-day OHLCV candles for any symbol over a custom date range. `open`, `high`, and `low` are `null`
until intraday data becomes available for that session — check `ohlc_available` before rendering a
candlestick.

<ParamTable fields={[
  { name: 'symbol',   type: 'string', required: true,  desc: 'Exchange-qualified symbol, e.g. SCOM.KE.' },
  { name: 'exchange', type: 'string', required: true,  desc: 'Exchange code, e.g. NSE.' },
  { name: 'from',     type: 'string', required: false, desc: 'Start date (YYYY-MM-DD, UTC).' },
  { name: 'to',       type: 'string', required: false, desc: 'End date (YYYY-MM-DD, UTC).' },
  { name: 'interval', type: 'string', required: false, desc: 'Candle interval — currently only 1d supported.' },
]} />

```bash
curl "https://mystocks.africa/api/v1/partner/market/ohlcv?symbol=SCOM.KE&exchange=NSE&from=2026-06-01&to=2026-06-06" \
  -H "Authorization: Bearer pk_live_<your_key>"
```

```json
{
  "data": [
    { "date": "2026-06-02", "open": null, "high": null, "low": null, "close": 16.25, "volume": 3820000, "ohlc_available": false },
    { "date": "2026-06-03", "open": 16.3, "high": 16.75, "low": 16.1, "close": 16.5, "volume": 4210000, "ohlc_available": true }
  ],
  "meta": { "symbol": "SCOM.KE", "exchange": "NSE", "interval": "1d" }
}
```

<Callout type="info">
  Every market endpoint lives under `/market/*` (quotes, movers, exchanges, ohlcv, status, settlement,
  holidays). The old `/market-data/*` paths remain working aliases but are deprecated — use `/market/*`
  in new code.
</Callout>
