spb/qc-election
Public
Python 66.6%
HTML 24.8%
CSS 4.9%
JavaScript 3.6%
1# QC Élection Forecast — Plateforme de prévision électorale du Québec 20262# Auteur : Simon-Pierre Boucher3# Contact : contact@spboucher.ai4# https://www.qc-election.com5"""Marchés prédictifs (Polymarket, API publique Gamma) — signal AUXILIAIRE.67Les prix des marchés reflètent l'opinion agrégée de parieurs, pas un modèle8statistique : ils sont affichés en regard du forecast pour comparaison, avec9provenance, et n'entrent jamais dans le calcul des probabilités du modèle.10"""11from __future__ import annotations1213import json14import time15from datetime import datetime, timezone1617import httpx1819GAMMA = "https://gamma-api.polymarket.com/events"20SLUG_WINNER = "quebec-general-election-winner"2122PARTY_IN_QUESTION = {23 "coalition avenir": "CAQ", "parti québécois": "PQ", "parti libéral": "PLQ",24 "québec solidaire": "QS", "parti conservateur": "PCQ",25}2627_cache: dict = {"at": 0.0, "data": None}28CACHE_TTL = 900 # 15 min293031def fetch_winner_market() -> dict | None:32 now = time.time()33 if _cache["data"] is not None and now - _cache["at"] < CACHE_TTL:34 return _cache["data"]35 try:36 r = httpx.get(GAMMA, params={"slug": SLUG_WINNER}, timeout=20)37 r.raise_for_status()38 events = r.json()39 if not events:40 return None41 ev = events[0]42 probs = {}43 for m in ev.get("markets", []):44 q = (m.get("question") or "").lower()45 prices = m.get("outcomePrices")46 if isinstance(prices, str):47 prices = json.loads(prices)48 if not prices:49 continue50 for frag, code in PARTY_IN_QUESTION.items():51 if frag in q:52 probs[code] = float(prices[0]) # prix du « Yes »53 data = {54 "source": "Polymarket (marché prédictif)",55 "event": ev.get("title"),56 "url": f"https://polymarket.com/event/{SLUG_WINNER}",57 "question": "Quel parti remportera le plus de sièges ?",58 "implied_prob_most_seats": probs,59 "volume_usd": round(float(ev.get("volume") or 0)),60 "fetched_at": datetime.now(timezone.utc).isoformat(),61 "note": ("Prix implicites d'un marché de paris — signal auxiliaire, "62 "n'entre pas dans le modèle."),63 }64 _cache.update(at=now, data=data)65 return data66 except Exception:67 return _cache["data"]68