# QC Élection Forecast — Plateforme de prévision électorale du Québec 2026 # Auteur : Simon-Pierre Boucher # Contact : contact@spboucher.ai # https://www.qc-election.com """Marchés prédictifs (Polymarket, API publique Gamma) — signal AUXILIAIRE. Les prix des marchés reflètent l'opinion agrégée de parieurs, pas un modèle statistique : ils sont affichés en regard du forecast pour comparaison, avec provenance, et n'entrent jamais dans le calcul des probabilités du modèle. """ from __future__ import annotations import json import time from datetime import datetime, timezone import httpx GAMMA = "https://gamma-api.polymarket.com/events" SLUG_WINNER = "quebec-general-election-winner" PARTY_IN_QUESTION = { "coalition avenir": "CAQ", "parti québécois": "PQ", "parti libéral": "PLQ", "québec solidaire": "QS", "parti conservateur": "PCQ", } _cache: dict = {"at": 0.0, "data": None} CACHE_TTL = 900 # 15 min def fetch_winner_market() -> dict | None: now = time.time() if _cache["data"] is not None and now - _cache["at"] < CACHE_TTL: return _cache["data"] try: r = httpx.get(GAMMA, params={"slug": SLUG_WINNER}, timeout=20) r.raise_for_status() events = r.json() if not events: return None ev = events[0] probs = {} for m in ev.get("markets", []): q = (m.get("question") or "").lower() prices = m.get("outcomePrices") if isinstance(prices, str): prices = json.loads(prices) if not prices: continue for frag, code in PARTY_IN_QUESTION.items(): if frag in q: probs[code] = float(prices[0]) # prix du « Yes » data = { "source": "Polymarket (marché prédictif)", "event": ev.get("title"), "url": f"https://polymarket.com/event/{SLUG_WINNER}", "question": "Quel parti remportera le plus de sièges ?", "implied_prob_most_seats": probs, "volume_usd": round(float(ev.get("volume") or 0)), "fetched_at": datetime.now(timezone.utc).isoformat(), "note": ("Prix implicites d'un marché de paris — signal auxiliaire, " "n'entre pas dans le modèle."), } _cache.update(at=now, data=data) return data except Exception: return _cache["data"]