Illustrative Moving Average Crossover Signal Generator

Manually input price data to see how a simple SMA crossover strategy might generate signals.

** VERY IMPORTANT - PLEASE READ **
  • This tool is for educational and illustrative purposes ONLY and uses manually entered data for a short series.
  • It is **NOT a backtesting tool** and does not account for trading costs, slippage, or other real-world market factors.
  • Results are based purely on the data and simple SMA logic you provide and **DO NOT predict future performance or constitute investment advice.**
  • Technical analysis strategies have limitations and risks. Consult qualified financial professionals before trading.

1. Input Price Data

Enter at least as many data points as your longest SMA period. More data provides more context.

2. Strategy Parameters (Simple Moving Average Crossover)

Note: Still in a long position at end of data. Total P/L includes mark-to-market of open position.

` : ''} `; this.elements.resultsSection.style.display = 'block'; }, generatePDF: async function() { if (!window.jspdf || !window.html2canvas || this.simulationResults.tableData.length === 0) { alert('Please run the simulation first to generate a PDF.'); return; } await new Promise(resolve => setTimeout(resolve, 50)); const inputs = this.simulationResults.inputs; const tableData = this.simulationResults.tableData; const summary = this.simulationResults.summary; const pdfExportContainer = document.createElement('div'); pdfExportContainer.classList.add('sma-pdf-export-content'); pdfExportContainer.style.width = '900px'; // Wider for table let pdfHtml = `

SMA Crossover Signal Generator - Results

`; pdfHtml += `
Disclaimer: Illustrative tool, manual data. NOT backtesting or financial advice. Results are hypothetical.
`; pdfHtml += `

Strategy Parameters

`; pdfHtml += `

Short-Term SMA Period: ${inputs.shortPeriod}

`; pdfHtml += `

Long-Term SMA Period: ${inputs.longPeriod}

`; // pdfHtml += `

Price Data Entered: ${inputs.pricesEntered}

`; // Can be very long pdfHtml += `

Simulation Table

`; tableData.forEach(row => { pdfHtml += ``; }); pdfHtml += `
PeriodCloseShort SMA Long SMASignalAction Trade P/LCum. P/L
${row.period}${row.closePrice} ${row.shortSMA}${row.longSMA} ${row.signal} ${row.action} ${row.tradePL} ${row.cumulativePL}
`; pdfHtml += `

Summary

`; pdfHtml += `

Total P/L from completed trades: ${summary.totalPL.toFixed(2)}

`; pdfHtml += `

Number of Completed Trades: ${summary.numTrades}

`; pdfHtml += `

Win Rate: ${summary.winRate.toFixed(1)}%

`; if (this.elements.summaryResultsDiv.innerHTML.includes("Still in a long position")) { pdfHtml += `

Note: Still in a long position at end of data. Total P/L includes mark-to-market of open position.

`; } pdfHtml += `
`; pdfExportContainer.innerHTML = pdfHtml; document.body.appendChild(pdfExportContainer); try { const canvas = await html2canvas(pdfExportContainer, { scale: 1.2, useCORS: true, logging: false, windowWidth: pdfExportContainer.scrollWidth, windowHeight: pdfExportContainer.scrollHeight }); document.body.removeChild(pdfExportContainer); const imgData = canvas.toDataURL('image/png'); const { jsPDF } = window.jspdf; const pdf = new jsPDF({ orientation: 'l', unit: 'pt', format: 'a4' }); // Landscape const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = pdf.internal.pageSize.getHeight(); const imgProps = pdf.getImageProperties(imgData); let imgFinalWidth = pdfWidth - 40; let imgFinalHeight = (imgProps.height * imgFinalWidth) / imgProps.width; if (imgFinalHeight > pdfHeight - 40) { imgFinalHeight = pdfHeight - 40; imgFinalWidth = (imgProps.width * imgFinalHeight) / imgProps.height; } let currentY = 20; let heightProcessed = 0; const pageMargin = 20; const pageHeightAvailable = pdfHeight - 2 * pageMargin; while(heightProcessed < canvas.height) { let pageSegmentHeightOnCanvas = Math.min(canvas.height - heightProcessed, (pageHeightAvailable / imgFinalHeight) * canvas.height ); if (pageSegmentHeightOnCanvas <=0) break; const segmentCanvas = document.createElement('canvas'); segmentCanvas.width = canvas.width; segmentCanvas.height = pageSegmentHeightOnCanvas; const sctx = segmentCanvas.getContext('2d'); sctx.drawImage(canvas, 0, heightProcessed, canvas.width, pageSegmentHeightOnCanvas, 0, 0, canvas.width, pageSegmentHeightOnCanvas); const segmentImgData = segmentCanvas.toDataURL('image/png'); const segmentImgPropsPdf = pdf.getImageProperties(segmentImgData); let segmentRenderWidth = pdfWidth - 2 * pageMargin; let segmentRenderHeight = (segmentImgPropsPdf.height * segmentRenderWidth) / segmentImgPropsPdf.width; if(segmentRenderHeight > pageHeightAvailable) { segmentRenderHeight = pageHeightAvailable; segmentRenderWidth = (segmentImgPropsPdf.width * segmentRenderHeight) / segmentImgPropsPdf.height; } if(heightProcessed > 0) pdf.addPage(); pdf.addImage(segmentImgData, 'PNG', pageMargin, (pdfHeight - segmentRenderHeight) / 2, segmentRenderWidth, segmentRenderHeight); // Center vertically too heightProcessed += pageSegmentHeightOnCanvas; } pdf.save('SMA_Crossover_Simulation.pdf'); } catch (error) { console.error("Error generating PDF:", error); alert("An error occurred while generating PDF."); if (document.body.contains(pdfExportContainer)) document.body.removeChild(pdfExportContainer); } } }; document.addEventListener('DOMContentLoaded', function() { smaApp.init(); });
Scroll to Top