- Updated all technical indicators to return pandas DataFrames instead of lists, improving consistency and usability. - Modified the `calculate` method in `TechnicalIndicators` to directly return DataFrames with relevant indicator values. - Enhanced the `data_integration.py` to utilize the new DataFrame outputs for better integration with charting. - Updated documentation to reflect the new DataFrame-centric approach, including usage examples and output structures. - Improved error handling to ensure empty DataFrames are returned when insufficient data is available. These changes streamline the indicator calculations and improve the overall architecture, aligning with project standards for maintainability and performance.
112 lines
3.3 KiB
Python
112 lines
3.3 KiB
Python
"""
|
|
Base classes and interfaces for technical indicators.
|
|
|
|
This module provides the foundation for all technical indicators
|
|
with common functionality and type definitions.
|
|
"""
|
|
|
|
from abc import ABC, abstractmethod
|
|
from typing import List, Dict, Any
|
|
import pandas as pd
|
|
from utils.logger import get_logger
|
|
|
|
from .result import IndicatorResult
|
|
from ..data_types import OHLCVCandle
|
|
|
|
|
|
|
|
class BaseIndicator(ABC):
|
|
"""
|
|
Abstract base class for all technical indicators.
|
|
|
|
Provides common functionality and enforces consistent interface
|
|
across all indicator implementations.
|
|
"""
|
|
|
|
def __init__(self, logger=None):
|
|
"""
|
|
Initialize base indicator.
|
|
|
|
Args:
|
|
logger: Optional logger instance
|
|
"""
|
|
if logger is None:
|
|
self.logger = get_logger(__name__)
|
|
self.logger = logger
|
|
|
|
def prepare_dataframe(self, candles: List[OHLCVCandle]) -> pd.DataFrame:
|
|
"""
|
|
Convert OHLCV candles to pandas DataFrame for calculations.
|
|
|
|
Args:
|
|
candles: List of OHLCV candles (can be sparse)
|
|
|
|
Returns:
|
|
DataFrame with OHLCV data, sorted by timestamp
|
|
"""
|
|
if not candles:
|
|
return pd.DataFrame()
|
|
|
|
# Convert to DataFrame
|
|
data = []
|
|
for candle in candles:
|
|
data.append({
|
|
'timestamp': candle.end_time, # Right-aligned timestamp
|
|
'symbol': candle.symbol,
|
|
'timeframe': candle.timeframe,
|
|
'open': float(candle.open),
|
|
'high': float(candle.high),
|
|
'low': float(candle.low),
|
|
'close': float(candle.close),
|
|
'volume': float(candle.volume),
|
|
'trade_count': candle.trade_count
|
|
})
|
|
|
|
df = pd.DataFrame(data)
|
|
|
|
# Sort by timestamp to ensure proper order
|
|
df = df.sort_values('timestamp').reset_index(drop=True)
|
|
|
|
# Set timestamp as index for time-series operations
|
|
df['timestamp'] = pd.to_datetime(df['timestamp'])
|
|
|
|
# Set as index, but keep as column
|
|
df.set_index('timestamp', inplace=True)
|
|
|
|
# Ensure it's datetime
|
|
df['timestamp'] = df.index
|
|
|
|
return df
|
|
|
|
@abstractmethod
|
|
def calculate(self, df: pd.DataFrame, **kwargs) -> List[IndicatorResult]:
|
|
"""
|
|
Calculate the indicator values.
|
|
|
|
Args:
|
|
df: DataFrame with OHLCV data
|
|
**kwargs: Additional parameters specific to each indicator
|
|
|
|
Returns:
|
|
List of indicator results
|
|
"""
|
|
pass
|
|
|
|
def validate_dataframe(self, df: pd.DataFrame, min_periods: int) -> bool:
|
|
"""
|
|
Validate that DataFrame has sufficient data for calculation.
|
|
|
|
Args:
|
|
df: DataFrame to validate
|
|
min_periods: Minimum number of periods required
|
|
|
|
Returns:
|
|
True if DataFrame is valid, False otherwise
|
|
"""
|
|
if df.empty or len(df) < min_periods:
|
|
if self.logger:
|
|
self.logger.warning(
|
|
f"Insufficient data: got {len(df)} periods, need {min_periods}"
|
|
)
|
|
return False
|
|
return True |