""" Exponential Moving Average (EMA) indicator implementation. """ from typing import List import pandas as pd from ..base import BaseIndicator from ..result import IndicatorResult class EMAIndicator(BaseIndicator): """ Exponential Moving Average (EMA) technical indicator. Calculates weighted moving average giving more weight to recent prices. Handles sparse data appropriately without interpolation. """ def calculate(self, df: pd.DataFrame, period: int = 20, price_column: str = 'close') -> List[IndicatorResult]: """ Calculate Exponential Moving Average (EMA). Args: df: DataFrame with OHLCV data period: Number of periods for moving average (default: 20) price_column: Price column to use ('open', 'high', 'low', 'close') Returns: List of indicator results with EMA values """ # Validate input data if not self.validate_dataframe(df, period): return [] try: # Calculate EMA using pandas exponential weighted moving average df['ema'] = df[price_column].ewm(span=period, adjust=False).mean() # Convert results to IndicatorResult objects results = [] for i, (timestamp, row) in enumerate(df.iterrows()): # Only return results after minimum period if i >= period - 1 and not pd.isna(row['ema']): result = IndicatorResult( timestamp=timestamp, symbol=row['symbol'], timeframe=row['timeframe'], values={'ema': row['ema']}, metadata={'period': period, 'price_column': price_column} ) results.append(result) return results except Exception as e: if self.logger: self.logger.error(f"Error calculating EMA: {e}") return []