- Deleted `app_new.py`, which was previously the main entry point for the dashboard application, to streamline the codebase. - Consolidated the application initialization and callback registration logic into `main.py`, enhancing modularity and maintainability. - Updated the logging and error handling practices in `main.py` to ensure consistent application behavior and improved debugging capabilities. These changes simplify the application structure, aligning with project standards for modularity and maintainability.
213 lines
7.8 KiB
Python
213 lines
7.8 KiB
Python
import plotly.graph_objects as go
|
|
from typing import List
|
|
import pandas as pd
|
|
|
|
from .builder import ChartBuilder
|
|
from .utils import prepare_chart_data, format_price, format_volume
|
|
from .error_handling import ChartErrorHandler, create_error_annotation
|
|
from utils.logger import get_logger
|
|
|
|
logger = get_logger("charts_creation")
|
|
|
|
def create_candlestick_chart(symbol: str, timeframe: str, days_back: int = 7, **kwargs) -> go.Figure:
|
|
"""
|
|
Create a candlestick chart with enhanced data integration.
|
|
|
|
Args:
|
|
symbol: Trading pair (e.g., 'BTC-USDT')
|
|
timeframe: Timeframe (e.g., '1h', '1d')
|
|
days_back: Number of days to look back
|
|
**kwargs: Additional chart parameters
|
|
|
|
Returns:
|
|
Plotly figure with candlestick chart
|
|
"""
|
|
builder = ChartBuilder()
|
|
|
|
# Check data quality first
|
|
data_quality = builder.check_data_quality(symbol, timeframe)
|
|
if not data_quality['available']:
|
|
logger.warning(f"Data not available for {symbol} {timeframe}: {data_quality['message']}")
|
|
return builder._create_error_chart(f"No data available: {data_quality['message']}")
|
|
|
|
if not data_quality['sufficient_for_indicators']:
|
|
logger.warning(f"Insufficient data for indicators: {symbol} {timeframe}")
|
|
|
|
# Use enhanced data fetching
|
|
try:
|
|
candles = builder.fetch_market_data_enhanced(symbol, timeframe, days_back)
|
|
if not candles:
|
|
return builder._create_error_chart(f"No market data found for {symbol} {timeframe}")
|
|
|
|
# Prepare data for charting
|
|
df = prepare_chart_data(candles)
|
|
if df.empty:
|
|
return builder._create_error_chart("Failed to prepare chart data")
|
|
|
|
# Create chart with data quality info
|
|
fig = builder._create_candlestick_with_volume(df, symbol, timeframe)
|
|
|
|
# Add data quality annotation if data is stale
|
|
if not data_quality['is_recent']:
|
|
age_hours = data_quality['data_age_minutes'] / 60
|
|
fig.add_annotation(
|
|
text=f"⚠️ Data is {age_hours:.1f}h old",
|
|
xref="paper", yref="paper",
|
|
x=0.02, y=0.98,
|
|
showarrow=False,
|
|
bgcolor="rgba(255,193,7,0.8)",
|
|
bordercolor="orange",
|
|
borderwidth=1
|
|
)
|
|
|
|
logger.debug(f"Created enhanced candlestick chart for {symbol} {timeframe} with {len(candles)} candles")
|
|
return fig
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error creating enhanced candlestick chart: {e}")
|
|
return builder._create_error_chart(f"Chart creation failed: {str(e)}")
|
|
|
|
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 create_error_chart(error_message: str):
|
|
"""Create an error chart with error message."""
|
|
builder = ChartBuilder()
|
|
return builder._create_error_chart(error_message)
|
|
|
|
def create_basic_chart(symbol: str, data: list,
|
|
indicators: list = None,
|
|
error_handling: bool = True) -> 'go.Figure':
|
|
"""
|
|
Create a basic chart with error handling.
|
|
|
|
Args:
|
|
symbol: Trading symbol
|
|
data: OHLCV data as list of dictionaries
|
|
indicators: List of indicator configurations
|
|
error_handling: Whether to use comprehensive error handling
|
|
|
|
Returns:
|
|
Plotly figure with chart or error display
|
|
"""
|
|
try:
|
|
# Initialize chart builder
|
|
builder = ChartBuilder()
|
|
|
|
if error_handling:
|
|
# Use error-aware chart creation
|
|
error_handler = ChartErrorHandler()
|
|
is_valid = error_handler.validate_data_sufficiency(data, indicators=indicators or [])
|
|
|
|
if not is_valid:
|
|
# Create error chart
|
|
fig = go.Figure()
|
|
error_msg = error_handler.get_user_friendly_message()
|
|
fig.add_annotation(create_error_annotation(error_msg, position='center'))
|
|
fig.update_layout(
|
|
title=f"Chart Error - {symbol}",
|
|
xaxis={'visible': False},
|
|
yaxis={'visible': False},
|
|
template='plotly_white',
|
|
height=400
|
|
)
|
|
return fig
|
|
|
|
# Create chart normally
|
|
return builder.create_candlestick_chart(data, symbol=symbol, indicators=indicators or [])
|
|
|
|
except Exception as e:
|
|
# Fallback error chart
|
|
fig = go.Figure()
|
|
fig.add_annotation(create_error_annotation(
|
|
f"Chart creation failed: {str(e)}",
|
|
position='center'
|
|
))
|
|
fig.update_layout(
|
|
title=f"Chart Error - {symbol}",
|
|
template='plotly_white',
|
|
height=400
|
|
)
|
|
return fig
|
|
|
|
def create_indicator_chart(symbol: str, data: list,
|
|
indicator_type: str, **params) -> 'go.Figure':
|
|
"""
|
|
Create a chart focused on a specific indicator.
|
|
|
|
Args:
|
|
symbol: Trading symbol
|
|
data: OHLCV data
|
|
indicator_type: Type of indicator ('sma', 'ema', 'bollinger_bands', 'rsi', 'macd')
|
|
**params: Indicator parameters
|
|
|
|
Returns:
|
|
Plotly figure with indicator chart
|
|
"""
|
|
try:
|
|
# Map indicator types to configurations
|
|
indicator_map = {
|
|
'sma': {'type': 'sma', 'parameters': {'period': params.get('period', 20)}},
|
|
'ema': {'type': 'ema', 'parameters': {'period': params.get('period', 20)}},
|
|
'bollinger_bands': {
|
|
'type': 'bollinger_bands',
|
|
'parameters': {
|
|
'period': params.get('period', 20),
|
|
'std_dev': params.get('std_dev', 2)
|
|
}
|
|
},
|
|
'rsi': {'type': 'rsi', 'parameters': {'period': params.get('period', 14)}},
|
|
'macd': {
|
|
'type': 'macd',
|
|
'parameters': {
|
|
'fast_period': params.get('fast_period', 12),
|
|
'slow_period': params.get('slow_period', 26),
|
|
'signal_period': params.get('signal_period', 9)
|
|
}
|
|
}
|
|
}
|
|
|
|
if indicator_type not in indicator_map:
|
|
raise ValueError(f"Unknown indicator type: {indicator_type}")
|
|
|
|
indicator_config = indicator_map[indicator_type]
|
|
return create_basic_chart(symbol, data, indicators=[indicator_config])
|
|
|
|
except Exception as e:
|
|
return create_basic_chart(symbol, data, indicators=[]) # Fallback to basic chart
|
|
|
|
def create_chart_with_indicators(symbol: str, timeframe: str,
|
|
overlay_indicators: List[str] = None,
|
|
subplot_indicators: List[str] = None,
|
|
days_back: int = 7, **kwargs) -> go.Figure:
|
|
"""
|
|
Create a chart with dynamically selected indicators.
|
|
|
|
Args:
|
|
symbol: Trading pair (e.g., 'BTC-USDT')
|
|
timeframe: Timeframe (e.g., '1h', '1d')
|
|
overlay_indicators: List of overlay indicator names
|
|
subplot_indicators: List of subplot indicator names
|
|
days_back: Number of days to look back
|
|
**kwargs: Additional chart parameters
|
|
|
|
Returns:
|
|
Plotly figure with selected indicators
|
|
"""
|
|
builder = ChartBuilder()
|
|
return builder.create_chart_with_indicators(
|
|
symbol, timeframe, overlay_indicators, subplot_indicators, days_back, **kwargs
|
|
) |