diff --git a/frontend/src/pages/InvestissementDetail.jsx b/frontend/src/pages/InvestissementDetail.jsx index 17c3b2a..19f92c3 100644 --- a/frontend/src/pages/InvestissementDetail.jsx +++ b/frontend/src/pages/InvestissementDetail.jsx @@ -953,6 +953,15 @@ export default function InvestissementDetail() { let rendementReelBrut = null; let rendementReel = null; const rendementEstime = inv.statut !== 'rembourse'; + // XIRR "attendu" (théorique) — même principe que sur la page Plateformes (cf. + // project_xirr_attendu_theorique.md) : au lieu de valoriser prudemment le capital + // restant dû "comme racheté aujourd'hui" (sans intérêts futurs), on projette les + // échéances futures prévues (simul_remboursements) jusqu'au terme du prêt — pour + // matcher le taux de rendement théorique affiché par les plateformes elles-mêmes + // (ex. "Mon taux de rendement interne" chez Bienprêter). Fallback identique au XIRR + // réel (valorisation du capital restant au jour) si aucune échéance future en base. + let rendementAttenduBrut = null; + let rendementAttendu = null; if (remb.length > 0 && inv.date_souscription) { // Flux sortants supplémentaires (réinvestissements = nouveaux décaissements) const reinvOutflows = reinvs.map(r => ({ amount: -r.montant, date: r.date_reinvestissement })); @@ -975,6 +984,37 @@ export default function InvestissementDetail() { ...valorisationAuj, ]; rendementReel = xirr(cashflows); + + if (rendementEstime && capRestant > 0.01) { + const futureEcheances = simul.filter(s => + s.date_prevue > todayStr && ((s.capital_prevu || 0) > 0 || (s.interets_prevus || 0) > 0) + ); + if (futureEcheances.length) { + const flowsBrut = [ + { amount: -inv.montant_investi, date: inv.date_souscription }, + ...reinvOutflows, + ...remb.map(r => ({ amount: (r.capital || 0) + (r.cashback || 0) + (r.interets_bruts || 0), date: r.date_remb })), + ]; + const flowsNet = [ + { amount: -inv.montant_investi, date: inv.date_souscription }, + ...reinvOutflows, + ...remb.map(r => ({ amount: r.net_recu, date: r.date_remb })), + ]; + for (const s of futureEcheances) { + const rates = getRatesForYear(s.date_prevue); + const pfu = rates ? (rates.prelev_sociaux + rates.impot_revenu) / 100 : 0.3; + flowsBrut.push({ amount: (s.capital_prevu || 0) + (s.interets_prevus || 0), date: s.date_prevue }); + flowsNet.push({ amount: (s.capital_prevu || 0) + (s.interets_prevus || 0) * (1 - pfu), date: s.date_prevue }); + } + rendementAttenduBrut = xirr(flowsBrut); + rendementAttendu = xirr(flowsNet); + } else { + // Pas d'échéancier prévisionnel disponible : identique au XIRR réel, pour ne + // jamais sous-évaluer un prêt faute de données (cf. page Plateformes). + rendementAttenduBrut = rendementReelBrut; + rendementAttendu = rendementReel; + } + } } return ( @@ -1049,6 +1089,7 @@ export default function InvestissementDetail() { {(() => { const rendement = netMode ? rendementReel : rendementReelBrut; + const rendementAttenduAffiche = netMode ? rendementAttendu : rendementAttenduBrut; const xirrExplication = `XIRR (taux de rendement interne actualisé) : taux annualisé calculé à partir des flux réels datés ` + `(versement initial, réinvestissements, remboursements ${netMode ? 'nets, après fiscalité' : 'bruts, avant fiscalité'}). ` + @@ -1056,6 +1097,14 @@ export default function InvestissementDetail() { (rendementEstime ? "Prêt pas encore soldé : le capital restant dû est ajouté en flux final, valorisé à la date du jour — c'est donc une estimation, pas un taux définitif." : 'Prêt intégralement remboursé : taux définitif.'); + const xirrAttenduExplication = + `XIRR attendu (théorique) : comme le taux de rendement interne affiché par les plateformes de crowdlending ` + + `(ex. "Mon taux de rendement interne" chez Bienprêter, le %/an affiché chez La Première Brique), ce calcul suppose ` + + `que toutes les échéances prévues (capital + intérêts) encore à venir seront honorées exactement à la date prévue ` + + `par l'échéancier — contrairement au XIRR ci-dessus, qui valorise prudemment le capital restant dû "comme racheté ` + + `aujourd'hui", sans compter les intérêts futurs.\n\n` + + `C'est donc une projection optimiste : elle ne tient pas compte d'un éventuel retard ou défaut de paiement. Si ce ` + + `prêt n'a pas d'échéancier prévisionnel en base, il est valorisé de la même façon que dans le XIRR réel.`; return (
@@ -1078,6 +1127,25 @@ export default function InvestissementDetail() { ? `${(rendement * 100).toLocaleString('fr-FR', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} %` : remb.length === 0 ? 'Aucun remboursement' : '—'}
+ {rendementAttenduAffiche !== null && ( +
+ + Attendu : {(rendementAttenduAffiche * 100).toLocaleString('fr-FR', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} % + + + + + + +
+ )}
); })()}