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()
|
|
|
|
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
|
|
) |