Metadata-Version: 2.4
Name: betfairstudio
Version: 1.0.0
Summary: Betfair Exchange horse racing feature collector for odds modeling
Author: betfairstudio
License: MIT
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.27.0
Requires-Dist: pydantic>=2.6.0
Requires-Dist: pydantic-settings>=2.2.0
Requires-Dist: pyarrow>=15.0.0
Requires-Dist: pandas>=2.2.0
Requires-Dist: pyyaml>=6.0.1
Requires-Dist: tenacity>=8.2.0
Requires-Dist: structlog>=24.1.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
Requires-Dist: ruff>=0.3.0; extra == "dev"

# Betfair Studio

Collecteur de features hippiques via l'API Betfair Exchange, orienté modélisation de cotes.

Récupère pour chaque course dans la fenêtre **[-20 min, +25 min]** :
- Hippodromes (venues)
- Métadonnées course (going, météo, type)
- Chevaux (pedigree, forme, poids, stall)
- Jockey, trainer, owner
- Cotes back/lay live (ou delayed selon la clé API)

Les données sont stockées dans un **feature store** (JSON + Parquet) prêt pour un modèle ML de correction de cotes.

## Installation

```bash
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
```

## Configuration

```bash
cp config/settings.example.yaml config/settings.yaml
# Éditer avec vos identifiants Betfair
```

Voir [docs/API_KEY_SETUP.md](docs/API_KEY_SETUP.md) pour créer une clé API gratuite.

## Lancer le collecteur

```bash
# Une seule collecte
betfair-collector --once

# Boucle toutes les 5 minutes (défaut)
betfair-collector

# Boucle toutes les 30 secondes (après activation clé Live)
betfair-collector --interval 30

# Filtrer un autre pays
betfair-collector --country GB
```

## Utilisation programmatique

```python
from betfairstudio.config.settings import Settings
from betfairstudio.factory import BetfairStudio
from betfairstudio.ml.odds_predictor import BaselineOddsPredictor

settings = Settings.from_yaml("config/settings.yaml")

with BetfairStudio(settings) as studio:
    snapshot, path = studio.collect_and_store()

    for race in snapshot.races:
        print(f"{race.venue.name} — {race.market_name} — {race.runner_count} partants")
        for horse in race.runners:
            back = horse.odds.best_back.price if horse.odds and horse.odds.best_back else None
            print(f"  {horse.name} | jockey={horse.jockey.name} | back={back}")

    predictor = BaselineOddsPredictor()
    if snapshot.races:
        preds = predictor.predict_race(snapshot.races[0])
        for p in preds:
            print(p.horse_name, p.predicted_price, p.edge_pct)
```

## Proxy

Trois modes de transport :

| Mode | Description |
|------|-------------|
| `direct` | Connexion directe à Betfair |
| `http_proxy` | Proxy HTTP/HTTPS classique |
| `relay_proxy` | Relais applicatif custom |

Voir [docs/PROXY_SETUP.md](docs/PROXY_SETUP.md).

## Structure du feature store

```
data/feature_store/
├── snapshots/          # JSON complets (webapp)
├── parquet/            # Tables runners (ML)
│   └── runners_cumulative.parquet
└── index/
    ├── latest_races.json    # Liste courses pour UI
    └── latest_snapshot.json
```

## Architecture

```
Transport (direct | http_proxy | relay_proxy)
    └── SessionManager (auth)
        └── BetfairClient (JSON-RPC)
            └── RaceCollector
                └── FeatureStore (JSON + Parquet)
                    └── OddsPredictor (ML)
```

## Tests

```bash
pytest tests/ -v
```

## Prochaines étapes

- Webapp de visualisation (liste courses → détail chevaux/features/cotes)
- Modèle ML custom remplaçant `BaselineOddsPredictor`
- Intégration Timeform API pour historique complet
- Passage à la clé Live pour données temps réel
