3.4 Implement user-defined indicator management system and enhance chart capabilities

- Introduced a comprehensive user indicator management system in `components/charts/indicator_manager.py`, allowing users to create, edit, and manage custom indicators with JSON persistence.
- Added new default indicators in `components/charts/indicator_defaults.py` to provide users with immediate options for technical analysis.
- Enhanced the chart rendering capabilities by implementing the `create_chart_with_indicators` function in `components/charts/builder.py`, supporting both overlay and subplot indicators.
- Updated the main application layout in `app.py` to include a modal for adding and editing indicators, improving user interaction.
- Enhanced documentation to cover the new indicator system, including a quick guide for adding new indicators and detailed usage examples.
- Added unit tests to ensure the reliability and functionality of the new indicator management features.
This commit is contained in:
Vasily.onl
2025-06-04 13:01:57 +08:00
parent d71cb763bc
commit 476bd67f14
25 changed files with 3160 additions and 55 deletions

View File

@@ -8,6 +8,7 @@ The Modular Chart Layers System is a flexible, strategy-driven chart system that
- [Architecture](#architecture)
- [Quick Start](#quick-start)
- [Components](#components)
- [User Indicator Management](#user-indicator-management)
- [Configuration System](#configuration-system)
- [Example Strategies](#example-strategies)
- [Validation System](#validation-system)
@@ -20,6 +21,7 @@ The Modular Chart Layers System is a flexible, strategy-driven chart system that
### Key Features
- **Modular Architecture**: Chart layers can be independently tested and composed
- **User Indicator Management**: Create, edit, and manage custom indicators with JSON persistence
- **Strategy-Driven Configuration**: JSON-based configurations for different trading strategies
- **Comprehensive Validation**: 10+ validation rules with detailed error reporting
- **Example Strategies**: 5 real-world trading strategy templates
@@ -44,7 +46,9 @@ The Modular Chart Layers System is a flexible, strategy-driven chart system that
```
components/charts/
├── config/ # Configuration management
├── indicator_manager.py # User indicator CRUD operations
├── indicator_defaults.py # Default indicator templates
├── config/ # Configuration management
│ ├── indicator_defs.py # Indicator schemas and validation
│ ├── defaults.py # Default configurations and presets
│ ├── strategy_charts.py # Strategy-specific configurations
@@ -58,6 +62,65 @@ components/charts/
│ └── signals.py # Signal overlays (future)
├── builder.py # Main chart builder
└── utils.py # Chart utilities
config/indicators/
└── user_indicators/ # User-created indicators (JSON files)
├── sma_abc123.json
├── ema_def456.json
└── ...
```
## User Indicator Management
The system includes a comprehensive user indicator management system that allows creating, editing, and managing custom technical indicators.
### Features
- **Interactive UI**: Modal dialog for creating and editing indicators
- **Real-time Updates**: Charts update immediately when indicators are toggled
- **JSON Persistence**: Each indicator saved as individual JSON file
- **Full CRUD Operations**: Create, Read, Update, Delete functionality
- **Type Validation**: Parameter validation based on indicator type
- **Custom Styling**: Color, line width, and appearance customization
### Quick Access
- **📊 [Complete Indicator Documentation](./indicators.md)** - Comprehensive guide to the indicator system
- **⚡ [Quick Guide: Adding New Indicators](./adding-new-indicators.md)** - Step-by-step checklist for developers
### Current User Indicators
| Indicator | Type | Parameters | Display |
|-----------|------|------------|---------|
| Simple Moving Average (SMA) | `sma` | period (1-200) | Overlay |
| Exponential Moving Average (EMA) | `ema` | period (1-200) | Overlay |
| Bollinger Bands | `bollinger_bands` | period (5-100), std_dev (0.5-5.0) | Overlay |
| Relative Strength Index (RSI) | `rsi` | period (2-50) | Subplot |
| MACD | `macd` | fast_period, slow_period, signal_period | Subplot |
### Usage Example
```python
# Get indicator manager
from components.charts.indicator_manager import get_indicator_manager
manager = get_indicator_manager()
# Create new indicator
indicator = manager.create_indicator(
name="My SMA 50",
indicator_type="sma",
parameters={"period": 50},
description="50-period Simple Moving Average",
color="#ff0000"
)
# Load and update
loaded = manager.load_indicator("sma_abc123")
success = manager.update_indicator("sma_abc123", name="Updated SMA")
# Get indicators by type
overlay_indicators = manager.get_indicators_by_type("overlay")
subplot_indicators = manager.get_indicators_by_type("subplot")
```
## Quick Start

View File

@@ -0,0 +1,393 @@
# Quick Guide: Adding New Indicators
## Overview
This guide provides a step-by-step checklist for adding new technical indicators to the Crypto Trading Bot Dashboard.
## Prerequisites
- Understanding of Python and technical analysis
- Familiarity with the project structure
- Knowledge of the indicator type (overlay vs subplot)
## Step-by-Step Checklist
### ✅ Step 1: Plan Your Indicator
- [ ] Determine indicator type (overlay or subplot)
- [ ] Define required parameters
- [ ] Choose default styling
- [ ] Research calculation formula
### ✅ Step 2: Create Indicator Class
**File**: `components/charts/layers/indicators.py` (overlay) or `components/charts/layers/subplots.py` (subplot)
```python
class StochasticLayer(IndicatorLayer):
"""Stochastic Oscillator indicator implementation."""
def __init__(self, config: Dict[str, Any]):
super().__init__(config)
self.name = "stochastic"
self.display_type = "subplot" # or "overlay"
def calculate_values(self, df: pd.DataFrame) -> Dict[str, pd.Series]:
"""Calculate stochastic oscillator values."""
k_period = self.config.get('k_period', 14)
d_period = self.config.get('d_period', 3)
# Calculate %K and %D lines
lowest_low = df['low'].rolling(window=k_period).min()
highest_high = df['high'].rolling(window=k_period).max()
k_percent = 100 * ((df['close'] - lowest_low) / (highest_high - lowest_low))
d_percent = k_percent.rolling(window=d_period).mean()
return {
'k_percent': k_percent,
'd_percent': d_percent
}
def create_traces(self, df: pd.DataFrame, values: Dict[str, pd.Series]) -> List[go.Scatter]:
"""Create plotly traces for stochastic oscillator."""
traces = []
# %K line
traces.append(go.Scatter(
x=df.index,
y=values['k_percent'],
mode='lines',
name=f"%K ({self.config.get('k_period', 14)})",
line=dict(
color=self.config.get('color', '#007bff'),
width=self.config.get('line_width', 2)
)
))
# %D line
traces.append(go.Scatter(
x=df.index,
y=values['d_percent'],
mode='lines',
name=f"%D ({self.config.get('d_period', 3)})",
line=dict(
color=self.config.get('secondary_color', '#ff6b35'),
width=self.config.get('line_width', 2)
)
))
return traces
```
### ✅ Step 3: Register Indicator
**File**: `components/charts/layers/__init__.py`
```python
# Import the new class
from .subplots import StochasticLayer
# Add to appropriate registry
SUBPLOT_REGISTRY = {
'rsi': RSILayer,
'macd': MACDLayer,
'stochastic': StochasticLayer, # Add this line
}
# For overlay indicators, add to INDICATOR_REGISTRY instead
INDICATOR_REGISTRY = {
'sma': SMALayer,
'ema': EMALayer,
'bollinger_bands': BollingerBandsLayer,
'stochastic': StochasticLayer, # Only if overlay
}
```
### ✅ Step 4: Add UI Dropdown Option
**File**: `app.py` (in the indicator type dropdown)
```python
dcc.Dropdown(
id='indicator-type-dropdown',
options=[
{'label': 'Simple Moving Average (SMA)', 'value': 'sma'},
{'label': 'Exponential Moving Average (EMA)', 'value': 'ema'},
{'label': 'Relative Strength Index (RSI)', 'value': 'rsi'},
{'label': 'MACD', 'value': 'macd'},
{'label': 'Bollinger Bands', 'value': 'bollinger_bands'},
{'label': 'Stochastic Oscillator', 'value': 'stochastic'}, # Add this
]
)
```
### ✅ Step 5: Add Parameter Fields to Modal
**File**: `app.py` (in the modal parameters section)
```python
# Add parameter section for stochastic
html.Div([
html.Div([
html.Label("%K Period:", style={'font-weight': 'bold', 'margin-bottom': '5px'}),
dcc.Input(
id='stochastic-k-period-input',
type='number',
value=14,
min=5, max=50,
style={'width': '80px', 'padding': '8px', 'border': '1px solid #ddd', 'border-radius': '4px'}
)
], style={'margin-bottom': '10px'}),
html.Div([
html.Label("%D Period:", style={'font-weight': 'bold', 'margin-bottom': '5px'}),
dcc.Input(
id='stochastic-d-period-input',
type='number',
value=3,
min=2, max=10,
style={'width': '80px', 'padding': '8px', 'border': '1px solid #ddd', 'border-radius': '4px'}
)
]),
html.P("Stochastic oscillator periods for %K and %D lines",
style={'color': '#7f8c8d', 'font-size': '12px', 'margin-top': '5px'})
], id='stochastic-parameters', style={'display': 'none', 'margin-bottom': '10px'})
```
### ✅ Step 6: Update Parameter Visibility Callback
**File**: `app.py` (in `update_parameter_fields` callback)
```python
@app.callback(
[Output('indicator-parameters-message', 'style'),
Output('sma-parameters', 'style'),
Output('ema-parameters', 'style'),
Output('rsi-parameters', 'style'),
Output('macd-parameters', 'style'),
Output('bb-parameters', 'style'),
Output('stochastic-parameters', 'style')], # Add this output
Input('indicator-type-dropdown', 'value'),
prevent_initial_call=True
)
def update_parameter_fields(indicator_type):
# ... existing code ...
# Add stochastic style
stochastic_style = hidden_style
# Show the relevant parameter section
if indicator_type == 'sma':
sma_style = visible_style
elif indicator_type == 'ema':
ema_style = visible_style
elif indicator_type == 'rsi':
rsi_style = visible_style
elif indicator_type == 'macd':
macd_style = visible_style
elif indicator_type == 'bollinger_bands':
bb_style = visible_style
elif indicator_type == 'stochastic': # Add this
stochastic_style = visible_style
return message_style, sma_style, ema_style, rsi_style, macd_style, bb_style, stochastic_style
```
### ✅ Step 7: Update Save Indicator Callback
**File**: `app.py` (in `save_new_indicator` callback)
```python
# Add stochastic parameters to State inputs
State('stochastic-k-period-input', 'value'),
State('stochastic-d-period-input', 'value'),
# Add to parameter collection logic
def save_new_indicator(n_clicks, name, indicator_type, description, color, line_width,
sma_period, ema_period, rsi_period,
macd_fast, macd_slow, macd_signal,
bb_period, bb_stddev,
stochastic_k, stochastic_d, # Add these
edit_data):
# ... existing code ...
elif indicator_type == 'stochastic':
parameters = {
'k_period': stochastic_k or 14,
'd_period': stochastic_d or 3
}
```
### ✅ Step 8: Update Edit Callback Parameters
**File**: `app.py` (in `edit_indicator` callback)
```python
# Add output for stochastic parameters
Output('stochastic-k-period-input', 'value'),
Output('stochastic-d-period-input', 'value'),
# Add parameter loading logic
elif indicator.type == 'stochastic':
stochastic_k = params.get('k_period', 14)
stochastic_d = params.get('d_period', 3)
# Add to return statement
return (
"✏️ Edit Indicator",
indicator.name,
indicator.type,
indicator.description,
indicator.styling.color,
edit_data,
sma_period,
ema_period,
rsi_period,
macd_fast,
macd_slow,
macd_signal,
bb_period,
bb_stddev,
stochastic_k, # Add these
stochastic_d
)
```
### ✅ Step 9: Update Reset Callback
**File**: `app.py` (in `reset_modal_form` callback)
```python
# Add outputs
Output('stochastic-k-period-input', 'value', allow_duplicate=True),
Output('stochastic-d-period-input', 'value', allow_duplicate=True),
# Add default values to return
return "", None, "", "#007bff", 2, "📊 Add New Indicator", None, 20, 12, 14, 12, 26, 9, 20, 2.0, 14, 3
```
### ✅ Step 10: Create Default Template
**File**: `components/charts/indicator_defaults.py`
```python
def create_stochastic_template() -> UserIndicator:
"""Create default Stochastic Oscillator template."""
return UserIndicator(
id=f"stochastic_{generate_short_id()}",
name="Stochastic 14,3",
description="14-period %K with 3-period %D smoothing",
type="stochastic",
display_type="subplot",
parameters={
"k_period": 14,
"d_period": 3
},
styling=IndicatorStyling(
color="#9c27b0",
line_width=2
)
)
# Add to DEFAULT_TEMPLATES
DEFAULT_TEMPLATES = {
"sma": create_sma_template,
"ema": create_ema_template,
"rsi": create_rsi_template,
"macd": create_macd_template,
"bollinger_bands": create_bollinger_bands_template,
"stochastic": create_stochastic_template, # Add this
}
```
### ✅ Step 11: Add Calculation Function (Optional)
**File**: `data/common/indicators.py`
```python
def calculate_stochastic(df: pd.DataFrame, k_period: int = 14, d_period: int = 3) -> tuple:
"""Calculate Stochastic Oscillator (%K and %D)."""
lowest_low = df['low'].rolling(window=k_period).min()
highest_high = df['high'].rolling(window=k_period).max()
k_percent = 100 * ((df['close'] - lowest_low) / (highest_high - lowest_low))
d_percent = k_percent.rolling(window=d_period).mean()
return k_percent, d_percent
```
## Testing Checklist
- [ ] Indicator appears in dropdown
- [ ] Parameter fields show/hide correctly
- [ ] Default values are set properly
- [ ] Indicator saves and loads correctly
- [ ] Edit functionality works
- [ ] Chart updates with indicator
- [ ] Delete functionality works
- [ ] Error handling works with insufficient data
## Common Patterns
### Single Line Overlay
```python
# Simple indicators like SMA, EMA
def create_traces(self, df: pd.DataFrame, values: Dict[str, pd.Series]) -> List[go.Scatter]:
return [go.Scatter(
x=df.index,
y=values['indicator_name'],
mode='lines',
name=self.config.get('name', 'Indicator'),
line=dict(color=self.config.get('color', '#007bff'))
)]
```
### Multi-Line Subplot
```python
# Complex indicators like MACD, Stochastic
def create_traces(self, df: pd.DataFrame, values: Dict[str, pd.Series]) -> List[go.Scatter]:
traces = []
for key, series in values.items():
traces.append(go.Scatter(
x=df.index,
y=series,
mode='lines',
name=f"{key.title()}"
))
return traces
```
### Band Indicators
```python
# Indicators with bands like Bollinger Bands
def create_traces(self, df: pd.DataFrame, values: Dict[str, pd.Series]) -> List[go.Scatter]:
return [
# Upper band
go.Scatter(x=df.index, y=values['upper'], name='Upper'),
# Middle line
go.Scatter(x=df.index, y=values['middle'], name='Middle'),
# Lower band with fill
go.Scatter(x=df.index, y=values['lower'], name='Lower',
fill='tonexty', fillcolor='rgba(0,123,255,0.1)')
]
```
## File Change Summary
When adding a new indicator, you'll typically modify these files:
1. **`components/charts/layers/indicators.py`** or **`subplots.py`** - Indicator class
2. **`components/charts/layers/__init__.py`** - Registry registration
3. **`app.py`** - UI dropdown, parameter fields, callbacks
4. **`components/charts/indicator_defaults.py`** - Default template
5. **`data/common/indicators.py`** - Calculation function (optional)
## Tips
- Start with a simple single-line indicator first
- Test each step before moving to the next
- Use existing indicators as templates
- Check console/logs for errors
- Test with different parameter values
- Verify calculations with known data

View File

@@ -0,0 +1,310 @@
# Indicator System Documentation
## Overview
The Crypto Trading Bot Dashboard features a comprehensive modular indicator system that allows users to create, customize, and manage technical indicators for chart analysis. The system supports both overlay indicators (displayed on the main price chart) and subplot indicators (displayed in separate panels below the main chart).
## Table of Contents
1. [System Architecture](#system-architecture)
2. [Current Indicators](#current-indicators)
3. [User Interface](#user-interface)
4. [File Structure](#file-structure)
5. [Adding New Indicators](#adding-new-indicators)
6. [Configuration Format](#configuration-format)
7. [API Reference](#api-reference)
8. [Troubleshooting](#troubleshooting)
## System Architecture
### Core Components
```
components/charts/
├── indicator_manager.py # Core indicator CRUD operations
├── indicator_defaults.py # Default indicator templates
├── layers/
│ ├── indicators.py # Overlay indicator rendering
│ └── subplots.py # Subplot indicator rendering
└── config/
└── indicator_defs.py # Indicator definitions and schemas
config/indicators/
└── user_indicators/ # User-created indicators (JSON files)
├── sma_abc123.json
├── ema_def456.json
└── ...
```
### Key Classes
- **`IndicatorManager`**: Handles CRUD operations for user indicators
- **`UserIndicator`**: Data structure for indicator configuration
- **`IndicatorStyling`**: Appearance and styling configuration
- **Indicator Layers**: Rendering classes for different indicator types
## Current Indicators
### Overlay Indicators
These indicators are displayed directly on the price chart:
| Indicator | Type | Parameters | Description |
|-----------|------|------------|-------------|
| **Simple Moving Average (SMA)** | `sma` | `period` (1-200) | Average price over N periods |
| **Exponential Moving Average (EMA)** | `ema` | `period` (1-200) | Weighted average giving more weight to recent prices |
| **Bollinger Bands** | `bollinger_bands` | `period` (5-100), `std_dev` (0.5-5.0) | Price channels based on standard deviation |
### Subplot Indicators
These indicators are displayed in separate panels:
| Indicator | Type | Parameters | Description |
|-----------|------|------------|-------------|
| **Relative Strength Index (RSI)** | `rsi` | `period` (2-50) | Momentum oscillator (0-100 scale) |
| **MACD** | `macd` | `fast_period` (2-50), `slow_period` (5-100), `signal_period` (2-30) | Moving average convergence divergence |
## User Interface
### Adding Indicators
1. **Click " Add New Indicator"** button
2. **Configure Basic Settings**:
- Name: Custom name for the indicator
- Type: Select from available indicator types
- Description: Optional description
3. **Set Parameters**: Type-specific parameters appear dynamically
4. **Customize Styling**:
- Color: Hex color code
- Line Width: 1-5 pixels
5. **Save**: Creates a new JSON file and updates the UI
### Managing Indicators
- **✅ Checkboxes**: Toggle indicator visibility on chart
- **✏️ Edit Button**: Modify existing indicator settings
- **🗑️ Delete Button**: Remove indicator permanently
### Real-time Updates
- Chart updates automatically when indicators are toggled
- Changes are saved immediately to JSON files
- No page refresh required
## File Structure
### Indicator JSON Format
```json
{
"id": "ema_ca5fd53d",
"name": "EMA 10",
"description": "10-period Exponential Moving Average for fast signals",
"type": "ema",
"display_type": "overlay",
"parameters": {
"period": 10
},
"styling": {
"color": "#ff6b35",
"line_width": 2,
"opacity": 1.0,
"line_style": "solid"
},
"visible": true,
"created_date": "2025-06-04T04:16:35.455729+00:00",
"modified_date": "2025-06-04T04:54:49.608549+00:00"
}
```
### Directory Structure
```
config/indicators/
└── user_indicators/
├── sma_abc123.json # Individual indicator files
├── ema_def456.json
├── rsi_ghi789.json
└── macd_jkl012.json
```
## Adding New Indicators
For developers who want to add new indicator types to the system, please refer to the comprehensive step-by-step guide:
**📋 [Quick Guide: Adding New Indicators](./adding-new-indicators.md)**
This guide covers:
- ✅ Complete 11-step implementation checklist
- ✅ Full code examples (Stochastic Oscillator implementation)
- ✅ File modification requirements
- ✅ Testing checklist and common patterns
- ✅ Tips and best practices
## Configuration Format
### User Indicator Structure
```python
@dataclass
class UserIndicator:
id: str # Unique identifier
name: str # Display name
description: str # User description
type: str # Indicator type (sma, ema, etc.)
display_type: str # "overlay" or "subplot"
parameters: Dict[str, Any] # Type-specific parameters
styling: IndicatorStyling # Appearance settings
visible: bool = True # Default visibility
created_date: datetime # Creation timestamp
modified_date: datetime # Last modification timestamp
```
### Styling Options
```python
@dataclass
class IndicatorStyling:
color: str = "#007bff" # Hex color code
line_width: int = 2 # Line thickness (1-5)
opacity: float = 1.0 # Transparency (0.0-1.0)
line_style: str = "solid" # Line style
```
### Parameter Examples
```python
# SMA/EMA Parameters
{"period": 20}
# RSI Parameters
{"period": 14}
# MACD Parameters
{
"fast_period": 12,
"slow_period": 26,
"signal_period": 9
}
# Bollinger Bands Parameters
{
"period": 20,
"std_dev": 2.0
}
```
## API Reference
### IndicatorManager Class
```python
class IndicatorManager:
def create_indicator(self, name: str, indicator_type: str,
parameters: Dict[str, Any], **kwargs) -> Optional[UserIndicator]
def load_indicator(self, indicator_id: str) -> Optional[UserIndicator]
def update_indicator(self, indicator_id: str, **kwargs) -> bool
def delete_indicator(self, indicator_id: str) -> bool
def list_indicators(self) -> List[UserIndicator]
def get_indicators_by_type(self, display_type: str) -> List[UserIndicator]
```
### Usage Examples
```python
# Get indicator manager
manager = get_indicator_manager()
# Create new indicator
indicator = manager.create_indicator(
name="My SMA 50",
indicator_type="sma",
parameters={"period": 50},
description="50-period Simple Moving Average",
color="#ff0000"
)
# Load indicator
loaded = manager.load_indicator("sma_abc123")
# Update indicator
success = manager.update_indicator(
"sma_abc123",
name="Updated SMA",
parameters={"period": 30}
)
# Delete indicator
deleted = manager.delete_indicator("sma_abc123")
# List all indicators
all_indicators = manager.list_indicators()
# Get by type
overlay_indicators = manager.get_indicators_by_type("overlay")
subplot_indicators = manager.get_indicators_by_type("subplot")
```
## Troubleshooting
### Common Issues
1. **Indicator not appearing in dropdown**
- Check if registered in `INDICATOR_REGISTRY`
- Verify the indicator type matches the class name
2. **Parameters not saving**
- Ensure parameter fields are added to save callback
- Check parameter collection logic in `save_new_indicator`
3. **Chart not updating**
- Verify the indicator layer implements `calculate_values` and `create_traces`
- Check if indicator is registered in the correct registry
4. **File permission errors**
- Ensure `config/indicators/user_indicators/` directory is writable
- Check file permissions on existing JSON files
### Debug Information
- Check browser console for JavaScript errors
- Look at application logs for Python exceptions
- Verify JSON file structure with a validator
- Test indicator calculations with sample data
### Performance Considerations
- Indicators with large periods may take longer to calculate
- Consider data availability when setting parameter limits
- Subplot indicators require additional chart space
- Real-time updates may impact performance with many indicators
## Best Practices
1. **Naming Conventions**
- Use descriptive names for indicators
- Include parameter values in names (e.g., "SMA 20")
- Use consistent naming patterns
2. **Parameter Validation**
- Set appropriate min/max values for parameters
- Provide helpful descriptions for parameters
- Use sensible default values
3. **Error Handling**
- Handle insufficient data gracefully
- Provide meaningful error messages
- Log errors for debugging
4. **Performance**
- Cache calculated values when possible
- Optimize calculation algorithms
- Limit the number of active indicators
5. **User Experience**
- Provide immediate visual feedback
- Use intuitive color schemes
- Group related indicators logically