Liability-Driven Investment (LDI) Strategy Model (Conceptual Simulator)

Define Future Liabilities

%

Asset Portfolio Construction

$

Asset Classes & Characteristics

Total Allocation: 0%

LDI Analysis & Funding Status

Analysis results will appear here.

Funding Status Chart will appear here.

Interest Rate Scenario Analysis

pp
E.g., 1.0 for a +1% (100bps) rate increase, -0.5 for a -0.5% (50bps) decrease. Assumes a parallel shift.

Chart appears here.

'; return; } const res = ldism_model.analysisResults; const fundingStatusClass = res.fundingRatio >= 100 ? 'ldism_funded' : 'ldism_underfunded'; resultsSection.innerHTML = `

LDI Funding Status

Present Value of Liabilities (PVL): ${ldism_formatCurrency(res.pvl)}
Present Value of Assets (PVA): ${ldism_formatCurrency(res.pva)}
Funding Ratio (PVA / PVL): ${ldism_formatPercent(res.fundingRatio)}
Surplus / (Deficit): ${ldism_formatCurrency(res.surplusDeficit)}

Duration Matching (Conceptual)

Liability Duration: ${ldism_formatYears(res.liabilityDuration)}
Asset Portfolio Duration: ${ldism_formatYears(res.portfolioDuration)}
Duration Gap (Assets - Liabilities): ${ldism_formatYears(res.portfolioDuration - res.liabilityDuration)}
`; ldism_renderFundingChart(res.pva, res.pvl, chartContainer); } function ldism_displayScenarioResults() { const resultsSection = ldism_getEl('ldism_scenarioResultsSection'); if (!resultsSection) { console.error("Scenario results display element missing."); return; } if (!ldism_model.scenarioResults) { resultsSection.innerHTML = "

Run a scenario to see impact.

"; resultsSection.style.display = 'none'; return; } const res = ldism_model.scenarioResults; const baseRes = ldism_model.analysisResults; // For comparison const fundingStatusClass = res.fundingRatio >= 100 ? 'ldism_funded' : 'ldism_underfunded'; resultsSection.innerHTML = `

Scenario Impact (Rate Change: ${(res.rateChangeApplied || 0).toFixed(1)} pp)

New Present Value of Liabilities (PVL): ${ldism_formatCurrency(res.pvl)}
New Present Value of Assets (PVA): ${ldism_formatCurrency(res.pva)}
New Funding Ratio: ${ldism_formatPercent(res.fundingRatio)}
New Surplus / (Deficit): ${ldism_formatCurrency(res.surplusDeficit)}

Change in Funding Ratio: ${(res.fundingRatio - baseRes.fundingRatio).toFixed(2)} pp
Change in Surplus/Deficit: ${ldism_formatCurrency(res.surplusDeficit - baseRes.surplusDeficit)}
`; resultsSection.style.display = 'block'; } function ldism_renderFundingChart(pva, pvl, container) { container.innerHTML = ''; // Clear previous const svgWidth = Math.min(400, (ldism_getEl('ldismContainer_main').offsetWidth || 400) - 80); const svgHeight = 200; const m = {top: 20, right: 20, bottom: 30, left: 60}; const w = svgWidth - m.left - m.right; const h = svgHeight - m.top - m.bottom; const maxValue = Math.max(pva, pvl, 0); const barWidth = w / 3; const yScale = val => h - ((val / (maxValue === 0 ? 1 : maxValue)) * h); container.innerHTML = ` {/* X-axis base */} {/* Y-axis */} ${ldism_formatCurrency(maxValue,0)} $0 PVA: ${ldism_formatCurrency(pva)} Assets (PVA) PVL: ${ldism_formatCurrency(pvl)} Liabilities (PVL) `; } // --- PDF Generation --- function ldism_downloadPDF() { if (!ldism_model.analysisResults) { alert("Please run analysis first."); return; } if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF === 'undefined') { alert('Core PDF library (jsPDF) is not loaded.'); console.error('jsPDF library not found.'); return; } const { jsPDF: JSPDF } = window.jspdf; const doc = new JSPDF(); if (typeof doc.autoTable !== 'function') { alert('PDF Table plugin (jsPDF-AutoTable) not loaded. Tables may be missing.'); console.error('doc.autoTable is not a function.'); } let y = 15; const m = 15; const cw = doc.internal.pageSize.getWidth() - (2 * m); const baseRes = ldism_model.analysisResults; const scenarioRes = ldism_model.scenarioResults; // Might be null const inputs = ldism_model; // Use main model for input section function addLine(text, size, style = 'normal', indent = 0, spacing = 2.5) { if (y > 275) { doc.addPage(); y = m; } doc.setFontSize(size); doc.setFont(undefined, style); const lines = doc.splitTextToSize(text, cw - indent); doc.text(lines, m + indent, y); y += (lines.length * (size * 0.35)) + spacing; } addLine(`LDI Strategy Model Report`, 16, 'bold', 0, 5); addLine(`Report Date: ${new Date().toLocaleDateString()}`, 9, 'italic', 0, 5); addLine("Liability Profile:", 12, 'bold', 0, 3); addLine(`- Discount Rate: ${ldism_formatPercent(inputs.discountRate)}`, 9); if(typeof doc.autoTable === 'function' && inputs.liabilities.length > 0) { const liaHead = [['Liability', 'Amount ($)', 'Years to Payout']]; const liaBody = inputs.liabilities.map(l => [l.name, l.amount.toFixed(0), l.yearsToPayout.toFixed(1)]); doc.autoTable({startY: y, head: liaHead, body: liaBody, theme: 'striped', headStyles:{fillColor:[55,65,81]}, styles:{fontSize:8.5}}); y = doc.lastAutoTable.finalY + 5; } else { inputs.liabilities.forEach(l=> addLine(` - ${l.name}: ${ldism_formatCurrency(l.amount)} in ${l.yearsToPayout} yrs`, 9)); y+=2;} addLine("Asset Portfolio:", 12, 'bold', 0, 3); addLine(`- Initial Market Value (PVA): ${ldism_formatCurrency(inputs.portfolioInitialValue)}`, 9); if(typeof doc.autoTable === 'function' && inputs.assetClasses.length > 0) { const assetHead = [['Asset Class', 'Allocation (%)', 'Exp. Return (%)', 'Duration (Yrs)']]; const assetBody = inputs.assetClasses.map(ac => [ac.name, ac.allocationPercent.toFixed(1), ac.expectedReturn.toFixed(1), ac.durationYears.toFixed(1)]); doc.autoTable({startY: y, head: assetHead, body: assetBody, theme: 'striped', headStyles:{fillColor:[55,65,81]}, styles:{fontSize:8.5}}); y = doc.lastAutoTable.finalY + 5; } else { addLine(" Asset table could not be generated (plugin/data issue).", 8, 'italic'); y+=5;} addLine("Base LDI Analysis:", 14, 'bold', 0, 4); let baseData = [ ["Present Value of Liabilities (PVL):", ldism_formatCurrency(baseRes.pvl)], ["Present Value of Assets (PVA):", ldism_formatCurrency(baseRes.pva)], ["Funding Ratio (PVA / PVL):", ldism_formatPercent(baseRes.fundingRatio)], ["Surplus / (Deficit):", ldism_formatCurrency(baseRes.surplusDeficit)], ["Liability Duration:", ldism_formatYears(baseRes.liabilityDuration)], ["Asset Portfolio Duration:", ldism_formatYears(baseRes.portfolioDuration)], ["Duration Gap (Assets - Liabilities):", ldism_formatYears(baseRes.portfolioDuration - baseRes.liabilityDuration)], ]; if(typeof doc.autoTable === 'function') { doc.autoTable({startY: y, body: baseData, theme:'plain', styles:{fontSize:9, cellPadding:1.2}, columnStyles:{0:{fontStyle:'bold'}}}); y = doc.lastAutoTable.finalY + 6; } else { baseData.forEach(row => addLine(`${row[0]} ${row[1]}`, 9)); y+=5; } if (scenarioRes) { addLine(`Interest Rate Scenario Analysis (Rate Change: ${(scenarioRes.rateChangeApplied || 0).toFixed(1)} pp):`, 14, 'bold', 0, 4); let scenarioData = [ ["New PVL:", ldism_formatCurrency(scenarioRes.pvl)], ["New PVA:", ldism_formatCurrency(scenarioRes.pva)], ["New Funding Ratio:", ldism_formatPercent(scenarioRes.fundingRatio)], ["New Surplus / (Deficit):", ldism_formatCurrency(scenarioRes.surplusDeficit)], ["Change in Funding Ratio:", `${(scenarioRes.fundingRatio - baseRes.fundingRatio).toFixed(2)} pp`], ["Change in Surplus/Deficit:", ldism_formatCurrency(scenarioRes.surplusDeficit - baseRes.surplusDeficit)], ]; if(typeof doc.autoTable === 'function') { doc.autoTable({startY: y, body: scenarioData, theme:'plain', styles:{fontSize:9, cellPadding:1.2}, columnStyles:{0:{fontStyle:'bold'}}}); y = doc.lastAutoTable.finalY + 7; } else { scenarioData.forEach(row => addLine(`${row[0]} ${row[1]}`, 9)); y+=5; } } addLine("Note: This is a conceptual LDI simulator based on user-defined inputs and simplified duration/PV calculations. It does not constitute financial advice.", 7, 'italic'); doc.save(`LDI_Strategy_Analysis.pdf`); }
Scroll to Top