agent / algorithme_readme.md
Echodelta06's picture
Update: algorithme recherche comps et valuation
e9297d9
|
Raw History Blame Contribute Delete
5.35 kB

Algorithme de Matching & Valorisation (Dual-Track)

Ce document decrit le moteur implemente dans backend/database.py apres refonte en double entonnoir:

  • Track A: Market Intel / affichage (list_display)
  • Track B: Valuation / extraction de multiples (list_valuation)

1) Vue d'ensemble du pipeline

  1. Embedding de la cible (Mistral).
  2. Retrieval des candidats (RPC pgvector, fallback Python si erreur).
  3. Scoring de chaque transaction:
    • vector_score
    • size_score
    • naf_score
    • weighted_final_score
  4. Construction de 2 listes:
    • list_display (pertinence marche/metier pour l'affichage)
    • list_valuation (coherence financiere pour la valorisation)
  5. Relaxation elastique si quota insuffisant:
    • list_display: baisse semantic uniquement, par pas de 0.05 (plancher 0.20)
    • list_valuation: hausse size d'abord (+10%), puis baisse semantic
  6. Calcul des multiples:
    • priorite a list_display
    • complement via list_valuation si < 3 valeurs
  7. Generation d'un CSV d'audit dans debug_logs/.

2) Parametres configurables (backend/config.py)

Phase 1 - Identification (List Display)

  • MIN_SEMANTIC_MATCH = 0.80
  • contrainte de taille retiree sur ce track (focus metier)
  • score d'affichage dedie:
    • display_score = (0.95 * vector_score) + (0.05 * size_score) (si taille connue)
    • sinon display_score = vector_score
  • relaxation si < 3 resultats:
    • baisse MIN_SEMANTIC_MATCH par pas de 0.05 jusqu'a 0.20

Phase 2 - Extraction Multiples (List Valuation)

  • VALUATION_MIN_SEMANTIC = 0.45
  • VALUATION_MIN_COUNT = 3
  • MAX_CA_MULTIPLE_VALUATION = 20
  • MAX_EBITDA_MULTIPLE_VALUATION = 70
  • contrainte de taille stricte au depart: size_delta_percent <= 1.00 (±100%)
  • filtres secondaires:
    • naf_score (si NAF cible disponible)
    • semantic_score
  • relaxation elastique:
    1. on relache d'abord la taille (+0.10 par pas)
    2. puis la semantique (pas 0.05)

Relaxation elastique (quota force)

  • semantic_step = 0.05 (jusqu'a 0.20)
  • size_step = 0.10
  • list_display: relaxe semantique uniquement
  • list_valuation: relaxe taille puis semantique

3) Formules de score

3.1 Delta de taille

size_delta_percent = |CA_transaction - CA_cible| / CA_cible

si la taille n'est pas connue: size_delta_percent = null.

3.2 Score final (taille connue + NAF disponible)

ScoreFinal = (0.40 * ScoreTaille) + (0.40 * ScoreVectoriel) + (0.20 * ScoreNAF)

3.3 Score final (taille inconnue + NAF disponible)

ScoreFinal = ((0.40 * ScoreVectoriel) + (0.20 * ScoreNAF)) / (0.40 + 0.20)

3.4 Score final (taille inconnue + NAF indisponible)

ScoreFinal = ScoreVectoriel

4) Regles hard-stop par track

Track A (list_display)

  • reject si vector_score < MIN_SEMANTIC_MATCH
  • pas de hard-stop taille (l'objectif est la coherence metier pour l'affichage)
  • priorisation par display_score (95% semantique, 5% taille)

Track B (list_valuation)

Une transaction entre dans list_valuation si:

  • vector_score >= VALUATION_MIN_SEMANTIC
  • ET multiple_ca ou multiple_ebitda est present et positif
  • ET respecte la contrainte de taille stricte initiale (±100%) quand taille connue
  • ET passe le filtre naf_score si NAF cible disponible
  • si quota insuffisant: relaxation elastique (taille puis semantique)

5) Logique de calcul des multiples

Pour chaque axe (CA, EBITDA):

  1. on prend les multiples valides de list_display
  2. si le count est < VALUATION_MIN_COUNT, on complete avec les meilleurs de list_valuation (tri weighted_final_score)
  3. si count final < VALUATION_MIN_COUNT:
    • is_calculable = false
    • reason = "Données insuffisantes même après élargissement"
  4. toute transaction ajoutee via paliers elastiques est taggee:
    • quality_label = "Match Élargi (Quota Forcé)"

Sinon, calcul mediane/moyenne.

6) Contrat de sortie (zero-null)

Dans results.multiples:

  • montants toujours numeriques (0 par defaut)
  • objet normalise:
    • valuation_ca = { value, is_calculable, reason }
    • valuation_ebitda = { value, is_calculable, reason }
  • scope de valorisation:
    • valuation_scope = "listing stricte" ou "listing élargie"

7) Audit CSV

Pour chaque execution:

  • fichier: debug_logs/audit_matching_[timestamp].csv
  • toutes les transactions scannees (retenues + rejetees)
  • colonnes de provenance:
    • in_display_track
    • in_valuation_track
    • list_origin (display, valuation, display+valuation, rejected)
  • statuts typiques:
    • RETAINED_DISPLAY
    • RETAINED_VALUATION_POOL
    • RETAINED_DISPLAY+VALUATION_POOL
    • REJECTED

Rajout ed06 (a améliorer):

Actuellement, la formule ressemble probablement à ceci : Score Final = (Poids_Sémantique * Similarité) + (Poids_CA * Proximité_CA)

Si la métallurgie a un score CA de 1.0 (CA identique) et un score sémantique de 0.6 (faible mais passe le seuil), elle peut battre une boutique de vêtements qui aurait un score sémantique de 0.9 mais un score CA de 0.4 (boutique plus petite). C'est ce qu'on appelle un faux positif financier. Si la métallurgie sort dans le top 3 d'une boutique de vêtements, c'est que ton algorithme actuel est additif (on additionne les scores) au lieu d'être éliminatoire (on filtre d'abord, on score ensuite).