2025-06-04 13:30:16 +08:00
|
|
|
"""
|
|
|
|
|
Market data layout for the dashboard.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from dash import html, dcc
|
|
|
|
|
from utils.logger import get_logger
|
|
|
|
|
from components.charts import get_supported_symbols, get_supported_timeframes
|
|
|
|
|
from components.charts.config import get_available_strategy_names
|
|
|
|
|
from components.charts.indicator_manager import get_indicator_manager
|
|
|
|
|
from components.charts.indicator_defaults import ensure_default_indicators
|
|
|
|
|
from dashboard.components.chart_controls import (
|
|
|
|
|
create_chart_config_panel,
|
2025-06-06 12:57:35 +08:00
|
|
|
create_time_range_controls,
|
|
|
|
|
create_export_controls
|
2025-06-04 13:30:16 +08:00
|
|
|
)
|
|
|
|
|
|
2025-06-04 17:03:35 +08:00
|
|
|
logger = get_logger("default_logger")
|
2025-06-04 13:30:16 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_market_data_layout():
|
|
|
|
|
"""Create the market data visualization layout with indicator controls."""
|
|
|
|
|
# Get available symbols and timeframes from database
|
|
|
|
|
symbols = get_supported_symbols()
|
|
|
|
|
timeframes = get_supported_timeframes()
|
|
|
|
|
|
|
|
|
|
# Create dropdown options
|
|
|
|
|
symbol_options = [{'label': symbol, 'value': symbol} for symbol in symbols]
|
|
|
|
|
timeframe_options = [
|
2025-06-04 15:54:14 +08:00
|
|
|
{'label': "1 Second", 'value': '1s'},
|
|
|
|
|
{'label': "5 Seconds", 'value': '5s'},
|
|
|
|
|
{'label': "15 Seconds", 'value': '15s'},
|
|
|
|
|
{'label': "30 Seconds", 'value': '30s'},
|
2025-06-04 13:30:16 +08:00
|
|
|
{'label': '1 Minute', 'value': '1m'},
|
|
|
|
|
{'label': '5 Minutes', 'value': '5m'},
|
|
|
|
|
{'label': '15 Minutes', 'value': '15m'},
|
|
|
|
|
{'label': '1 Hour', 'value': '1h'},
|
|
|
|
|
{'label': '4 Hours', 'value': '4h'},
|
|
|
|
|
{'label': '1 Day', 'value': '1d'},
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
# Filter timeframe options to only show those available in database
|
2025-06-04 15:54:14 +08:00
|
|
|
available_timeframes = [tf for tf in ['1s', '5s', '15s', '30s', '1m', '5m', '15m', '1h', '4h', '1d'] if tf in timeframes]
|
2025-06-04 13:30:16 +08:00
|
|
|
if not available_timeframes:
|
2025-06-04 15:54:14 +08:00
|
|
|
available_timeframes = ['5m'] # Default fallback
|
2025-06-04 13:30:16 +08:00
|
|
|
|
|
|
|
|
timeframe_options = [opt for opt in timeframe_options if opt['value'] in available_timeframes]
|
|
|
|
|
|
|
|
|
|
# Get available strategies and indicators
|
|
|
|
|
try:
|
|
|
|
|
strategy_names = get_available_strategy_names()
|
|
|
|
|
strategy_options = [{'label': name.replace('_', ' ').title(), 'value': name} for name in strategy_names]
|
|
|
|
|
|
|
|
|
|
# Get user indicators from the new indicator manager
|
|
|
|
|
indicator_manager = get_indicator_manager()
|
|
|
|
|
|
|
|
|
|
# Ensure default indicators exist
|
|
|
|
|
ensure_default_indicators()
|
|
|
|
|
|
|
|
|
|
# Get indicators by display type
|
|
|
|
|
overlay_indicators = indicator_manager.get_indicators_by_type('overlay')
|
|
|
|
|
subplot_indicators = indicator_manager.get_indicators_by_type('subplot')
|
|
|
|
|
|
|
|
|
|
# Create checkbox options for overlay indicators
|
|
|
|
|
overlay_options = []
|
|
|
|
|
for indicator in overlay_indicators:
|
|
|
|
|
display_name = f"{indicator.name} ({indicator.type.upper()})"
|
|
|
|
|
overlay_options.append({'label': display_name, 'value': indicator.id})
|
|
|
|
|
|
|
|
|
|
# Create checkbox options for subplot indicators
|
|
|
|
|
subplot_options = []
|
|
|
|
|
for indicator in subplot_indicators:
|
|
|
|
|
display_name = f"{indicator.name} ({indicator.type.upper()})"
|
|
|
|
|
subplot_options.append({'label': display_name, 'value': indicator.id})
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
2025-06-04 17:03:35 +08:00
|
|
|
logger.warning(f"Market data layout: Error loading indicator options: {e}")
|
2025-06-04 13:30:16 +08:00
|
|
|
strategy_options = [{'label': 'Basic Chart', 'value': 'basic'}]
|
|
|
|
|
overlay_options = []
|
|
|
|
|
subplot_options = []
|
|
|
|
|
|
|
|
|
|
# Create components using the new modular functions
|
|
|
|
|
chart_config_panel = create_chart_config_panel(strategy_options, overlay_options, subplot_options)
|
2025-06-05 12:54:41 +08:00
|
|
|
time_range_controls = create_time_range_controls()
|
2025-06-06 12:57:35 +08:00
|
|
|
export_controls = create_export_controls()
|
2025-06-04 13:30:16 +08:00
|
|
|
|
|
|
|
|
return html.Div([
|
|
|
|
|
# Title and basic controls
|
|
|
|
|
html.H3("💹 Market Data Visualization", style={'color': '#2c3e50', 'margin-bottom': '20px'}),
|
|
|
|
|
|
|
|
|
|
# Main chart controls
|
|
|
|
|
html.Div([
|
|
|
|
|
html.Div([
|
|
|
|
|
html.Label("Symbol:", style={'font-weight': 'bold'}),
|
|
|
|
|
dcc.Dropdown(
|
|
|
|
|
id='symbol-dropdown',
|
|
|
|
|
options=symbol_options,
|
|
|
|
|
value=symbols[0] if symbols else 'BTC-USDT',
|
|
|
|
|
clearable=False,
|
|
|
|
|
style={'margin-bottom': '10px'}
|
|
|
|
|
)
|
|
|
|
|
], style={'width': '48%', 'display': 'inline-block'}),
|
|
|
|
|
html.Div([
|
|
|
|
|
html.Label("Timeframe:", style={'font-weight': 'bold'}),
|
|
|
|
|
dcc.Dropdown(
|
|
|
|
|
id='timeframe-dropdown',
|
|
|
|
|
options=timeframe_options,
|
|
|
|
|
value='1h',
|
|
|
|
|
clearable=False,
|
|
|
|
|
style={'margin-bottom': '10px'}
|
|
|
|
|
)
|
|
|
|
|
], style={'width': '48%', 'float': 'right', 'display': 'inline-block'})
|
|
|
|
|
], style={'margin-bottom': '20px'}),
|
|
|
|
|
|
|
|
|
|
# Chart Configuration Panel
|
|
|
|
|
chart_config_panel,
|
|
|
|
|
|
2025-06-05 12:54:41 +08:00
|
|
|
# Time Range Controls (positioned under indicators, next to chart)
|
|
|
|
|
time_range_controls,
|
2025-06-04 13:30:16 +08:00
|
|
|
|
2025-06-06 12:57:35 +08:00
|
|
|
# Export Controls
|
|
|
|
|
export_controls,
|
|
|
|
|
|
2025-06-04 13:30:16 +08:00
|
|
|
# Chart
|
|
|
|
|
dcc.Graph(id='price-chart'),
|
|
|
|
|
|
2025-06-06 12:57:35 +08:00
|
|
|
# Hidden store for chart data
|
|
|
|
|
dcc.Store(id='chart-data-store'),
|
|
|
|
|
|
2025-06-05 11:24:21 +08:00
|
|
|
# Enhanced Market statistics with integrated data analysis
|
2025-06-04 13:30:16 +08:00
|
|
|
html.Div(id='market-stats', style={'margin-top': '20px'})
|
|
|
|
|
])
|