Index: ${anomaly.index}, Value: ${anomaly.value.toFixed(2)}
${anomaly.description}
`;
anomalyListUl.appendChild(listItem);
});
}
}
// Function to generate an overall anomaly summary
function generateOverallSummary(anomalies, totalDataPoints) {
let summaryText = '';
if (anomalies.length === 0) {
summaryText = 'The analysis did not identify any significant anomalies in the provided data series based on the current detection parameters. The market appears to be stable and predictable within these thresholds.';
} else {
const numSpikes = anomalies.filter(a => a.type.includes('Spike') || a.type.includes('Surge')).length;
const numDrops = anomalies.filter(a => a.type.includes('Drop')).length;
const highSeverityCount = anomalies.filter(a => a.severity === 'high').length;
const anomalyPercentage = (anomalies.length / totalDataPoints * 100).toFixed(1);
summaryText = `The system detected
${anomalies.length} significant anomalies across ${totalDataPoints} data points, representing approximately
${anomalyPercentage}% of the series. `;
if (numSpikes > 0 && numDrops > 0) {
summaryText += `There were ${numSpikes} notable upward movements (spikes/surges) and ${numDrops} distinct downward movements (drops). `;
} else if (numSpikes > 0) {
summaryText += `The detected anomalies were predominantly upward movements (spikes/surges), totaling ${numSpikes}. `;
} else if (numDrops > 0) {
summaryText += `The detected anomalies were primarily downward movements (drops), totaling ${numDrops}. `;
}
if (highSeverityCount > 0) {
summaryText += `
${highSeverityCount} of these anomalies were classified as high severity, indicating strong deviations from the expected patterns. These instances warrant closer investigation for potential market events or data irregularities.`;
} else {
summaryText += `Most anomalies were of moderate or low severity, suggesting localized deviations rather than extreme market disruptions.`;
}
}
overallAnomalySummaryPara.innerHTML = summaryText;
}
// Function to reset the tool
window.resetTool = function() {
marketDataInput.value = '';
rollingWindowInput.value = '5';
stdDevThresholdInput.value = '2.5';
percentChangeThresholdInput.value = '10.0';
clearError();
resultsSection.style.display = 'none';
anomalyChartSvg.innerHTML = ''; // Clear chart
anomalyListUl.innerHTML = '
No significant anomalies detected based on current parameters.';
overallAnomalySummaryPara.innerHTML = 'No analysis performed yet. Please input data and click \'Detect Anomalies\'.';
};
// PDF Download Functionality
window.downloadPdf = function() {
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
doc.setFontSize(22);
doc.text("Market Anomaly Detection Report", 105, 20, null, null, "center");
doc.setFontSize(12);
doc.text(`Report Date: ${new Date().toLocaleDateString()}`, 14, 35);
doc.text(`Rolling Window Size: ${rollingWindowInput.value} periods`, 14, 42);
doc.text(`Std Dev Threshold: ${stdDevThresholdInput.value}x`, 14, 49);
doc.text(`Percent Change Threshold: ${percentChangeThresholdInput.value}%`, 14, 56);
let yOffset = 70;
// Input Data Section
doc.setFontSize(16);
doc.text("Input Market Data Series", 14, yOffset);
yOffset += 10;
doc.setFontSize(10);
doc.text(`Data: ${marketDataInput.value.replace(/,/g, ', ')}`, 14, yOffset, { maxWidth: 180 });
yOffset += doc.getTextDimensions(`Data: ${marketDataInput.value}`, { maxWidth: 180 }).h + 20;
// Chart Placeholder
doc.setFontSize(16);
doc.text("Market Data Series with Anomalies (Visualized On-Screen)", 14, yOffset);
yOffset += 10;
doc.setFontSize(10);
doc.text("The interactive chart on the tool visually highlights the detected anomalies.", 14, yOffset);
doc.text("Please refer to the online tool for the full visual representation.", 14, yOffset + 5);
yOffset += 20;
// Detected Anomalies List
doc.setFontSize(16);
doc.text("Detected Anomalies", 14, yOffset);
yOffset += 10;
const anomaliesForPdf = [];
const anomalyItems = anomalyListUl.querySelectorAll('.anomaly-item');
if (anomalyItems.length === 0 || anomalyListUl.querySelector('.no-anomalies-detected')) {
anomaliesForPdf.push([{ content: "No significant anomalies detected based on current parameters.", styles: { fontStyle: 'italic', textColor: [102, 102, 102], halign: 'center' } }]);
} else {
anomalyItems.forEach(item => {
const type = item.querySelector('.type').textContent;
const magnitude = item.querySelector('strong').textContent;
const indexValue = item.querySelector('p:nth-child(2)').textContent;
const description = item.querySelector('p:nth-child(3)').textContent;
anomaliesForPdf.push([{ content: `${type} (Magnitude: ${magnitude})`, styles: { fontStyle: 'bold', fillColor: [252, 246, 246], textColor: [220, 53, 69] } }]);
anomaliesForPdf.push([indexValue]);
anomaliesForPdf.push([description]);
anomaliesForPdf.push(['']); // Empty row for spacing
});
}
doc.autoTable({
startY: yOffset,
body: anomaliesForPdf,
theme: 'plain',
styles: {
font: 'helvetica',
fontSize: 10,
cellPadding: 3,
valign: 'top',
lineColor: [230, 230, 230],
lineWidth: 0.1
}
});
yOffset = doc.autoTable.previous.finalY + 20;
// Overall Anomaly Summary
doc.setFontSize(16);
doc.text("Overall Anomaly Profile", 14, yOffset);
yOffset += 10;
doc.setFontSize(11);
const summaryText = overallAnomalySummaryPara.innerHTML.replace(/
(.*?)<\/strong>/g, '$1'); // Remove strong tags for PDF
doc.text(summaryText, 14, yOffset, { maxWidth: 180, lineHeightFactor: 1.2 });
doc.save(`Market_Anomaly_Detector_Report.pdf`);
};
// Initial example data and analysis on load
marketDataInput.value = '100, 102, 101, 103, 105, 120, 104, 106, 108, 90, 107, 109, 110, 112, 135, 111, 113, 114, 115, 80, 116, 118, 120, 119, 121, 123, 122, 124, 126, 125, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200';
rollingWindowInput.value = '7';
stdDevThresholdInput.value = '2.7';
percentChangeThresholdInput.value = '12.0';
detectAnomalies(); // Run analysis on page load with example data
});