Primary Risk
${currentData.title.split('&')[0].split('(')[0]}
${currentData.title}
${currentData.summary}
Expiration Scenario Analysis (Intrinsic Value)
| Stock Price at Expiry |
Option Value at Expiry |
Status |
${scenarioTableRows}
*This is a simplified illustration of intrinsic value and does not account for the premium paid for the option.
`;
downloadSection.classList.remove('hidden');
showTab(1);
};
generateBtn.addEventListener('click', analyzeRisk);
// --- PDF DOWNLOAD ---
const downloadPDF = () => {
if (!currentData) return;
const { jsPDF } = window.jspdf;
const pdf = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' });
const btnText = getElem('pdf-btn-text');
const btnSpinner = getElem('pdf-btn-spinner');
btnText.classList.add('hidden');
btnSpinner.classList.remove('hidden');
downloadPdfBtn.disabled = true;
try {
const pageWidth = pdf.internal.pageSize.getWidth();
const margin = 40;
let y = margin;
// --- Helper
const addSection = (title, body) => {
const splitText = pdf.splitTextToSize(body, pageWidth - margin*2);
if (y + 20 + splitText.length * 14 > pdf.internal.pageSize.getHeight() - margin) {
pdf.addPage(); y = margin;
}
pdf.setFont('helvetica', 'bold');
pdf.setFontSize(14);
pdf.text(title, margin, y);
y += 25;
pdf.setFont('helvetica', 'normal');
pdf.setFontSize(11);
pdf.text(splitText, margin, y);
y += splitText.length * 12 + 20;
}
// --- PDF Content ---
pdf.setFont('helvetica', 'bold');
pdf.setFontSize(20);
pdf.text("Options Expiry Risk Report", pageWidth / 2, y, { align: 'center' });
y += 30;
pdf.autoTable({
startY: y,
theme: 'plain',
body: [
['Stock Ticker:', userInputs.ticker, 'Current Price:', `$${userInputs.currentPrice.toFixed(2)}`],
['Option Type:', userInputs.optionType, 'Strike Price:', `$${userInputs.strikePrice.toFixed(2)}`],
['Expiry Date:', new Date(userInputs.expiryDate).toLocaleDateString('en-US'), 'Days to Expiry:', currentData.daysToExpire],
],
didDrawPage: (data) => {
y = data.cursor.y; // Update y to the position after the table
}
});
y += 20; // Add margin after table
addSection("Overall Risk Assessment", `${currentData.level}. ${currentData.summary}`);
pdf.autoTable({
startY: y,
head: [['Stock Price at Expiry', 'Option Value at Expiry', 'Status']],
body: [-0.10, -0.02, 0, 0.02, 0.10].map(change => {
const expiryPrice = userInputs.currentPrice * (1 + change);
let intrinsicValue = 0;
if (userInputs.optionType === 'Call') {
intrinsicValue = Math.max(0, expiryPrice - userInputs.strikePrice);
} else {
intrinsicValue = Math.max(0, userInputs.strikePrice - expiryPrice);
}
return [`$${expiryPrice.toFixed(2)}`, `$${intrinsicValue.toFixed(2)}`, intrinsicValue > 0 ? 'In-the-Money' : 'Out-of-the-Money'];
}),
theme: 'striped',
headStyles: { fillColor: [30, 64, 175] }
});
pdf.save(`Options-Risk-Report-${userInputs.ticker}.pdf`);
} catch(e) { console.error("PDF Generation failed:", e); }
finally {
btnText.classList.remove('hidden');
btnSpinner.classList.add('hidden');
downloadPdfBtn.disabled = false;
}
};
downloadPdfBtn.addEventListener('click', downloadPDF);
});