""" Modular Chart System for Crypto Trading Bot Dashboard This package provides a flexible, strategy-driven chart system that supports: - Technical indicator overlays (SMA, EMA, Bollinger Bands) - Subplot management (RSI, MACD) - Strategy-specific configurations - Future bot signal integration Main Components: - ChartBuilder: Main orchestrator for chart creation - Layer System: Modular rendering components - Configuration System: Strategy-driven chart configs """ from .builder import ChartBuilder from .utils import ( validate_market_data, prepare_chart_data, get_indicator_colors ) # Version information __version__ = "0.1.0" __package_name__ = "charts" # Public API exports __all__ = [ "ChartBuilder", "validate_market_data", "prepare_chart_data", "get_indicator_colors", "create_candlestick_chart", "create_strategy_chart", "get_supported_symbols", "get_supported_timeframes", "get_market_statistics", "check_data_availability", "create_data_status_indicator", "create_error_chart" ] def create_candlestick_chart(symbol: str, timeframe: str, days_back: int = 7, **kwargs): """ Convenience function to create a basic candlestick chart. Args: symbol: Trading pair (e.g., 'BTC-USDT') timeframe: Timeframe (e.g., '1h', '1d') days_back: Number of days to look back **kwargs: Additional parameters for chart customization Returns: Plotly Figure object """ builder = ChartBuilder() return builder.create_candlestick_chart(symbol, timeframe, days_back, **kwargs) def create_strategy_chart(symbol: str, timeframe: str, strategy_name: str, **kwargs): """ Convenience function to create a strategy-specific chart. Args: symbol: Trading pair timeframe: Timeframe strategy_name: Name of the strategy configuration **kwargs: Additional parameters Returns: Plotly Figure object with strategy indicators """ builder = ChartBuilder() return builder.create_strategy_chart(symbol, timeframe, strategy_name, **kwargs) def get_supported_symbols(): """Get list of symbols that have data in the database.""" builder = ChartBuilder() candles = builder.fetch_market_data("BTC-USDT", "1m", days_back=1) # Test query if candles: from database.operations import get_database_operations from utils.logger import get_logger logger = get_logger("charts_symbols") try: db = get_database_operations(logger) with db.market_data.get_session() as session: from sqlalchemy import text result = session.execute(text("SELECT DISTINCT symbol FROM market_data ORDER BY symbol")) return [row[0] for row in result] except Exception: pass return ['BTC-USDT', 'ETH-USDT'] # Fallback def get_supported_timeframes(): """Get list of timeframes that have data in the database.""" builder = ChartBuilder() candles = builder.fetch_market_data("BTC-USDT", "1m", days_back=1) # Test query if candles: from database.operations import get_database_operations from utils.logger import get_logger logger = get_logger("charts_timeframes") try: db = get_database_operations(logger) with db.market_data.get_session() as session: from sqlalchemy import text result = session.execute(text("SELECT DISTINCT timeframe FROM market_data ORDER BY timeframe")) return [row[0] for row in result] except Exception: pass return ['5s', '1m', '15m', '1h'] # Fallback def get_market_statistics(symbol: str, timeframe: str = "1h"): """Calculate market statistics from recent data.""" builder = ChartBuilder() candles = builder.fetch_market_data(symbol, timeframe, days_back=1) if not candles: return {'Price': 'N/A', '24h Change': 'N/A', '24h Volume': 'N/A', 'High 24h': 'N/A', 'Low 24h': 'N/A'} import pandas as pd df = pd.DataFrame(candles) latest = df.iloc[-1] current_price = float(latest['close']) # Calculate 24h change if len(df) > 1: price_24h_ago = float(df.iloc[0]['open']) change_percent = ((current_price - price_24h_ago) / price_24h_ago) * 100 else: change_percent = 0 from .utils import format_price, format_volume return { 'Price': format_price(current_price, decimals=2), '24h Change': f"{'+' if change_percent >= 0 else ''}{change_percent:.2f}%", '24h Volume': format_volume(df['volume'].sum()), 'High 24h': format_price(df['high'].max(), decimals=2), 'Low 24h': format_price(df['low'].min(), decimals=2) } def check_data_availability(symbol: str, timeframe: str): """Check data availability for a symbol and timeframe.""" from datetime import datetime, timezone, timedelta from database.operations import get_database_operations from utils.logger import get_logger try: logger = get_logger("charts_data_check") db = get_database_operations(logger) latest_candle = db.market_data.get_latest_candle(symbol, timeframe) if latest_candle: latest_time = latest_candle['timestamp'] time_diff = datetime.now(timezone.utc) - latest_time.replace(tzinfo=timezone.utc) return { 'has_data': True, 'latest_timestamp': latest_time, 'time_since_last': time_diff, 'is_recent': time_diff < timedelta(hours=1), 'message': f"Latest data: {latest_time.strftime('%Y-%m-%d %H:%M:%S UTC')}" } else: return { 'has_data': False, 'latest_timestamp': None, 'time_since_last': None, 'is_recent': False, 'message': f"No data available for {symbol} {timeframe}" } except Exception as e: return { 'has_data': False, 'latest_timestamp': None, 'time_since_last': None, 'is_recent': False, 'message': f"Error checking data: {str(e)}" } def create_data_status_indicator(symbol: str, timeframe: str): """Create a data status indicator for the dashboard.""" status = check_data_availability(symbol, timeframe) if status['has_data']: if status['is_recent']: icon, color, status_text = "🟢", "#27ae60", "Real-time Data" else: icon, color, status_text = "🟡", "#f39c12", "Delayed Data" else: icon, color, status_text = "🔴", "#e74c3c", "No Data" return f'{icon} {status_text}
{status["message"]}' def create_error_chart(error_message: str): """Create an error chart with error message.""" builder = ChartBuilder() return builder._create_error_chart(error_message)