# Technical Indicators Module The Technical Indicators module provides a suite of common technical analysis tools. It is designed to work efficiently with pandas DataFrames, which is the standard data structure for time-series analysis in the TCP Trading Platform. ## Overview The module has been refactored into a dedicated package structure under `data/common/indicators/`. All calculation methods now expect a pandas DataFrame with a `DatetimeIndex` and the required OHLCV columns (`open`, `high`, `low`, `close`, `volume`). This change simplifies the data pipeline, improves performance through vectorization, and ensures consistency across the platform. ### Package Structure ``` data/common/indicators/ ├── __init__.py # Package exports ├── technical.py # TechnicalIndicators class implementation ├── result.py # IndicatorResult dataclass └── utils.py # Utility functions for configuration ``` The module implements five core technical indicators: - **Simple Moving Average (SMA)** - **Exponential Moving Average (EMA)** - **Relative Strength Index (RSI)** - **Moving Average Convergence Divergence (MACD)** - **Bollinger Bands** ## Key Features - **DataFrame-Centric Design**: Operates directly on pandas DataFrames for performance and simplicity. - **Vectorized Calculations**: Leverages pandas and numpy for high-speed computation. - **Flexible `calculate` Method**: A single entry point for calculating any supported indicator by name. - **Standardized Output**: All methods return a DataFrame containing the calculated indicator values, indexed by timestamp. - **Modular Architecture**: Clear separation between calculation logic, result types, and utilities. ## Usage Examples ### Importing the Required Components ```python from data.common.indicators import ( TechnicalIndicators, IndicatorResult, create_default_indicators_config, validate_indicator_config ) from data.common.data_types import OHLCVCandle ``` ### Preparing the DataFrame Before you can calculate indicators, you need a properly formatted pandas DataFrame. The `prepare_chart_data` utility is the recommended way to create one from a list of candle dictionaries. ```python from components.charts.utils import prepare_chart_data from data.common.indicators import TechnicalIndicators # Assume 'candles' is a list of OHLCV dictionaries from the database # candles = fetch_market_data(...) # Prepare the DataFrame df = prepare_chart_data(candles) # df is now ready for indicator calculations # It has a DatetimeIndex and the necessary OHLCV columns. ``` ### Basic Indicator Calculation Once you have a prepared DataFrame, you can calculate indicators directly. ```python # Initialize the calculator indicators = TechnicalIndicators() # Calculate a Simple Moving Average sma_df = indicators.sma(df, period=20) # Calculate an Exponential Moving Average ema_df = indicators.ema(df, period=12) # sma_df and ema_df are pandas DataFrames containing the results. ``` ### Using the `calculate` Method The most flexible way to compute an indicator is with the `calculate` method, which accepts the indicator type as a string. ```python # Calculate RSI using the generic method rsi_pkg = indicators.calculate('rsi', df, period=14) if rsi_pkg: rsi_df = rsi_pkg['data'] # Calculate MACD with custom parameters macd_pkg = indicators.calculate('macd', df, fast_period=10, slow_period=30, signal_period=8) if macd_pkg: macd_df = macd_pkg['data'] ``` ### Using Different Price Columns You can specify which price column (`open`, `high`, `low`, or `close`) to use for the calculation. ```python # Calculate SMA on the 'high' price sma_high_df = indicators.sma(df, period=20, price_column='high') # Calculate RSI on the 'open' price rsi_open_pkg = indicators.calculate('rsi', df, period=14, price_column='open') ``` ## Indicator Details The following details the parameters and the columns returned in the result DataFrame for each indicator. ### Simple Moving Average (SMA) - **Parameters**: `period` (int), `price_column` (str, default: 'close') - **Returned Columns**: `sma` ### Exponential Moving Average (EMA) - **Parameters**: `period` (int), `price_column` (str, default: 'close') - **Returned Columns**: `ema` ### Relative Strength Index (RSI) - **Parameters**: `period` (int), `price_column` (str, default: 'close') - **Returned Columns**: `rsi` ### MACD (Moving Average Convergence Divergence) - **Parameters**: `fast_period` (int), `slow_period` (int), `signal_period` (int), `price_column` (str, default: 'close') - **Returned Columns**: `macd`, `signal`, `histogram` ### Bollinger Bands - **Parameters**: `period` (int), `std_dev` (float), `price_column` (str, default: 'close') - **Returned Columns**: `upper_band`, `middle_band`, `lower_band` ## Data Structures ### IndicatorResult The `IndicatorResult` class (from `data.common.indicators.result`) contains technical indicator calculation results: ```python @dataclass class IndicatorResult: timestamp: datetime # Right-aligned candle timestamp symbol: str # Trading symbol (e.g., 'BTC-USDT') timeframe: str # Candle timeframe (e.g., '1m', '5m') values: Dict[str, float] # Indicator values metadata: Optional[Dict[str, Any]] = None # Calculation metadata ``` ### Configuration Management The module provides utilities for managing indicator configurations (from `data.common.indicators.utils`): ```python # Create default configurations config = create_default_indicators_config() # Validate a configuration is_valid = validate_indicator_config({ 'type': 'sma', 'period': 20, 'price_column': 'close' }) ``` ### Integration with TCP Platform The indicators module is designed to work seamlessly with the platform's components: ```python from data.common.indicators import TechnicalIndicators from data.common.data_types import OHLCVCandle from components.charts.utils import prepare_chart_data # Initialize calculator indicators = TechnicalIndicators() # Calculate indicators results = indicators.calculate_multiple_indicators(df, { 'sma_20': {'type': 'sma', 'period': 20}, 'rsi_14': {'type': 'rsi', 'period': 14} }) # Access results for indicator_name, indicator_results in results.items(): for result in indicator_results: print(f"{indicator_name}: {result.values}") ``` ## Integration with the TCP Platform The refactored `TechnicalIndicators` module is now tightly integrated with the `ChartBuilder`, which handles all data preparation and calculation automatically when indicators are added to a chart. For custom analysis or strategy development, you can use the class directly as shown in the examples above. The key is to always start with a properly prepared DataFrame using `prepare_chart_data`. ## Performance Considerations ### Memory Usage - Process indicators in batches for large datasets - Use appropriate period lengths to balance accuracy and performance - Consider data retention policies for historical indicator values ### Calculation Frequency - Calculate indicators only when new complete candles are available - Cache recent indicator values to avoid recalculation - Use incremental updates for real-time scenarios ### Optimization Tips - Use `calculate_multiple_indicators()` for efficiency when computing multiple indicators - Limit the number of historical candles to what's actually needed - Consider using different timeframes for different indicators ## Error Handling The module includes comprehensive error handling: - **Insufficient Data**: Returns empty results when not enough data is available - **Invalid Configuration**: Validates configuration parameters before calculation - **Data Quality Issues**: Handles NaN values and missing data gracefully - **Type Errors**: Converts data types safely with fallback values ## Testing The module includes comprehensive unit tests covering: - All indicator calculations with known expected values - Sparse data handling scenarios - Edge cases (insufficient data, invalid parameters) - Configuration validation - Multiple indicator batch processing Run tests with: ```bash uv run pytest tests/test_indicators.py -v ``` ## Future Enhancements Potential future additions to the indicators module: - **Additional Indicators**: Stochastic, Williams %R, Commodity Channel Index - **Custom Indicators**: Framework for user-defined indicators - **Performance Metrics**: Calculation timing and memory usage statistics - **Streaming Updates**: Incremental indicator updates for real-time scenarios - **Parallel Processing**: Multi-threaded calculation for large datasets ## See Also - [Aggregation Strategy Documentation](aggregation-strategy.md) - [Data Types Documentation](data-types.md) - [Database Schema Documentation](database-schema.md) - [API Reference](api-reference.md) ## `TechnicalIndicators` Class The main class for calculating technical indicators. - **RSI**: `rsi(df, period=14, price_column='close')` - **MACD**: `macd(df, fast_period=12, slow_period=26, signal_period=9, price_column='close')` - **Bollinger Bands**: `bollinger_bands(df, period=20, std_dev=2.0, price_column='close')` ### `calculate_multiple_indicators` Calculates multiple indicators in a single pass for efficiency. ```python # Configuration for multiple indicators indicators_config = { 'sma_20': {'type': 'sma', 'period': 20}, 'ema_50': {'type': 'ema', 'period': 50}, 'rsi_14': {'type': 'rsi', 'period': 14} } # Calculate all indicators all_results = ti.calculate_multiple_indicators(candles, indicators_config) print(f"SMA results: {len(all_results['sma_20'])}") print(f"RSI results: {len(all_results['rsi_14'])}") ``` ## Sparse Data Handling The `TechnicalIndicators` class is designed to handle sparse OHLCV data, which is a common scenario in real-time data collection.