data =transpose(series_r).map(d => ({...d,date:newDate(d.date)}))statsA =transpose(stats_r)noms = statsA.map(d => d.allocation)stats =Object.fromEntries(statsA.map(d => [d.allocation, d]))couleurs = ["#2c4a42","#c49a55","#7a9b90"]derniere = data.at(-1)fmtPct = x => (x >=0?"+":"") + (x *100).toLocaleString("fr-FR", {minimumFractionDigits:1,maximumFractionDigits:1}) +"\u00a0%"fmtEur = x =>Math.round(x).toLocaleString("fr-FR") +"\u00a0€"fmtNum = x => x.toLocaleString("fr-FR", {maximumFractionDigits:1})
emettre = el => el.dispatchEvent(newEvent("input", {bubbles:true}))isoDate = d =>newDate(d).toISOString().slice(0,10)// Curseur + champ numérique synchroniséscurseur = ({label, min, max, step =1, value, unite =""}) => {const range =html`<input type="range" min=${min} max=${max} step=${step} value=${value}>`;const num =html`<input type="number" min=${min} max=${max} step=${step} value=${value}>`;const el =html`<div class="champ"><label>${label}</label> <div class="ligne">${range}<div class="num">${num}${unite ?html`<span>${unite}</span>`:""}</div></div></div>`;const remplissage = () => range.style.setProperty("--pct",`${100* (range.value- min) / (max - min)}%`);const maj = v => { v =+v;if (Number.isNaN(v)) return; v =Math.max(min,Math.min(max, v)); el.value= v; range.value= v; num.value= v;remplissage();emettre(el); }; range.addEventListener("input", e => { e.stopPropagation();maj(range.value); }); num.addEventListener("input", e => e.stopPropagation()); num.addEventListener("change", e => { e.stopPropagation();maj(num.value); }); el.value= value;remplissage();return el;}// Pilules : choix unique ou multiplepilules = ({label, options, value, multiple =false, libelles = {}}) => {const el =html`<div class="champ"><label>${label}</label><div class="pilules"></div></div>`;const box = el.querySelector(".pilules");let sel = multiple ?newSet(value) : value;const valeur = () => multiple ? options.filter(o => sel.has(o)) : sel;const rendu = () => box.replaceChildren(...options.map(o => {const actif = multiple ? sel.has(o) : sel === o;const b =html`<button type="button" class="pilule${actif ?" actif":""}"><span class="puce"></span>${libelles[o] ?? o}</button>`; b.onclick= () => {if (multiple) { if (sel.has(o)) { if (sel.size>1) sel.delete(o); } else sel.add(o); }else sel = o;rendu(); el.value=valeur();emettre(el); };return b; }));rendu(); el.value=valeur();return el;}// Sélecteur de date avec raccourcischoixDate = ({label, value, min, max, raccourcis = []}) => {const input =html`<input type="date" min=${isoDate(min)} max=${isoDate(max)} value=${isoDate(value)}>`;const el =html`<div class="champ"><label>${label}</label>${input} <div class="pilules petites">${raccourcis.map(([txt, d]) => {const b =html`<button type="button" class="pilule">${txt}</button>`; b.onclick= () => { input.value=isoDate(d); el.value= d;emettre(el); };return b; })}</div></div>`; input.addEventListener("input", e => { e.stopPropagation();if (input.value) { el.value=newDate(input.value);emettre(el); } }); el.value= value;return el;}libellesAlloc =Object.fromEntries(noms.map(n => [n, n]))
Gestion indicielle
Trois allocations, une même exigence
Découvrez l’évolution de nos allocations Trésorerie, Patrimoine et Horizon, simulez un investissement passé et explorez leurs trajectoires possibles selon leur profil rendement / risque.
IAM Horizon est notre allocation orientée vers la croissance à long terme, avec un profil rendement / risque très dynamique. Son allocation est intégralement axée sur les actions et les actifs à fort potentiel de croissance.
L’allocation est investie à 100% en actions.
Horizon d’investissement : 8 ans et plus
Objectif de performance : 7% par an
Volatilité cible : 12% par an
IAM Patrimoine est notre allocation équilibrée, visant à concilier croissance et préservation du capital. Elle combine des actions et des obligations pour offrir un profil rendement / risque modéré.
L’allocation est investie à 50% en actions et 50% en obligations.
Horizon d’investissement : 5 à 8 ans
Objectif de performance : 5% par an
Volatilité cible : 8% par an
IAM Trésorerie est notre allocation sécurisée, visant à préserver le capital tout en offrant une liquidité optimale. Elle est principalement investie en instruments monétaires et obligations à court terme.
L’allocation est investie à 100% en instruments monétaires et obligations à court terme.
Horizon d’investissement : 1 à 3 ans
Objectif de performance : 3% par an
Volatilité cible : 2% par an
Évolution de nos allocations
Nos allocations ont été créées le 31 mars 2023 et reflètent notre approche d’investissement diversifiée et adaptée à différents horizons temporels. Nous n’investissons que dans des ETF et produits indiciels. Il s’agit de produits financiers n’ayant aucune contrainte de liquidité et offrant une grande flexibilité pour nos investisseurs.
Paramètres d’affichage
viewof periode =pilules({label:"Période",options: ["1 an","3 ans","5 ans","Origine"],value:"Origine"})viewof choix =pilules({label:"Allocation mise en avant",options: noms,value: noms[0],libelles: libellesAlloc})
debutPeriode = {const y = {"1 an":1,"3 ans":3,"5 ans":5}[periode];return y ? d3.utcYear.offset(derniere.date,-y) : data[0].date;}sousPeriode = data.filter(d => d.date>= debutPeriode)// L'allocation choisie est tracée en dernier pour passer au premier planordreTrace = [...noms.filter(n => n !== choix), choix]rebase = sousPeriode.flatMap(d => ordreTrace.map(n => ({date: d.date,allocation: n,valeur:100* d[n] / sousPeriode[0][n]})))html`<div class="bilan-titre">Performances sur la période</div><div class="kpis">${noms.map((n, i) => {const p = sousPeriode.at(-1)[n] / sousPeriode[0][n] -1;returnhtml`<div class="kpi ${["fonce","beige","vert"][i]}"> <div class="lbl">${n}</div><div class="val">${fmtPct(p)}</div> <div class="sub">${fmtPct(stats[n].cagr)} / an depuis l'origine</div> <div class="sub">${fmtNum(stats[n].sigma*100)} % de volatilité</div></div>`})}</div>`
Plot.plot({ width,height:600,marginLeft:65,marginBottom:45,y: {label:"↑ Base 100",grid:true},x: {label:null},color: {domain: noms,range: couleurs,legend:true},marks: [ Plot.ruleY([100], {stroke:"#2c4a42"}), Plot.lineY(rebase, {x:"date",y:"valeur",z:"allocation",stroke:"allocation",strokeWidth: d => d.allocation=== choix ?4:2,strokeOpacity: d => d.allocation=== choix ?1:0.75}), Plot.tip(rebase, Plot.pointerX({x:"date",y:"valeur",stroke:"allocation",title: d =>`${d.allocation}\n${d.date.toLocaleDateString("fr-FR")}\n${fmtNum(d.valeur)}`})) ]})
moisLib = ["Janv.","Févr.","Mars","Avr.","Mai","Juin","Juil.","Août","Sept.","Oct.","Nov.","Déc."]perfMensuelles = {// Dernière valeur de chaque moisconst finMois = d3.rollups(data, v => v.at(-1)[choix], d => d.date.getUTCFullYear() *12+ d.date.getUTCMonth()).sort((a, b) => a[0] - b[0]);const lignes =newMap();let prec = data[0][choix];// base : première valeur de la sérielet precAnnee = data[0][choix];let anneeCourante =null;for (const [cle, v] of finMois) {const an =Math.floor(cle /12), m = cle %12;if (an !== anneeCourante) { if (anneeCourante !==null) precAnnee = prec; anneeCourante = an; }if (!lignes.has(an)) lignes.set(an, {an,mois:Array(12).fill(null),annee:null,base: precAnnee});const l = lignes.get(an); l.mois[m] = v / prec -1; l.annee= v / l.base-1;// cumul depuis la fin de l'année précédente (YTD pour l'année en cours) prec = v; }return [...lignes.values()].sort((a, b) => b.an- a.an);}cellPerf = x => x ===null?html`<td class="vide"></td>`:html`<td class="${x >=0?"pos":"neg"}">${fmtPct(x)}</td>`html`<div class="bilan-titre">Performances mensuelles de IAM ${choix}</div><div class="table-wrap"><table class="table-mens"> <thead><tr><th>Année</th>${moisLib.map(m =>html`<th>${m}</th>`)}<th class="col-annee">Année</th></tr></thead> <tbody>${perfMensuelles.map(l =>html`<tr> <td class="an">${l.an}</td>${l.mois.map(cellPerf)}${l.annee===null?html`<td class="col-annee vide"></td>`:html`<td class="col-annee ${l.annee>=0?"pos":"neg"}">${fmtPct(l.annee)}</td>`} </tr>`)}</tbody></table></div><p class="note-sim">Performances calculées de fin de mois à fin de mois, hors frais et fiscalité. La première année démarre à la création de l'allocation, l'année en cours est arrêtée au ${derniere.date.toLocaleDateString("fr-FR")}.</p>`
Et si vous aviez investi…
Nous ne savons jamais vraiment quand c’est le bon moment pour investir, et lorsque vous avez décidé d’investir, il reste important de comparer les performances de vos allocations sur différentes périodes. C’est dans ce but que nous vous avons créé ce simulateur.
depart = data.find(d => d.date>= dateInv) ?? data[0]periodeSim = data.filter(d => d.date>= depart.date)anneesSim = (derniere.date- depart.date) / (365.25*864e5)finales = noms.map((n, i) => {const v = montant * derniere[n] / depart[n];let pic =-Infinity, dd =0;for (const d of periodeSim) { pic =Math.max(pic, d[n]); dd =Math.min(dd, d[n] / pic -1); }return {n, i, v,gain: v - montant,perf: v / montant -1,annu: anneesSim >=1?Math.pow(v / montant,1/ anneesSim) -1:null, dd};})dateDebutAjustee = dateInv < data[0].datehtml`<div class="bilan-titre">Valeur de votre placement aujourd'hui</div><p class="phrase-sim">Si vous aviez investi <strong>${fmtEur(montant)}</strong> le <strong>${depart.date.toLocaleDateString("fr-FR")}</strong>, votre placement vaudrait au ${derniere.date.toLocaleDateString("fr-FR")} :${dateDebutAjustee ?html`<br><em>La date saisie est antérieure au début des données : la simulation démarre au ${data[0].date.toLocaleDateString("fr-FR")}.</em>`:""}</p><div class="table-wrap"><table class="table-sim"> <thead><tr> <th>Allocation</th><th>Valeur aujourd'hui</th><th>Plus-value</th> <th>Performance</th><th>Perf. annualisée</th><th>Baisse max.</th> </tr></thead> <tbody>${finales.map(f =>html`<tr> <td><span class="pastille" style="background:${couleurs[f.i]}"></span>${f.n}</td> <td class="fort">${fmtEur(f.v)}</td> <td class="${f.gain>=0?"pos":"neg"}">${(f.gain>=0?"+":"") +fmtEur(f.gain)}</td> <td class="${f.perf>=0?"pos":"neg"}">${fmtPct(f.perf)}</td> <td>${f.annu===null?"–":fmtPct(f.annu)}</td> <td class="neg">${fmtPct(f.dd)}</td> </tr>`)}</tbody></table></div><p class="note-sim">Montant investi : ${fmtEur(montant)}. Performances hors fiscalité et frais. Perf. annualisée affichée pour une durée d'au moins un an.Baisse max. : plus forte perte subie entre un plus haut et un plus bas sur la période.</p>`
Projections
Cette section vous permet de projeter la valeur future de votre investissement en fonction de différentes hypothèses d’allocation et d’horizon temporel. Vous pouvez ajuster le capital de départ, la durée de l’investissement et l’allocation pour visualiser les scénarios défavorable, médian et favorable.
Hypothèses
viewof allocProj =pilules({label:"Allocation",options: noms,value: noms[1],libelles: libellesAlloc})viewof base =curseur({label:"Capital de départ (€)",min:1000,max:2000000,step:1000,value:100000})viewof horizon =curseur({label:"Horizon de projection",min:1,max:30,value:10,unite:"ans"})viewof histo =curseur({label:"Historique affiché",min:1,max:20,value:5,unite:"ans"})
proj = {const {mu, sigma} = stats[allocProj];const z = {p05:-1.6449,p25:-0.6745,p50:0,p75:0.6745,p95:1.6449};return d3.range(0, horizon *12+1).map(k => {const t = k /12, o = {date: d3.utcMonth.offset(derniere.date, k)};for (const [q, zq] ofObject.entries(z)) o[q] = base *Math.exp(.75* mu * t + zq * sigma *Math.sqrt(t));return o; });}fin = proj.at(-1)html`<div class="bilan-titre">Valeur estimée dans ${horizon} an${horizon >1?"s":""}</div><div class="kpis"> <div class="kpi vert"><div class="lbl">Scénario défavorable</div><div class="lbl">(Les pires 5 %)</div><div class="val">${fmtEur(fin.p05)}</div></div> <div class="kpi fonce"><div class="lbl">Scénario médian</div><div class="lbl"> </div><div class="val">${fmtEur(fin.p50)}</div></div> <div class="kpi beige"><div class="lbl">Scénario favorable</div><div class="lbl">(Les meilleurs 5 %)</div><div class="val">${fmtEur(fin.p95)}</div></div></div>`
md`Calibration sur l'historique : rendement annualisé **${fmtNum(stats[allocProj].cagr*0.75*100)} %** (*75% de la performance historique*), volatilité **${fmtNum(stats[allocProj].sigma*100)} %**. Zone foncée : 50 % des scénarios ; zone claire : 90 % ; pointillés : trajectoire médiane.`
Les performances passées ne préjugent pas des performances futures. Les projections reposent sur un modèle statistique simplifié (rendements lognormaux, paramètres constants estimés sur l’historique) et ne constituent ni une promesse ni une garantie de rendement.