درس 4 — Analyser

Ratios et alertes en Python

9 دقائق قراءة

هذا المحتوى غير مترجم بعد. تُعرض النسخة الأصلية.

Ratios et alertes en Python

Solvéa Énergies affiche un ROE de 18,3 %, le meilleur des trois. C'est aussi la société qui a brûlé 47 millions d'euros de trésorerie en 2025 et dont le délai de paiement clients est passé de 101 à 143 jours. Un ratio isolé ment ; c'est la combinaison qui informe, et elle n'a de valeur que si chaque ratio est calculé de la même façon pour les trois sociétés, avec une définition écrite. Cette leçon calcule 16 ratios en Python, les formate une seule fois, et en tire des alertes qui citent leur page.

Le mécanisme : une définition, un calcul, un format

flowchart LR
  E["États normalisés en k€"] --> R["ratios_exercice : 16 ratios + EBITDA"]
  D["DEFINITIONS : libellé et formule"] --> T["Tableau de bord"]
  R --> F["formater : un seul format"]
  F --> T
  F --> M["Faits du mémo"]
  R --> A["Règles d'alerte + pages des états"]
  A --> T
  A --> M

Les définitions vivent dans le code, à côté du calcul, et sont affichées telles quelles sous chaque ratio du tableau de bord : un analyste qui conteste une valeur voit la formule utilisée.

files/analyste/ratios.py
DEFINITIONS: dict[str, tuple[str, str]] = {
    "roe": ("ROE", "résultat net / capitaux propres moyens (N et N-1)"),
    "levier": ("Levier", "dette nette / EBITDA"),
    "bfr_jours": ("BFR en jours de CA", "BFR / CA x 365"),
    "free_cash_flow": ("Free cash-flow (k€)", "flux de trésorerie d'exploitation - investissements"),
    ...
}

Quelques définitions demandent une décision explicite :

RatioChoix retenuAlternativePourquoi
ROEcapitaux propres moyens N et N-1capitaux propres de clôtureSolvéa a augmenté son capital de 15 M€ en 2025 : la clôture sous-estime la rentabilité de l'année
EBITDArésultat d'exploitation + dotationsEBITDA « ajusté » de la sociétél'ajusté de Ferlac (25 140 k€) exclut des charges que l'entreprise a bien payées
Délai clientscréances / CA x 365créances / CA TTC x 365le CA TTC n'est pas publié ; le ratio sert à comparer, la convention est affichée
Conversion en cashFCF / résultat netFCF / EBITDAnon significative si le résultat est une perte (affichée « n.s. »)
files/analyste/ratios.py
        # EBITDA négatif : le quotient serait négatif et passerait sous tous les seuils.
        "levier": _div(dette_nette, ebitda) if ebitda > 0 else None,
        # Une conversion rapportée à une perte n'a pas de sens : non significatif.
        "conversion_fcf": _div(fcf, cr["resultat_net"]) if cr["resultat_net"] > 0 else None,

Le format est unique (formater) : le tableau de bord et le mémo affichent la même chaîne, « 5,5x », « 19,8 % », « -14 930 k€ ». C'est ce qui permettra, à la leçon suivante, de vérifier mot pour mot que le mémo n'invente aucun nombre.

Une société a une dette nette de 40 M€ et un EBITDA de -5 M€. Le levier calculé vaut -8x et l'alerte « levier > 3x » ne se déclenche pas. Où corrigez-vous ?

Les alertes : des règles lisibles, des seuils discutables

files/analyste/signaux.py
SEUILS = {
    "levier_max": 3.0,          # dette nette / EBITDA
    "couverture_min": 3.0,      # résultat d'exploitation / charges financières
    "hausse_dso_jours": 15,     # dérive du délai clients en un an
    "baisse_marge_points": 1.0  # points de marge d'EBITDA perdus en un an
}
...
    if cr["resultat_net"] > 0 and r["free_cash_flow"] < 0:
        ajouter("moyenne", "Bénéfice non converti en trésorerie",
                f"Résultat net de {formater('montant', cr['resultat_net'])} mais free cash-flow de "
                f"{formater('free_cash_flow', r['free_cash_flow'])} en {n}.", [p_cr, p_fl])

Chaque alerte porte un identifiant stable (A-solvea-2), une gravité, un constat chiffré et les pages des états dont elle provient. Les seuils sont des choix d'analyste : ils sont en tête de fichier, commentés, pour être discutés en comité plutôt que découverts dans un prompt.

Résultat obtenu (2026-10-15)

Extrait de exemple/analyse.json, produit par make e2e :

Ratio 2025Maison Ferlac SASHelvane Robotique SASolvéa Énergies SA
Croissance du CA2,5 %12,0 %45,4 %
Marge d'EBITDA5,7 %19,8 %13,6 %
ROE-2,1 %17,4 %18,3 %
Levier5,5x-0,6x2,3x
Couverture des intérêts0,7x33,8x4,0x
Délai clients (jours)76 j75 j143 j
Free cash-flow (k€)-14 930 k€13 400 k€-47 225 k€
Conversion en cashn.s.0,7x-4,2x
A-ferlac-1 haute   Endettement élevé | Dette nette / EBITDA de 5,5x en 2025 (3,6x en 2024). [4, 5]
A-ferlac-2 haute   Intérêts mal couverts | Le résultat d'exploitation couvre 0,7x les charges financières en 2025. [4]
A-ferlac-5 moyenne Dividende supérieur au résultat | Dividendes versés de 4 500 k€ pour un résultat net de -1 410 k€ en 2025. [4, 6]
A-solvea-2 moyenne Bénéfice non converti en trésorerie | Résultat net de 11 175 k€ mais free cash-flow de -47 225 k€ en 2025. [4, 6]
A-solvea-3 haute   Dérive des créances clients | Délai clients passé de 101 j à 143 j. [4, 5]

Helvane ne déclenche aucune règle. Les écarts de ratios avec la vérité terrain sont nuls : les ratios calculés sur l'extraction et sur les annotations sont identiques.

Ratios comparés : valeur 2025, valeur 2024 en dessous, formule sous chaque libellé ; un clic ouvre la page de l'état source

Ce qui casse en production

  • Le signe qui inverse le sens. Levier négatif (trésorerie nette ou EBITDA négatif), conversion en cash sur une perte : un quotient calculé sans garde-fou produit une valeur qui passe sous les seuils. Testez chaque ratio aux bornes (test_ebitda_negatif_ne_masque_pas_la_dette).
  • Les seuils universels. 3x de levier est prudent pour un industriel, normal pour une foncière. Symptôme : des alertes systématiques sur un secteur, que les analystes apprennent à ignorer. Parade : des seuils par secteur, dans un fichier versionné.
  • Les ratios sur des exercices non comparables. Solvéa a changé de méthode de reconnaissance du chiffre d'affaires en 2025 : sa croissance de 45,4 % inclut 14 800 k€ dus au seul changement de méthode. Le ratio est juste, sa lecture non. Seul le signal qualitatif (leçon 5) le révèle.
  • Le format dupliqué. Si le JavaScript reformate les ratios de son côté, « 5,5x » et « 5,46x » coexistent et la vérification des nombres du mémo échoue. Un seul formater, côté Python.

Règle de décision

Tout ratio qui sort du système a une formule écrite, un format unique et un test aux bornes. Une alerte est une règle de deux lignes, pas un jugement du modèle. Revoyez les seuils une fois par an avec les analystes, et mesurez combien d'alertes ont été jugées utiles : moins de la moitié, et les seuils sont à revoir.

Pratique

Le comité trouve que l'alerte « Free cash-flow négatif » se déclenche trop souvent sur des sociétés en forte croissance qui investissent. Que proposez-vous ?

Un analyste conteste le ROE de 18,3 % de Solvéa : il obtient 15,1 % avec les capitaux propres de clôture. Qui a raison ?

Exercice. Ajoutez le ratio « intensité d'investissement » (investissements / dotations aux amortissements) et une alerte « Sous-investissement » quand il est inférieur à 0,8 deux années de suite. Quelle société déclenche l'alerte ?

Voir la solution
files/analyste/ratios.py
    "intensite_invest": ("Intensité d'investissement", "investissements / dotations aux amortissements"),
# dans ratios_exercice :
        "intensite_invest": _div(fl["investissements"], cr["dotations_amortissements"]),
# dans formater, avec les ratios en « x » :
    if cle in {"levier", "couverture_interets", "conversion_fcf", "intensite_invest"}:
files/analyste/signaux.py
    if all(x["intensite_invest"] is not None and x["intensite_invest"] < 0.8 for x in (r, r1)):
        ajouter("moyenne", "Sous-investissement",
                f"Investissements inférieurs à 80 % des dotations en {n1} et {n}.", [p_fl, p_cr])

Aucune des trois sociétés ne la déclenche : Helvane investit 1,3x et 1,4x ses dotations, Ferlac 1,1x et 0,9x, Solvéa 2,4x et 3,1x. C'est un résultat utile : une règle qui ne se déclenche jamais sur le corpus doit être testée sur un cas construit (un test avec des investissements réduits), sinon on ne sait pas si elle fonctionne.

  • Je sais écrire un ratio avec sa définition, son format et ses gardes-fous
  • Je sais pourquoi un levier négatif ne doit pas passer sous un seuil
  • Je sais écrire une règle d'alerte qui cite les pages de ses sources
  • Je sais expliquer pourquoi un ROE élevé peut coexister avec une trésorerie qui fond
التالي