"""
TimeSeriesAnomalyDetector
Generated by Eden via recursive self-improvement
2025-10-27 23:40:37.208660
"""

class TimeSeriesAnomalyDetector:
    """Detects anomalies in time series data using statistical measures on sliding windows.
    
    Attributes:
        window_size (int): Number of previous points to consider for anomaly detection.
        step_size (int): How many steps to move the window at each iteration.
        trained_data (list): Time series data used for training.
        
    Methods:
        __init__: Initializes with window and step sizes.
        train: Trains the detector on provided time series data.
        detect_anomalies: Detects anomalies in new or existing data points.
    """

    def __init__(self, window_size=20, step_size=1):
        """Initializes the anomaly detector with specified window and step sizes."""
        self.window_size = window_size
        self.step_size = step_size
        self.trained_data = []
        
    def train(self, data):
        """Trains the detector using provided time series data.
        
        Args:
            data (list): Time series data to train on. Must be a list of numerical values.
        """
        if len(data) < self.window_size:
            raise ValueError("Data must be longer than window size for training.")
            
        self.trained_data = data
        
    def detect_anomalies(self, new_data_point):
        """Detects anomalies in new data points based on recent history.
        
        Args:
            new_data_point (float): New data point to check for anomaly.
            
        Returns:
            bool: True if the data point is an anomaly, False otherwise.
        """
        current_index = len(self.trained_data)
        window_start = max(0, current_index - self.window_size)
        
        # Get previous values within the window
        window = self.trained_data[window_start : current_index]
        
        # Take a step back for each check based on step size
        steps_back = range(self.step_size, len(window), self.step_size)
        for i in reversed(steps_back):
            prev_values = window[:i]
            
            if len(prev_values) == 0:
                continue
                
            mean = sum(prev_values) / len(prev_values)
            std = (sum([(x - mean)**2 for x in prev_values]) / len(prev_values))**0.5
            
            # Z-score calculation
            z_score = abs(new_data_point - mean) / std if std != 0 else float('inf')
            
            if z_score > 3:  # Common threshold for anomalies
                return True
                
        return False

# Example usage:
detector = TimeSeriesAnomalyDetector(window_size=20, step_size=5)
training_data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 
                11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
detector.train(training_data)

# Test normal point
print(detector.detect_anomalies(21))  # Output: False

# Test anomaly (outside expected range)
print(detector.detect_anomalies(40))  # Output: True

# Update data and test new point
training_data.append(25)
detector.train(training_data)
print(detector.detect_anomalies(30))  # Output: True