SPB Git
6.8 KB · 108 lines python
1"""Méthode du coût : coût neuf, dépréciation (physique, fonctionnelle, externe), extraction de marché.23Convention centrale (sans double comptage) :4    V = V_L + C_N − D_phys − D_fonc − D_ext5où C_N est le coût de REMPLACEMENT (ou de reproduction) neuf, incluant coûts directs, indirects et incitatif6de l'entrepreneur, et où chaque dépréciation est mesurée sur la base de coût restante après les précédentes7(ordre : physique curable → physique incurable → fonctionnelle → externe)."""8from __future__ import annotations9from dataclasses import dataclass, field10from typing import Sequence1112# ----------------------------------------------------------------------------- coût neuf1314def cout_neuf(cout_direct: float, taux_indirects: float, taux_incitatif: float, base_incitatif: str = "direct+indirect") -> dict:15    """Coût neuf = direct + indirects (taux × direct) + incitatif de l'entrepreneur.16    base_incitatif : 'direct' ou 'direct+indirect' (convention à déclarer)."""17    indirects = cout_direct * taux_indirects18    base = cout_direct if base_incitatif == "direct" else cout_direct + indirects19    incitatif = base * taux_incitatif20    return {"direct": cout_direct, "indirects": indirects, "incitatif": incitatif, "total": cout_direct + indirects + incitatif}2122def indexer_cout(cout_base: float, indice_base: float, indice_courant: float) -> float:23    """Actualisation d'un coût historique par ratio d'indices : C_t = C_0 × I_t / I_0."""24    return cout_base * indice_courant / indice_base2526def cout_par_superficie_ajuste(cout_unitaire_ref: float, superficie_ref: float, superficie: float, elasticite: float = -0.1) -> float:27    """Ajustement de taille : coût unitaire ∝ (S/S_ref)^élasticité (économies d'échelle si élasticité < 0)."""28    return cout_unitaire_ref * (superficie / superficie_ref) ** elasticite2930def cout_par_composantes(quantites: dict[str, float], prix_unitaires: dict[str, float]) -> dict:31    """Métré × prix unitaires → coût direct par composante et total."""32    detail = {k: quantites[k] * prix_unitaires[k] for k in quantites}33    return {"detail": detail, "total": sum(detail.values())}3435# ----------------------------------------------------------------------------- dépréciation3637def depreciation_age_vie(cout_neuf_: float, age_effectif: float, vie_economique: float) -> float:38    """Méthode âge-vie (linéaire) : D = C_N × âge effectif / vie économique totale (plafonnée à C_N)."""39    if vie_economique <= 0:40        raise ValueError("vie économique > 0")41    return cout_neuf_ * min(age_effectif / vie_economique, 1.0)4243def depreciation_age_vie_modifiee(cout_neuf_: float, cout_curable: float, age_effectif: float, vie_economique: float) -> dict:44    """Âge-vie modifiée : on retire d'abord les éléments curables, puis on applique le ratio au reste."""45    reste = cout_neuf_ - cout_curable46    incurable = depreciation_age_vie(reste, age_effectif, vie_economique)47    return {"curable": cout_curable, "incurable": incurable, "total": cout_curable + incurable}4849def vie_restante(vie_economique: float, age_effectif: float) -> float:50    return max(vie_economique - age_effectif, 0.0)5152@dataclass53class Composante:54    nom: str55    cout: float56    age_effectif: float57    vie_utile: float58    courte_duree: bool = True5960def depreciation_ventilee(cout_neuf_total: float, curable: float, composantes_courte: Sequence[Composante],61                         age_effectif_structure: float, vie_economique_structure: float) -> dict:62    """Méthode ventilée (breakdown) de la dépréciation physique :63    curable (coût de réparation) + incurable de courte durée (par composante, âge/vie utile) +64    incurable de longue durée (structure : (C_N − curable − coût des composantes courte durée) × âge/vie)."""65    d_courte = {c.nom: c.cout * min(c.age_effectif / c.vie_utile, 1.0) for c in composantes_courte}66    cout_courte = sum(c.cout for c in composantes_courte)67    base_longue = cout_neuf_total - curable - cout_courte68    d_longue = depreciation_age_vie(base_longue, age_effectif_structure, vie_economique_structure)69    total = curable + sum(d_courte.values()) + d_longue70    return {"curable": curable, "courte_duree": d_courte, "longue_duree": d_longue, "base_longue": base_longue, "total": total}7172def desuetude_fonctionnelle_curable(cout_correction: float, cout_si_neuf: float, cout_deja_compte: float = 0.0) -> float:73    """Désuétude fonctionnelle curable (carence ou surabondance) :74    D = coût de correction (installé) − coût de l'élément s'il avait été inclus à neuf + dépréciation déjà imputée à l'élément existant.75    Convention : on évite le double comptage en soustrayant ce qui a déjà été compté en dépréciation physique."""76    return cout_correction - cout_si_neuf - cout_deja_compte7778def desuetude_incurable_par_loyer(perte_loyer_mensuelle: float, multiplicateur_loyer_brut: float) -> float:79    """Désuétude incurable mesurée par capitalisation de la perte de loyer : D = perte mensuelle × MRB mensuel."""80    return perte_loyer_mensuelle * multiplicateur_loyer_brut8182def desuetude_incurable_par_rne(perte_rne_annuelle: float, taux_capitalisation: float, part_batiment: float = 1.0) -> float:83    """D = (perte de RNE / R) × part attribuable au bâtiment (le reste est imputé au terrain)."""84    return perte_rne_annuelle / taux_capitalisation * part_batiment8586def desuetude_externe_ventes_appariees(prix_sans: float, prix_avec: float, part_batiment: float) -> float:87    """Désuétude externe par ventes appariées : (P_sans − P_avec) × part du bâtiment."""88    return (prix_sans - prix_avec) * part_batiment8990def extraction_depreciation_marche(prix_vente: float, valeur_terrain: float, cout_neuf_: float, age_effectif: float | None = None) -> dict:91    """Dépréciation totale extraite du marché : D = C_N − (P − V_L) ; taux = D/C_N ; taux annuel = taux/âge."""92    contrib_bat = prix_vente - valeur_terrain93    d = cout_neuf_ - contrib_bat94    out = {"contribution_batiment": contrib_bat, "depreciation": d, "taux": d / cout_neuf_}95    if age_effectif:96        out["taux_annuel"] = out["taux"] / age_effectif97    return out9899# ----------------------------------------------------------------------------- indication100101def valeur_par_cout(valeur_terrain: float, cout_neuf_: float, dep_physique: float, dep_fonctionnelle: float = 0.0,102                    dep_externe: float = 0.0, ameliorations_site: float = 0.0) -> dict:103    """V = V_L + (C_N − D_phys − D_fonc − D_ext) + améliorations du site (dépréciées séparément)."""104    contrib = cout_neuf_ - dep_physique - dep_fonctionnelle - dep_externe105    return {"contribution_batiment": contrib, "valeur": valeur_terrain + contrib + ameliorations_site,106            "depreciation_totale": dep_physique + dep_fonctionnelle + dep_externe,107            "taux_depreciation": (dep_physique + dep_fonctionnelle + dep_externe) / cout_neuf_ if cout_neuf_ else 0.0}108
Files · 98fa933b6a1cb092e58d4abad01e8e47ddf90324
Menu

Theme