## Market data
Prices, candles and the option chain, from the
[Market data](/api/v1/reference/market-data/) endpoints. Instruments are named
by `instrument_id` from the [scrip master](/sdk/python/scrip-master/).

- **No IP check**, and a short `429` is retried once.
- **For live prices use the [tick stream](/sdk/python/streams/)**: `get_ltp`
  and `get_quotes` allow one call per second each.
- **Examples** use `api` and `instrument_id` from [Getting started](/sdk/python/).

### api.get_ltp(...) — Last traded price

**Calls:** [`GET /v1/marketdata/ltp`](/api/v1/reference/market-data/#get-v1marketdataltp--last-traded-price) · **Scope:** `marketdata.read`

Last price for up to 100 instruments.

#### Signature

```python
api.get_ltp(instrument_ids: int | Sequence[int], *, timeout: float | None = None) -> dict
```

| Parameter | Type | Required | Notes |
|---|---|---|---|
| `instrument_ids` | int or list[int] | yes | One id, or up to 100. |
| `timeout` | float | no | Seconds. |

#### Returns

`{"data": {"<id>": {"last_trade_price": ..., "last_trade_time": ...}}}`, keyed
by the id as a string. An unknown id maps to `None`.

#### Raises

- [`SahiValidationException`](/sdk/python/errors/#sahivalidationexception): more than 100 ids.
- [`SahiAPIException`](/sdk/python/errors/#sahiapiexception): far more ids, roughly 200, make the URL too long for the edge.
- `ValueError`: no ids, raised before sending.
- [`SahiRateLimitException`](/sdk/python/errors/#sahiratelimitexception): over 1/s.

#### Example

```python
ltp = api.get_ltp(instrument_id)["data"][str(instrument_id)]
print(ltp["last_trade_price"] / 100, "INR")
```

### api.get_quotes(...) — Full quote with market depth

**Calls:** [`GET /v1/marketdata/quotes`](/api/v1/reference/market-data/#get-v1marketdataquotes--full-quote-with-market-depth) · **Scope:** `marketdata.read`

Price, volume, price band, open interest and depth for up to 100 instruments.

#### Signature

```python
api.get_quotes(instrument_ids: int | Sequence[int], *, timeout: float | None = None) -> dict
```

#### Returns

`{"data": {"<id>": {...}}}`; fields are on [the endpoint](/api/v1/reference/market-data/#get-v1marketdataquotes--full-quote-with-market-depth).

#### Raises

- As for `get_ltp`.

#### Example

```python
quote = api.get_quotes(instrument_id)["data"][str(instrument_id)]
print(quote["dpr_lower"] / 100, "to", quote["dpr_upper"] / 100, "INR")
```

### api.get_candles(...) — Historical candles

**Calls:** [`GET /v1/marketdata/candles`](/api/v1/reference/market-data/#get-v1marketdatacandles--historical-ohlc) · **Scope:** `marketdata.read`

Up to 2500 candles for a window, most recent first if it holds more; then
`has_more` is set. For a longer range use
[`get_candle_history`](#apiget_candle_history--candle-history).

#### Signature

```python
api.get_candles(instrument_id: int, size: str, from_ms: int, to_ms: int, *, include_partial: bool = False, oi: bool = False, timeout: float | None = None) -> dict
```

| Parameter | Type | Required | Notes |
|---|---|---|---|
| `instrument_id` | int | yes | The instrument. |
| `size` | str | yes | `1m`, `3m`, `5m`, `15m`, `30m`, `1h` or `1d`; use the `CANDLE_*` constants. |
| `from_ms` | int | yes | Start, epoch ms, inclusive. |
| `to_ms` | int | yes | End, epoch ms, inclusive. |
| `include_partial` | bool | no | Add the in-progress candle while the market is open. |
| `oi` | bool | no | Add open interest as a seventh element. |
| `timeout` | float | no | Seconds. |

#### Returns

`{"candles": [[ts, o, h, l, c, v], ...], "has_more": ...}`. Prices in paise,
`ts` in epoch ms.

#### Raises

- `ValueError`: unknown `size`, or `to_ms` before `from_ms`.
- [`SahiRateLimitException`](/sdk/python/errors/#sahiratelimitexception): over 2/s, 250/min or 100,000/day.

#### Example

```python
import time

now_ms = int(time.time() * 1000)
page = api.get_candles(instrument_id, SahiAPI.CANDLE_5M, now_ms - 86400 * 1000, now_ms)
print(len(page["candles"]), "candles")
```

### api.get_candle_history(...) — Candle history

Every candle in a range, oldest first: the SDK pages through `get_candles` for
you. The whole range is held in memory.

#### Signature

```python
api.get_candle_history(instrument_id: int, size: str, from_ms: int, to_ms: int, *, oi: bool = False, timeout: float | None = None) -> list[list]
```

#### Returns

A list of candles shaped as in `get_candles`.

#### Raises

- As for `get_candles`.

#### Example

```python
import time

now_ms = int(time.time() * 1000)
candles = api.get_candle_history(instrument_id, SahiAPI.CANDLE_1D, now_ms - 365 * 86400 * 1000, now_ms)
```

### api.get_option_expiries(...) — Option expiries

**Calls:** [`GET /v1/marketdata/optionchain/expiries`](/api/v1/reference/market-data/#get-v1marketdataoptionchainexpiries--option-expiries) · **Scope:** `marketdata.read`

The expiries with an option chain for an underlying.

#### Signature

```python
api.get_option_expiries(underlying_id: int, *, timeout: float | None = None) -> dict
```

| Parameter | Type | Required | Notes |
|---|---|---|---|
| `underlying_id` | int | yes | The index's or stock's `instrument_id`. |
| `timeout` | float | no | Seconds. |

#### Returns

`{"expiries": ["YYYY-MM-DD", ...]}`, nearest first.

#### Raises

- [`SahiRateLimitException`](/sdk/python/errors/#sahiratelimitexception): over 5/s, 250/min or 10,000/day.

#### Example

`nifty` is from [Find an index](/sdk/python/scrip-master/#find-an-index).

```python
print(api.get_option_expiries(nifty)["expiries"][:3])
```

### api.get_option_chain(...) — Option chain

**Calls:** [`GET /v1/marketdata/optionchain`](/api/v1/reference/market-data/#get-v1marketdataoptionchain--option-chain) · **Scope:** `marketdata.read`

The chain for one underlying and expiry.

#### Signature

```python
api.get_option_chain(underlying_id: int, expiry: str | None = None, *, timeout: float | None = None) -> dict
```

| Parameter | Type | Required | Notes |
|---|---|---|---|
| `underlying_id` | int | yes | The underlying's `instrument_id`. |
| `expiry` | str | no | `YYYY-MM-DD`; default the nearest. |
| `timeout` | float | no | Seconds. |

#### Returns

`underlying_id`, `expiry`, `last_price` and `strikes` (lowest first), each with
`ce` and `pe` legs. Prices are paise, `implied_volatility` is a percent, and
`greeks` are in rupees.

#### Raises

- [`SahiRateLimitException`](/sdk/python/errors/#sahiratelimitexception): over 2/s, 120/min or 20,000/day.

#### Example

```python
chain = api.get_option_chain(nifty)
for row in chain["strikes"][:3]:
    print(row["strike"] / 100, row["ce"] and row["ce"]["last_trade_price"] / 100)
```

