# yukka

A Python client for [YUKKA Lab](https://www.yukkalab.com)'s sentiment and financial data APIs. Pull news sentiment, entity resolution, and market data directly into your Python environment.

```python
from yukka import Session, Asset
from yukka.data import stoxx600

with Session() as session:  # reads YUKKA_TOKEN from environment
    bmw = Asset.from_isin("DE0005190003", session.resolver)
    df = session.sentiment(bmw, date_from="2026-01-01")
```

## Installation

```bash
pip install yukka
```

Requires Python 3.13+.

## Authentication

A JWT token is required to access the YUKKA APIs. Set it as an environment variable:

```bash
export YUKKA_TOKEN="eyJ..."
```

Or pass it explicitly:

```python
from yukka import Session

session = Session(token="eyJ...")
```

> Contact [YUKKA Lab](https://www.yukka.ai/contact-us) to request API access.

## Quick Start

### Using a pre-validated universe

The package ships with pre-resolved constituent lists for major indices. No entity resolution needed.

```python
from yukka import Session, Asset
from yukka.data import stoxx600, sp500, ftse100, nasdaq100

# Load STOXX 600 constituents (isin, ric, name, yukka_id, ...)
universe = stoxx600()

# Create assets from YUKKA IDs and fetch sentiment
assets = Asset.from_yukka_id(universe["yukka_id"].to_list())

with Session() as session:
    df = session.sentiment(assets, date_from="2026-01-01", date_to="2026-02-01")
```

### Creating assets from different identifier types

```python
from yukka import Session, Asset

with Session() as session:
    # From YUKKA ID (no API call needed)
    bmw = Asset.from_yukka_id("company:bmw")

    # From ISIN (resolves via Metadata API)
    siemens = Asset.from_isin("DE0007236101", session.resolver)

    # From RIC code (resolves via bundled master file)
    sap = Asset.from_ric("SAPG.DE")

    df = session.sentiment([bmw, siemens, sap], date_from="2026-01-01")
```

### Batch requests

Large entity lists are automatically batched (default 50 per request):

```python
with Session() as session:
    assets = Asset.from_ric(universe["constituent_ric"].to_list())
    df = session.sentiment(assets, date_from="2025-01-01", batch_size=50)
```

## API Reference

### `Session`

High-level entry point. Reads `YUKKA_TOKEN` from the environment automatically.

| Method | Description |
|--------|-------------|
| `session.sentiment(assets, date_from, date_to)` | Fetch daily sentiment counts (positive / neutral / negative) |
| `session.resolver` | `EntityResolver` for ISIN → YUKKA ID lookups |
| `session.today` | Today's date |

Returns a Polars DataFrame with columns: `date`, `entity`, `positive`, `neutral`, `negative`.

### `Asset`

Immutable representation of a YUKKA entity.

| Factory | Description |
|---------|-------------|
| `Asset.from_yukka_id(id)` | From a YUKKA compound key, e.g. `"company:bmw"` |
| `Asset.from_isin(isin, resolver)` | From an ISIN via Metadata API lookup |
| `Asset.from_ric(ric)` | From a RIC code via bundled master file |

All factory methods accept a single value or a list.

### `YukkaClient`

Low-level client for direct API access, if you need more control than `Session` provides.

```python
from yukka import YukkaClient

with YukkaClient.from_token("eyJ...") as client:
    df = client.sentiment(["company:bmw", "company:siemens"], "2026-01-01", "2026-01-31")
```

### Pre-validated universes

```python
from yukka.data import stoxx600, sp500, ftse100, nasdaq100

df = stoxx600()   # STOXX Europe 600
df = sp500()      # S&P 500
df = ftse100()    # FTSE 100
df = nasdaq100()  # NASDAQ 100
```

Each returns a Polars DataFrame with `isin`, `constituent_ric`, `constituent_name`, and `yukka_id` columns.

## Universe Coverage

Not all index constituents are present in the YUKKA ontology. The table below summarises coverage as of the bundled master file.

| Index | Total constituents | In YUKKA ontology | Not in YUKKA ontology |
|-------|--------------------|-------------------|-----------------------|
| STOXX 600 | 931 | 915 | 16 |
| S&P 500 | 680 | 671 | 9 |
| NASDAQ 100 | 184 | 177 | 7 |
| FTSE 100 | 126 | 124 | 2 |

Each list contains historical constituents from June 2016 to December 2025.

<details>
<summary>STOXX 600 — 16 companies not in YUKKA ontology</summary>

| RIC | ISIN | Name |
|-----|------|------|
| SAB.L^J16 | GB00BYZTBD95 | Abi Sab Group Holding Ltd |
| AMRZ.S | CH1430134226 | Amrize AG |
| CVC.AS | JE00BRX98089 | CVC Capital Partners PLC |
| CAN.L | FR001400T0D6 | Canal+ SA |
| EMEIS.PA | FR001400NLM4 | Emeis SA |
| GALD.S | CH1335392721 | Galderma Group Ltd |
| HIAB.HE | FI4000571013 | Hiab Oyj |
| LTMC.MI | IT0005541336 | Lottomatica Group SpA |
| MFEB.MI | NL0015001OJ9 | MFE-MEDIAFOREUROPE NV |
| MICCT.L | NL0015002MS2 | Magnum Ice Cream Company NV |
| PUIGb.MC | ES0105777017 | Puig Brands SA |
| R3NK.DE | DE000RENK730 | RENK Group AG |
| SUNN.S | CH1386220409 | Sunrise Communications AG |
| VAR.OL | NO0011202772 | Var Energi ASA |
| VSURE.ST | GB00BVMN1558 | Verisure PLC |
| VOLCARb.ST | SE0021628898 | Volvo Car AB |

</details>

<details>
<summary>S&P 500 — 9 companies not in YUKKA ontology</summary>

| RIC | ISIN | Name |
|-----|------|------|
| AMCR.N | JE00BV7DQ550 | Amcor PLC |
| AMTM.N | US0239391016 | Amentum Holdings Inc |
| J.N | US46982L1089 | Jacobs Solutions Inc |
| LH.N | US5049221055 | Labcorp Holdings Inc |
| PSKY.OQ | US69932A2042 | Paramount Skydance Corp |
| Q.N | US74743L1008 | Qnity Electronics Inc |
| SOLV.N | US83444M1018 | Solventum Corp |
| TEL.N | IE000IVNQZ81 | TE Connectivity PLC |
| TKO.N | US87256C1018 | TKO Group Holdings Inc |

</details>

<details>
<summary>NASDAQ 100 — 7 companies not in YUKKA ontology</summary>

| RIC | ISIN | Name |
|-----|------|------|
| ARM.OQ | US0420682058 | Arm Holdings PLC |
| GRAL.OQ | US3847471014 | Grail Inc |
| LBTYA.OQ | BMG611881019 | Liberty Global Ltd |
| LCID.OQ | US5494982029 | Lucid Group Inc |
| QVCGA.OQ | US74915M6057 | QVC Group Inc |
| SIRI.OQ | US8299331004 | Sirius XM Holdings Inc |
| TRI.OQ | CA8849038085 | Thomson Reuters Corp |

</details>

<details>
<summary>FTSE 100 — 2 companies not in YUKKA ontology</summary>

| RIC | ISIN | Name |
|-----|------|------|
| BMEB.L | JE00BVSYJW51 | B&M European Value Retail SA |
| PCT.L | GB00BR3YV268 | Polar Capital Technology Trust PLC |

</details>

## License

MIT
