Convertible Arbitrage Strategy Backtester

Convertible Arbitrage Strategy Backtester

Convertible Arbitrage Strategy Setup

Define the convertible bond, underlying stock, and general parameters for your backtest.

Convertible Bond Details

General Parameters

Annualized Return: ${(backtestResultsSummary.annualizedReturn * 100).toFixed(2)}%

`; pdfHtmlContent += `

Annualized Volatility (Std Dev): ${(backtestResultsSummary.annualizedStdDev * 100).toFixed(2)}%

`; pdfHtmlContent += `

Sharpe Ratio: ${backtestResultsSummary.sharpeRatio.toFixed(2)}

`; pdfHtmlContent += `

Maximum Drawdown: ${(backtestResultsSummary.maxDrawdown * 100).toFixed(2)}%

`; } // 4. Monthly Performance Breakdown if (backtestPerformed && backtestCumulativeValues.length > 0) { pdfHtmlContent += `

Monthly Performance Breakdown

`; pdfHtmlContent += ``; for (let i = 0; i < monthlyPriceData.length; i++) { const monthData = monthlyPriceData[i]; const monthlyReturnDisplay = (i > 0) ? (backtestMonthlyReturns[i-1] * 100).toFixed(2) + '%' : 'N/A'; const cumulativeValueDisplay = backtestCumulativeValues[i].toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); pdfHtmlContent += ` `; } pdfHtmlContent += `
MonthBond Price ($)Stock Price ($)Monthly Return (%)Cumulative Value ($)
${i + 1} $${monthData.bondPrice.toFixed(2)} $${monthData.stockPrice.toFixed(2)} ${monthlyReturnDisplay} $${cumulativeValueDisplay}
`; } // Set the HTML content to the hidden container pdfRenderContainer.innerHTML = pdfHtmlContent; try { // Create a canvas from the hidden container const canvas = await html2canvas(pdfRenderContainer, { useCORS: true, scale: 2, // Increase scale for better resolution logging: false // Disable logging for cleaner console }); const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF('p', 'mm', 'a4'); // 'p' for portrait, 'mm' for millimeters, 'a4' size const imgWidth = 210; // A4 width in mm const pageHeight = 297; // A4 height in mm const imgHeight = canvas.height * imgWidth / canvas.width; let heightLeft = imgHeight; let position = 0; // Add image with calculated height for multi-page support pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight); heightLeft -= pageHeight; while (heightLeft >= 0) { position = heightLeft - imgHeight; pdf.addPage(); pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight); heightLeft -= pageHeight; } pdf.save('convertible_arbitrage_report.pdf'); } catch (error) { console.error('Error generating PDF:', error); alertUser('Failed to generate PDF. Please try again or check console for errors.'); } finally { // Clear the content of the hidden container pdfRenderContainer.innerHTML = ''; } }); // --- Custom Alert Function (instead of alert()) --- function alertUser(message) { // Implement a simple modal or message box instead of alert() // For now, using a simple console log for demonstration in browser console.warn("Alert (User-friendly):", message); // A basic in-page message display: let msgBox = document.getElementById('user-message-box'); if (!msgBox) { msgBox = document.createElement('div'); msgBox.id = 'user-message-box'; msgBox.className = 'fixed inset-x-0 top-0 flex items-center justify-center p-4 z-50'; msgBox.innerHTML = ` `; document.body.appendChild(msgBox); document.getElementById('close-user-message').addEventListener('click', () => { msgBox.classList.add('hidden'); }); } document.getElementById('user-message-text').textContent = message; msgBox.classList.remove('hidden'); setTimeout(() => { msgBox.classList.add('hidden'); }, 5000); // Hide after 5 seconds } // Initial rendering renderMonthlyDataInputs(); });
Scroll to Top