- Introduced a new modular structure for the dashboard, enhancing maintainability and scalability. - Created main application entry point in `app_new.py`, integrating all components and callbacks. - Developed layout modules for market data, bot management, performance analytics, and system health in the `layouts` directory. - Implemented callback modules for navigation, charts, indicators, and system health in the `callbacks` directory. - Established reusable UI components in the `components` directory, including chart controls and indicator modals. - Enhanced documentation to reflect the new modular structure and provide clear usage guidelines. - Ensured all components are under 300-400 lines for better readability and maintainability.
203 lines
7.9 KiB
Python
203 lines
7.9 KiB
Python
"""
|
||
Chart control components for the market data layout.
|
||
"""
|
||
|
||
from dash import html, dcc
|
||
from utils.logger import get_logger
|
||
|
||
logger = get_logger("chart_controls")
|
||
|
||
|
||
def create_chart_config_panel(strategy_options, overlay_options, subplot_options):
|
||
"""Create the chart configuration panel with add/edit UI."""
|
||
return html.Div([
|
||
html.H5("🎯 Chart Configuration", style={'color': '#2c3e50', 'margin-bottom': '15px'}),
|
||
|
||
# Add New Indicator Button
|
||
html.Div([
|
||
html.Button(
|
||
"➕ Add New Indicator",
|
||
id="add-indicator-btn-visible",
|
||
className="btn btn-primary",
|
||
style={
|
||
'background-color': '#007bff',
|
||
'color': 'white',
|
||
'border': 'none',
|
||
'padding': '8px 16px',
|
||
'border-radius': '4px',
|
||
'cursor': 'pointer',
|
||
'margin-bottom': '15px',
|
||
'font-weight': 'bold'
|
||
}
|
||
)
|
||
]),
|
||
|
||
# Strategy Selection
|
||
html.Div([
|
||
html.Label("Strategy Template:", style={'font-weight': 'bold', 'margin-bottom': '5px'}),
|
||
dcc.Dropdown(
|
||
id='strategy-dropdown',
|
||
options=strategy_options,
|
||
value=None,
|
||
placeholder="Select a strategy template (optional)",
|
||
style={'margin-bottom': '15px'}
|
||
)
|
||
]),
|
||
|
||
# Indicator Controls with Edit Buttons
|
||
html.Div([
|
||
# Overlay Indicators
|
||
html.Div([
|
||
html.Label("Overlay Indicators:", style={'font-weight': 'bold', 'margin-bottom': '10px', 'display': 'block'}),
|
||
html.Div([
|
||
# Hidden checklist for callback compatibility
|
||
dcc.Checklist(
|
||
id='overlay-indicators-checklist',
|
||
options=overlay_options,
|
||
value=[], # Start with no indicators selected
|
||
style={'display': 'none'} # Hide the basic checklist
|
||
),
|
||
# Custom indicator list with edit buttons
|
||
html.Div(id='overlay-indicators-list', children=[
|
||
# This will be populated dynamically
|
||
])
|
||
])
|
||
], style={'width': '48%', 'display': 'inline-block', 'margin-right': '4%', 'vertical-align': 'top'}),
|
||
|
||
# Subplot Indicators
|
||
html.Div([
|
||
html.Label("Subplot Indicators:", style={'font-weight': 'bold', 'margin-bottom': '10px', 'display': 'block'}),
|
||
html.Div([
|
||
# Hidden checklist for callback compatibility
|
||
dcc.Checklist(
|
||
id='subplot-indicators-checklist',
|
||
options=subplot_options,
|
||
value=[], # Start with no indicators selected
|
||
style={'display': 'none'} # Hide the basic checklist
|
||
),
|
||
# Custom indicator list with edit buttons
|
||
html.Div(id='subplot-indicators-list', children=[
|
||
# This will be populated dynamically
|
||
])
|
||
])
|
||
], style={'width': '48%', 'display': 'inline-block', 'vertical-align': 'top'})
|
||
])
|
||
], style={
|
||
'border': '1px solid #bdc3c7',
|
||
'border-radius': '8px',
|
||
'padding': '15px',
|
||
'background-color': '#f8f9fa',
|
||
'margin-bottom': '20px'
|
||
})
|
||
|
||
|
||
def create_parameter_controls():
|
||
"""Create the parameter controls section for indicator configuration."""
|
||
return html.Div([
|
||
html.H5("📊 Indicator Parameters", style={'color': '#2c3e50', 'margin-bottom': '15px'}),
|
||
|
||
# SMA/EMA Period Controls
|
||
html.Div([
|
||
html.Label("Moving Average Period:", style={'font-weight': 'bold', 'margin-bottom': '5px'}),
|
||
dcc.Slider(
|
||
id='ma-period-slider',
|
||
min=5, max=200, step=5, value=20,
|
||
marks={i: str(i) for i in [5, 20, 50, 100, 200]},
|
||
tooltip={'placement': 'bottom', 'always_visible': True}
|
||
)
|
||
], style={'margin-bottom': '20px'}),
|
||
|
||
# RSI Period Control
|
||
html.Div([
|
||
html.Label("RSI Period:", style={'font-weight': 'bold', 'margin-bottom': '5px'}),
|
||
dcc.Slider(
|
||
id='rsi-period-slider',
|
||
min=7, max=30, step=1, value=14,
|
||
marks={i: str(i) for i in [7, 14, 21, 30]},
|
||
tooltip={'placement': 'bottom', 'always_visible': True}
|
||
)
|
||
], style={'margin-bottom': '20px'}),
|
||
|
||
# MACD Parameters
|
||
html.Div([
|
||
html.Label("MACD Parameters:", style={'font-weight': 'bold', 'margin-bottom': '10px'}),
|
||
html.Div([
|
||
html.Div([
|
||
html.Label("Fast:", style={'font-size': '12px'}),
|
||
dcc.Input(
|
||
id='macd-fast-input',
|
||
type='number',
|
||
value=12,
|
||
min=5, max=50,
|
||
style={'width': '60px', 'margin-left': '5px'}
|
||
)
|
||
], style={'display': 'inline-block', 'margin-right': '15px'}),
|
||
html.Div([
|
||
html.Label("Slow:", style={'font-size': '12px'}),
|
||
dcc.Input(
|
||
id='macd-slow-input',
|
||
type='number',
|
||
value=26,
|
||
min=10, max=100,
|
||
style={'width': '60px', 'margin-left': '5px'}
|
||
)
|
||
], style={'display': 'inline-block', 'margin-right': '15px'}),
|
||
html.Div([
|
||
html.Label("Signal:", style={'font-size': '12px'}),
|
||
dcc.Input(
|
||
id='macd-signal-input',
|
||
type='number',
|
||
value=9,
|
||
min=3, max=20,
|
||
style={'width': '60px', 'margin-left': '5px'}
|
||
)
|
||
], style={'display': 'inline-block'})
|
||
])
|
||
], style={'margin-bottom': '20px'}),
|
||
|
||
# Bollinger Bands Parameters
|
||
html.Div([
|
||
html.Label("Bollinger Bands:", style={'font-weight': 'bold', 'margin-bottom': '10px'}),
|
||
html.Div([
|
||
html.Div([
|
||
html.Label("Period:", style={'font-size': '12px'}),
|
||
dcc.Input(
|
||
id='bb-period-input',
|
||
type='number',
|
||
value=20,
|
||
min=5, max=50,
|
||
style={'width': '60px', 'margin-left': '5px'}
|
||
)
|
||
], style={'display': 'inline-block', 'margin-right': '15px'}),
|
||
html.Div([
|
||
html.Label("Std Dev:", style={'font-size': '12px'}),
|
||
dcc.Input(
|
||
id='bb-stddev-input',
|
||
type='number',
|
||
value=2.0,
|
||
min=1.0, max=3.0, step=0.1,
|
||
style={'width': '70px', 'margin-left': '5px'}
|
||
)
|
||
], style={'display': 'inline-block'})
|
||
])
|
||
])
|
||
], style={
|
||
'border': '1px solid #bdc3c7',
|
||
'border-radius': '8px',
|
||
'padding': '15px',
|
||
'background-color': '#f8f9fa',
|
||
'margin-bottom': '20px'
|
||
})
|
||
|
||
|
||
def create_auto_update_control():
|
||
"""Create the auto-update control section."""
|
||
return html.Div([
|
||
dcc.Checklist(
|
||
id='auto-update-checkbox',
|
||
options=[{'label': ' Auto-update charts', 'value': 'auto'}],
|
||
value=['auto'],
|
||
style={'margin-bottom': '10px'}
|
||
),
|
||
html.Div(id='update-status', style={'font-size': '12px', 'color': '#7f8c8d'})
|
||
]) |