Iron Condor P&L Calculator

Iron Condor Profit & Loss Calculator

Define Your Iron Condor

Bull Put Spread

Lowest strike price (long put).

Higher put strike (short put).

Premium received from P2 minus premium paid for P1.

Bear Call Spread

Lower call strike (short call).

Highest strike price (long call).

Premium received from C1 minus premium paid for C2.

Each contract represents 100 shares of the underlying asset.

Net Premium (per share): $${(results.params.putPremium + results.params.callPremium).toFixed(2)}

Number of Contracts: ${results.params.numContracts}

Metric Value
Total Net Credit Received: ${formatCurrency(results.netCredit)}
Maximum Profit: ${formatCurrency(results.maxProfit)}
Maximum Loss: ${formatCurrency(Math.abs(results.maxLoss))}
Lower Breakeven Point: ${formatCurrency(results.lowerBreakeven)}
Upper Breakeven Point: ${formatCurrency(results.upperBreakeven)}

Max Profit: Occurs if the underlying price at expiration is between the short put strike (P2) and the short call strike (C1).
Max Loss: Occurs if the underlying price at expiration is below the long put strike (P1) or above the long call strike (C2).
Breakeven Points: The underlying prices at expiration where the trade results in zero profit or loss.
Disclaimer: This tool provides *simulated* P&L calculations for educational and illustrative purposes only. It does not account for commissions, slippage, dividends, or early assignment risk. Options trading involves substantial risk.

`; resultsOutput.innerHTML = tableHtml; } /** * Renders the P&L chart. * @param {Object} results - Results from calculatePnL. */ function renderPnLChart(results) { if (!results || !results.params) { chartPlaceholder.classList.remove('hidden'); if (pnlChartInstance) { pnlChartInstance.destroy(); pnlChartInstance = null; } return; } chartPlaceholder.classList.add('hidden'); // Hide placeholder if chart can be rendered const ctx = document.getElementById('pnlChart').getContext('2d'); // Destroy existing chart instance if it exists to prevent overlap if (pnlChartInstance) { pnlChartInstance.destroy(); } const { p1, p2, c1, c2 } = results.params; // Determine price range for the chart (a bit wider than the outer strikes) const minPrice = Math.floor(p1 * 0.9) - 5; const maxPrice = Math.ceil(c2 * 1.1) + 5; const priceRange = []; for (let p = minPrice; p <= maxPrice; p += 0.5) { priceRange.push(p); } const pnlData = priceRange.map(price => calculatePnLAtPrice(price, results.params)); pnlChartInstance = new Chart(ctx, { type: 'line', data: { labels: priceRange.map(p => p.toFixed(2)), datasets: [ { label: 'P&L at Expiration', data: pnlData, borderColor: '#3B82F6', // Blue 500 backgroundColor: 'rgba(59, 130, 246, 0.2)', // Light blue fill borderWidth: 2, tension: 0.1, // Smooth curve pointRadius: 0, // No points for cleaner line fill: false, }, { label: 'Zero Line', data: new Array(priceRange.length).fill(0), borderColor: '#9CA3AF', // Gray 400 borderWidth: 1, borderDash: [5, 5], pointRadius: 0, fill: false, stepped: false // Ensure it's a straight line } ] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: true, position: 'top', labels: { font: { size: 14, family: 'Inter', }, color: '#333' } }, title: { display: true, text: 'Iron Condor P&L Profile at Expiration', font: { size: 18, family: 'Inter', weight: 'bold' }, color: '#1F2937' }, tooltip: { mode: 'index', intersect: false, callbacks: { label: function(context) { let label = context.dataset.label || ''; if (label) { label += ': '; } if (context.parsed.y !== null) { label += `$${context.parsed.y.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; } return label; } } }, annotation: { // For vertical lines at strikes annotations: { p1Line: { type: 'line', xMin: p1, xMax: p1, borderColor: 'rgba(255, 99, 132, 0.7)', borderWidth: 2, label: { content: `P1: ${p1}`, enabled: true, position: 'start', font: { size: 10, family: 'Inter' } } }, p2Line: { type: 'line', xMin: p2, xMax: p2, borderColor: 'rgba(75, 192, 192, 0.7)', borderWidth: 2, label: { content: `P2: ${p2}`, enabled: true, position: 'start', font: { size: 10, family: 'Inter' } } }, c1Line: { type: 'line', xMin: c1, xMax: c1, borderColor: 'rgba(75, 192, 192, 0.7)', borderWidth: 2, label: { content: `C1: ${c1}`, enabled: true, position: 'end', font: { size: 10, family: 'Inter' } } }, c2Line: { type: 'line', xMin: c2, xMax: c2, borderColor: 'rgba(255, 99, 132, 0.7)', borderWidth: 2, label: { content: `C2: ${c2}`, enabled: true, position: 'end', font: { size: 10, family: 'Inter' } } } } } }, scales: { y: { beginAtZero: false, title: { display: true, text: 'Profit / Loss ($)', font: { size: 14, family: 'Inter' }, color: '#333' }, ticks: { callback: function(value) { return '$' + value.toLocaleString(); }, font: { family: 'Inter' } } }, x: { title: { display: true, text: 'Underlying Price at Expiration ($)', font: { size: 14, family: 'Inter' }, color: '#333' }, ticks: { font: { family: 'Inter' } } } } } }); } /** * Handles the PDF download functionality. * Captures the results output and chart canvases to generate a PDF report. */ window.downloadPdf = async function() { if (typeof html2canvas === 'undefined' || typeof jspdf === 'undefined' || typeof jspdf.jsPDF === 'undefined') { displayMessage('PDF generation libraries not loaded. Please try again or refresh.'); return; } hideMessage(); const { jsPDF } = jspdf; const doc = new jsPDF('p', 'pt', 'a4'); // Temporarily show the charts tab to ensure they render on canvas before capturing const chartsTabWasHidden = chartsTab.classList.contains('hidden'); if (chartsTabWasHidden) { chartsTab.classList.remove('hidden'); } // Elements to capture for PDF: results table and then the chart canvas const elementsToCapture = [ document.getElementById('resultsOutput'), document.getElementById('pnlChart') ]; let yPos = 40; doc.setFontSize(22); doc.setTextColor(51, 51, 51); doc.text('Iron Condor P&L Report', doc.internal.pageSize.getWidth() / 2, yPos, { align: 'center' }); yPos += 30; doc.setFontSize(12); doc.setTextColor(100, 100, 100); doc.text(`Generated on: ${new Date().toLocaleDateString()}`, doc.internal.pageSize.getWidth() / 2, yPos, { align: 'center' }); yPos += 40; for (const element of elementsToCapture) { try { // For chart canvases, ensure they are rendered. For other elements, ensure visibility if needed. let elementToRender = element; if (element.tagName.toLowerCase() === 'canvas') { if (element.id === 'pnlChart' && pnlChartInstance === null) { console.warn(`Chart ${element.id} not yet rendered for PDF capture. Skipping.`); continue; } } else { // For non-canvas elements, ensure they are visible for html2canvas const wasHidden = element.classList.contains('hidden'); if (wasHidden) { element.classList.remove('hidden'); } // Capture the element as a canvas elementToRender = await html2canvas(element, { scale: 2, // Increase scale for better resolution in PDF useCORS: true, // Required for images/fonts loaded from other origins if any backgroundColor: '#ffffff' }); if (wasHidden) { element.classList.add('hidden'); // Restore hidden state } } const imgData = elementToRender.toDataURL('image/png'); const imgWidth = 550; // Desired width for image in PDF const imgHeight = (elementToRender.height * imgWidth) / elementToRender.width; if (yPos + imgHeight > doc.internal.pageSize.getHeight() - 40) { doc.addPage(); yPos = 40; } doc.addImage(imgData, 'PNG', (doc.internal.pageSize.getWidth() - imgWidth) / 2, yPos, imgWidth, imgHeight); yPos += imgHeight + 30; } catch (error) { console.error('Error capturing element for PDF:', error); displayMessage('Failed to generate part of the PDF. Please ensure all data is loaded and visible before downloading.'); } } // Restore charts tab hidden state if it was temporarily shown if (chartsTabWasHidden) { chartsTab.classList.add('hidden'); } doc.save('Iron_Condor_PNL_Report.pdf'); }; // Initial setup: Show the input tab when the DOM is ready showTab('input'); });
Scroll to Top