2025-06-07 14:01:20 +08:00

106 lines
3.1 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.set_index('timestamp', inplace=True)
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