SPB Git forge

spb/house-ka

Public
18commits 1branches 0releases
1.9 MBsize
maindefault branch
20 days agolast push
Python 67% TypeScript 18.2% CSS 14.4%
3.3 KB · 78 lines python
Raw Blame History
1# -----------------------------------------------------------------------------2# Immo-Ka — Agrégateur de maisons à vendre (province de Québec)3# Auteur : Simon-Pierre Boucher — contact@spboucher.ai4# mortgage/providers/bank_of_canada.py : Banque du Canada — API Valet5#   (officielle, publique, JSON). Séries de référence : taux hypothécaire6#   conventionnel affiché 1/3/5 ans, taux directeur, rendement obligataire7#   5 ans. purpose="unknown" : séries de RÉFÉRENCE, exclues du comparateur8#   de prêteurs (la BdC ne prête pas aux particuliers).9# -----------------------------------------------------------------------------10from __future__ import annotations1112from .base import RateProvider1314SERIES_URL = ("https://www.bankofcanada.ca/valet/observations/"15              "V80691333,V80691334,V80691335,V39079,BD.CDN.5YR.DQ.YLD/"16              "json?recent=10")1718# série -> (terme mois, nom de produit)19MORTGAGE_SERIES = {20    "V80691333": (12, "Taux hypothécaire conventionnel affiché — 1 an"),21    "V80691334": (36, "Taux hypothécaire conventionnel affiché — 3 ans"),22    "V80691335": (60, "Taux hypothécaire conventionnel affiché — 5 ans"),23}24CONTEXT_SERIES = {25    "V39079": "Taux cible du financement à un jour",26    "BD.CDN.5YR.DQ.YLD": "Rendement obligataire 5 ans — Gouvernement du Canada",27}282930class BankOfCanadaProvider(RateProvider):31    provider_id = "bank_of_canada"32    institution = "Banque du Canada"33    source_url = "https://www.bankofcanada.ca/rates/interest-rates/"34    request_delay = 0.53536    def fetch(self) -> list[dict]:37        return self.parse(self.get(SERIES_URL).text)3839    def parse(self, payload: str) -> list[dict]:40        import json41        data = json.loads(payload)42        observations = data.get("observations") or []43        # Séries à fréquences mélangées : garder la DERNIÈRE valeur par série.44        latest: dict[str, tuple[str, float]] = {}45        for obs in observations:46            d = obs.get("d", "")47            for sid, cell in obs.items():48                if sid == "d" or not isinstance(cell, dict):49                    continue50                v = cell.get("v")51                if v in (None, ""):52                    continue53                try:54                    latest[sid] = (d, float(v))55                except ValueError:56                    continue57        out: list[dict] = []58        for sid, (term, name) in MORTGAGE_SERIES.items():59            if sid not in latest:60                continue61            d, v = latest[sid]62            out.append(self.make_product(63                rate=v, rate_type="fixed", term_months=term, kind="posted",64                product_name=name, purpose="unknown",65                conditions=f"Série Valet {sid} — observation du {d} "66                           "(moyenne hebdomadaire des taux affichés)",67                raw={"series": sid, "date": d, "value": v}))68        for sid, name in CONTEXT_SERIES.items():69            if sid not in latest:70                continue71            d, v = latest[sid]72            out.append(self.make_product(73                rate=v, rate_type="other", term_months=12, kind="posted",74                product_name=name, purpose="unknown",75                conditions=f"Série Valet {sid} — observation du {d}",76                raw={"series": sid, "date": d, "value": v}))77        return out78