TCPDashboard/docs/modules/charts/configuration.md
Vasily.onl 3e0e89b826 Refactor indicator management to a data-driven approach
- Introduced dynamic generation of parameter fields and callback handling for indicators, enhancing modularity and maintainability.
- Updated `config_utils.py` with new utility functions to load indicator templates and generate dynamic outputs and states for parameter fields.
- Refactored `indicators.py` to utilize these utilities, streamlining the callback logic and improving user experience by reducing hardcoded elements.
- Modified `indicator_modal.py` to create parameter fields dynamically based on JSON templates, eliminating the need for manual updates when adding new indicators.
- Added documentation outlining the new data-driven architecture for indicators, improving clarity and guidance for future development.

These changes significantly enhance the flexibility and scalability of the indicator system, aligning with project goals for maintainability and performance.
2025-06-11 19:09:52 +08:00

23 KiB

Chart Configuration System

The Chart Configuration System provides comprehensive management of chart settings, indicator definitions, and trading strategy configurations. It includes schema validation, default presets, and extensible configuration patterns.

Table of Contents

Overview

The configuration system is built around three core concepts:

  1. Indicator Definitions - Schema and validation for technical indicators
  2. Default Configurations - Pre-built indicator presets organized by category
  3. Strategy Configurations - Complete chart setups for trading strategies

Architecture

components/charts/config/
├── indicator_defs.py     # Core schemas and validation
├── defaults.py           # Default indicator presets
├── strategy_charts.py    # Strategy configurations
├── validation.py         # Validation system
├── example_strategies.py # Real-world examples
└── __init__.py          # Package exports

Indicator Definitions

The indicator definitions are now primarily managed through JSON template files located in config/indicators/templates/. These JSON files define the schema, default parameters, display properties, and styling for each technical indicator. This approach allows for easy addition and modification of indicators without requiring code changes.

Core Schema Fields (defined in JSON templates)

Each indicator JSON template includes the following key fields:

  • name: Display name of the indicator (e.g., "Simple Moving Average")
  • description: Brief explanation of the indicator.
  • type: Unique identifier for the indicator (e.g., "sma", "ema"). This is used for internal mapping.
  • display_type: How the indicator is rendered on the chart ("overlay" or "subplot").
  • timeframe: Optional default timeframe for the indicator (can be null for chart timeframe).
  • default_parameters: Default values for the indicator's calculation parameters.
  • parameter_schema: Defines the type, validation rules (min/max), default values, and descriptions for each parameter.
  • default_styling: Default color, line width, and other visual properties.

Example JSON Template (config/indicators/templates/sma_template.json):

{
  "name": "Simple Moving Average",
  "description": "Simple Moving Average indicator",
  "type": "sma",
  "display_type": "overlay",
  "timeframe": null,
  "default_parameters": {
    "period": 20
  },
  "parameter_schema": {
    "period": {
      "type": "int",
      "min": 1,
      "max": 200,
      "default": 20,
      "description": "Period for SMA calculation"
    },
    "timeframe": {
      "type": "string",
      "default": null,
      "description": "Indicator timeframe (e.g., '1h', '4h'). Null for chart timeframe."
    }
  },
  "default_styling": {
    "color": "#007bff",
    "line_width": 2
  }
}

ChartIndicatorConfig (Python representation)

The ChartIndicatorConfig Python dataclass in components/charts/config/indicator_defs.py serves as the runtime representation of an indicator's configuration, parsed from the JSON templates.

@dataclass
class ChartIndicatorConfig:
    name: str
    indicator_type: str
    parameters: Dict[str, Any]
    display_type: str  # 'overlay', 'subplot'
    color: str
    line_style: str = 'solid'  # 'solid', 'dash', 'dot'
    line_width: int = 2
    opacity: float = 1.0
    visible: bool = True
    subplot_height_ratio: float = 0.3  # For subplot indicators

Enums (for internal type safety)

Enums like IndicatorType, DisplayType, LineStyle are still used internally for type safety and consistent value representation within the Python codebase.

IndicatorType

class IndicatorType(str, Enum):
    SMA = "sma"
    EMA = "ema"
    RSI = "rsi"
    MACD = "macd"
    BOLLINGER_BANDS = "bollinger_bands"
    VOLUME = "volume"
    # ... new indicator types should be added here for internal consistency

DisplayType

class DisplayType(str, Enum):
    OVERLAY = "overlay"      # Overlaid on price chart
    SUBPLOT = "subplot"      # Separate subplot
    HISTOGRAM = "histogram"  # Histogram display

LineStyle

class LineStyle(str, Enum):
    SOLID = "solid"
    DASHED = "dash"
    DOTTED = "dot"
    DASH_DOT = "dashdot"

PriceColumn

class PriceColumn(str, Enum):
    OPEN = "open"
    HIGH = "high"
    LOW = "low"
    CLOSE = "close"
    VOLUME = "volume"

Schema Validation (driven by JSON templates)

The validation system now primarily reads parameter schemas from the JSON templates. The IndicatorParameterSchema and IndicatorSchema dataclasses are used for internal representation when parsing and validating these JSON definitions.

IndicatorParameterSchema

Defines validation rules for indicator parameters:

@dataclass
class IndicatorParameterSchema:
    name: str
    type: type
    required: bool = True
    default: Any = None
    min_value: Optional[Union[int, float]] = None
    max_value: Optional[Union[int, float]] = None
    description: str = ""

IndicatorSchema

Complete schema for an indicator type:

@dataclass
class IndicatorSchema:
    indicator_type: IndicatorType
    display_type: DisplayType
    required_parameters: List[IndicatorParameterSchema]
    optional_parameters: List[IndicatorParameterSchema] = field(default_factory=list)
    min_data_points: int = 1
    description: str = ""

Schema Definitions (now loaded dynamically)

The INDICATOR_SCHEMAS dictionary is now populated dynamically at runtime by loading and parsing the JSON template files. Manual definitions in indicator_defs.py are deprecated.

Utility Functions

Validation Functions

# Validate individual indicator configuration
def validate_indicator_configuration(config: ChartIndicatorConfig) -> tuple[bool, List[str]]

# Create indicator configuration with validation
def create_indicator_config(
    name: str,
    indicator_type: str,
    parameters: Dict[str, Any],
    display_type: Optional[str] = None,
    color: str = "#007bff",
    **display_options
) -> tuple[Optional[ChartIndicatorConfig], List[str]]

# Get schema for indicator type
def get_indicator_schema(indicator_type: str) -> Optional[IndicatorSchema]

# Get available indicator types
def get_available_indicator_types() -> List[str]

# Validate parameters for specific type
def validate_parameters_for_type(
    indicator_type: str, 
    parameters: Dict[str, Any]
) -> tuple[bool, List[str]]

Default Configurations

Organization

Default configurations are organized by category and trading strategy:

Categories

class IndicatorCategory(str, Enum):
    TREND = "trend"
    MOMENTUM = "momentum"
    VOLATILITY = "volatility"
    VOLUME = "volume"
    SUPPORT_RESISTANCE = "support_resistance"

Trading Strategies

class TradingStrategy(str, Enum):
    SCALPING = "scalping"
    DAY_TRADING = "day_trading"
    SWING_TRADING = "swing_trading"
    POSITION_TRADING = "position_trading"
    MOMENTUM = "momentum"
    MEAN_REVERSION = "mean_reversion"

Indicator Presets

IndicatorPreset

Container for pre-configured indicators:

@dataclass
class IndicatorPreset:
    name: str
    config: ChartIndicatorConfig
    category: IndicatorCategory
    description: str
    recommended_timeframes: List[str]
    suitable_strategies: List[TradingStrategy]
    notes: List[str] = field(default_factory=list)

Available Presets

Trend Indicators (13 presets)

  • sma_5, sma_10, sma_20, sma_50, sma_100, sma_200
  • ema_5, ema_12, ema_21, ema_26, ema_50, ema_100, ema_200

Momentum Indicators (9 presets)

  • rsi_7, rsi_14, rsi_21
  • macd_5_13_4, macd_8_17_6, macd_12_26_9, macd_19_39_13

Volatility Indicators (4 presets)

  • bb_10_15, bb_20_15, bb_20_20, bb_50_20

Color Schemes

Organized color palettes by category:

CATEGORY_COLORS = {
    IndicatorCategory.TREND: {
        "primary": "#2E86C1",    # Blue
        "secondary": "#5DADE2",  # Light Blue
        "accent": "#1F618D"      # Dark Blue
    },
    IndicatorCategory.MOMENTUM: {
        "primary": "#E74C3C",    # Red
        "secondary": "#F1948A",  # Light Red
        "accent": "#C0392B"      # Dark Red
    },
    # ... more colors
}

Access Functions

# Get all default indicators
def get_all_default_indicators() -> Dict[str, IndicatorPreset]

# Filter by category
def get_indicators_by_category(category: IndicatorCategory) -> Dict[str, IndicatorPreset]

# Filter by timeframe
def get_indicators_for_timeframe(timeframe: str) -> Dict[str, IndicatorPreset]

# Get strategy-specific indicators
def get_strategy_indicators(strategy: TradingStrategy) -> Dict[str, IndicatorPreset]

# Create custom preset
def create_custom_preset(
    name: str,
    indicator_type: IndicatorType,
    parameters: Dict[str, Any],
    category: IndicatorCategory,
    **kwargs
) -> tuple[Optional[IndicatorPreset], List[str]]

Strategy Configurations

Core Classes

StrategyChartConfig

Complete chart configuration for a trading strategy:

@dataclass
class StrategyChartConfig:
    strategy_name: str
    strategy_type: TradingStrategy
    description: str
    timeframes: List[str]
    
    # Chart layout
    layout: ChartLayout = ChartLayout.MAIN_WITH_SUBPLOTS
    main_chart_height: float = 0.7
    
    # Indicators
    overlay_indicators: List[str] = field(default_factory=list)
    subplot_configs: List[SubplotConfig] = field(default_factory=list)
    
    # Style
    chart_style: ChartStyle = field(default_factory=ChartStyle)
    
    # Metadata
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None
    version: str = "1.0"
    tags: List[str] = field(default_factory=list)

SubplotConfig

Configuration for chart subplots:

@dataclass
class SubplotConfig:
    subplot_type: SubplotType
    height_ratio: float = 0.3
    indicators: List[str] = field(default_factory=list)
    title: Optional[str] = None
    y_axis_label: Optional[str] = None
    show_grid: bool = True
    show_legend: bool = True
    background_color: Optional[str] = None

ChartStyle

Comprehensive chart styling:

@dataclass
class ChartStyle:
    theme: str = "plotly_white"
    background_color: str = "#ffffff"
    grid_color: str = "#e6e6e6"
    text_color: str = "#2c3e50"
    font_family: str = "Arial, sans-serif"
    font_size: int = 12
    candlestick_up_color: str = "#26a69a"
    candlestick_down_color: str = "#ef5350"
    volume_color: str = "#78909c"
    show_volume: bool = True
    show_grid: bool = True
    show_legend: bool = True
    show_toolbar: bool = True

Default Strategy Configurations

Pre-built strategy configurations for common trading approaches:

  1. Scalping Strategy

    • Ultra-fast indicators (EMA 5, 12, 21)
    • Fast RSI (7) and MACD (5,13,4)
    • 1m-5m timeframes
  2. Day Trading Strategy

    • Balanced indicators (SMA 20, EMA 12/26, BB 20,2.0)
    • Standard RSI (14) and MACD (12,26,9)
    • 5m-1h timeframes
  3. Swing Trading Strategy

    • Longer-term indicators (SMA 50, EMA 21/50, BB 20,2.0)
    • Standard momentum indicators
    • 1h-1d timeframes

Configuration Functions

# Create default strategy configurations
def create_default_strategy_configurations() -> Dict[str, StrategyChartConfig]

# Create custom strategy
def create_custom_strategy_config(
    strategy_name: str,
    strategy_type: TradingStrategy,
    description: str,
    timeframes: List[str],
    overlay_indicators: List[str],
    subplot_configs: List[Dict[str, Any]],
    **kwargs
) -> tuple[Optional[StrategyChartConfig], List[str]]

# JSON import/export
def load_strategy_config_from_json(json_data: Union[str, Dict[str, Any]]) -> tuple[Optional[StrategyChartConfig], List[str]]
def export_strategy_config_to_json(config: StrategyChartConfig) -> str

# Access functions
def get_strategy_config(strategy_name: str) -> Optional[StrategyChartConfig]
def get_all_strategy_configs() -> Dict[str, StrategyChartConfig]
def get_available_strategy_names() -> List[str]

Validation System

Validation Rules

The system includes 10 comprehensive validation rules:

  1. REQUIRED_FIELDS - Validates essential configuration fields
  2. HEIGHT_RATIOS - Ensures chart height ratios sum correctly
  3. INDICATOR_EXISTENCE - Checks indicator availability
  4. TIMEFRAME_FORMAT - Validates timeframe patterns
  5. CHART_STYLE - Validates styling options
  6. SUBPLOT_CONFIG - Validates subplot configurations
  7. STRATEGY_CONSISTENCY - Checks strategy-timeframe alignment
  8. PERFORMANCE_IMPACT - Warns about performance issues
  9. INDICATOR_CONFLICTS - Detects redundant indicators
  10. RESOURCE_USAGE - Estimates resource consumption

Validation Classes

ValidationReport

Comprehensive validation results:

@dataclass
class ValidationReport:
    is_valid: bool
    errors: List[ValidationIssue] = field(default_factory=list)
    warnings: List[ValidationIssue] = field(default_factory=list)
    info: List[ValidationIssue] = field(default_factory=list)
    debug: List[ValidationIssue] = field(default_factory=list)
    validation_time: Optional[datetime] = None
    rules_applied: Set[ValidationRule] = field(default_factory=set)

ValidationIssue

Individual validation issue:

@dataclass
class ValidationIssue:
    level: ValidationLevel
    rule: ValidationRule
    message: str
    field_path: str = ""
    suggestion: Optional[str] = None
    auto_fix: Optional[str] = None
    context: Dict[str, Any] = field(default_factory=dict)

Validation Usage

from components.charts.config import validate_configuration

# Comprehensive validation
report = validate_configuration(config)

# Check results
if report.is_valid:
    print("✅ Configuration is valid")
else:
    print("❌ Configuration has errors:")
    for error in report.errors:
        print(f"  • {error}")

# Handle warnings
if report.warnings:
    print("⚠️ Warnings:")
    for warning in report.warnings:
        print(f"  • {warning}")

Configuration Files

File Structure

components/charts/config/
├── __init__.py              # Package exports and public API
├── indicator_defs.py        # Core indicator schemas and validation
├── defaults.py              # Default indicator presets and categories
├── strategy_charts.py       # Strategy configuration classes and defaults
├── validation.py            # Validation system and rules
└── example_strategies.py    # Real-world trading strategy examples

Key Exports

From __init__.py:

# Core classes
from .indicator_defs import (
    IndicatorType, DisplayType, LineStyle, PriceColumn,
    IndicatorParameterSchema, IndicatorSchema, ChartIndicatorConfig
)

# Default configurations
from .defaults import (
    IndicatorCategory, TradingStrategy, IndicatorPreset,
    get_all_default_indicators, get_indicators_by_category
)

# Strategy configurations  
from .strategy_charts import (
    ChartLayout, SubplotType, SubplotConfig, ChartStyle, StrategyChartConfig,
    create_default_strategy_configurations
)

# Validation system
from .validation import (
    ValidationLevel, ValidationRule, ValidationIssue, ValidationReport,
    validate_configuration
)

# Utility functions from indicator_defs
from .indicator_defs import (
    create_indicator_config, get_indicator_schema, get_available_indicator_types
)

Usage Examples

Example 1: Creating Custom Indicator

from components.charts.config import (
    create_indicator_config, IndicatorType
)

# Create custom EMA configuration
config, errors = create_indicator_config(
    name="EMA 21",
    indicator_type=IndicatorType.EMA,
    parameters={"period": 21, "price_column": "close"},
    color="#2E86C1",
    line_width=2
)

if config:
    print(f"Created: {config.name}")
else:
    print(f"Errors: {errors}")

Example 2: Using Default Presets

from components.charts.config import (
    get_all_default_indicators,
    get_indicators_by_category,
    IndicatorCategory
)

# Get all available indicators
all_indicators = get_all_default_indicators()
print(f"Available indicators: {len(all_indicators)}")

# Get trend indicators only
trend_indicators = get_indicators_by_category(IndicatorCategory.TREND)
for name, preset in trend_indicators.items():
    print(f"{name}: {preset.description}")

Example 3: Strategy Configuration

from components.charts.config import (
    create_custom_strategy_config,
    TradingStrategy
)

# Create custom momentum strategy
config, errors = create_custom_strategy_config(
    strategy_name="Custom Momentum",
    strategy_type=TradingStrategy.MOMENTUM,
    description="Fast momentum trading strategy",
    timeframes=["5m", "15m"],
    overlay_indicators=["ema_8", "ema_21"],
    subplot_configs=[{
        "subplot_type": "rsi",
        "height_ratio": 0.2,
        "indicators": ["rsi_7"]
    }]
)

if config:
    print(f"Created strategy: {config.strategy_name}")
    is_valid, validation_errors = config.validate()
    if is_valid:
        print("Strategy is valid!")
    else:
        print(f"Validation errors: {validation_errors}")

Example 4: Comprehensive Validation

from components.charts.config import (
    validate_configuration,
    ValidationRule
)

# Validate with specific rules
rules = {ValidationRule.REQUIRED_FIELDS, ValidationRule.HEIGHT_RATIOS}
report = validate_configuration(config, rules=rules)

# Detailed error handling
for error in report.errors:
    print(f"ERROR: {error.message}")
    if error.suggestion:
        print(f"  Suggestion: {error.suggestion}")
    if error.auto_fix:
        print(f"  Auto-fix: {error.auto_fix}")

# Performance warnings
performance_issues = report.get_issues_by_rule(ValidationRule.PERFORMANCE_IMPACT)
if performance_issues:
    print(f"Performance concerns: {len(performance_issues)}")

Extension Guide

Adding New Indicators

  1. Define Indicator Type

    • Add to IndicatorType enum (if not already present)
  2. Create JSON Template

    • Create a new JSON file in config/indicators/templates/ (e.g., stochastic_template.json)
    • Define the indicator's name, type, display type, default parameters, parameter schema, and default styling.
    • Example (stochastic_template.json):
      {
        "name": "Stochastic Oscillator",
        "description": "Stochastic momentum oscillator indicator",
        "type": "stochastic",
        "display_type": "subplot",
        "timeframe": null,
        "default_parameters": {
          "k_period": 14,
          "d_period": 3,
          "smooth_k": 1
        },
        "parameter_schema": {
          "k_period": {
            "type": "int",
            "min": 2,
            "max": 50,
            "default": 14,
            "description": "Period for %K calculation"
          },
          "d_period": {
            "type": "int",
            "min": 1,
            "max": 20,
            "default": 3,
            "description": "Period for %D (moving average of %K)"
          },
          "smooth_k": {
            "type": "int",
            "min": 1,
            "max": 10,
            "default": 1,
            "description": "Smoothing factor for %K"
          },
          "timeframe": {
            "type": "string",
            "default": null,
            "description": "Indicator timeframe (e.g., '1h', '4h'). Null for chart timeframe."
          }
        },
        "default_styling": {
          "color": "#e83e8c",
          "line_width": 2
        }
      }
      
  3. Create Default Presets

    # Add to defaults.py
    def create_momentum_indicators():
        # ... existing indicators
        indicators["stoch_14"] = IndicatorPreset(
            name="stoch_14",
            config=create_indicator_config(
                IndicatorType.STOCHASTIC,
                {"k_period": 14, "d_period": 3},
                display_name="Stochastic %K(14,%D(3))",
                color=CATEGORY_COLORS[IndicatorCategory.MOMENTUM]["primary"]
            )[0],
            category=IndicatorCategory.MOMENTUM,
            description="Standard Stochastic oscillator",
            recommended_timeframes=["15m", "1h", "4h"],
            suitable_strategies=[TradingStrategy.SWING_TRADING]
        )
    

Adding New Validation Rules

  1. Define Rule

    # Add to ValidationRule enum
    class ValidationRule(str, Enum):
        # ... existing rules
        CUSTOM_RULE = "custom_rule"
    
  2. Implement Validation

    # Add to ConfigurationValidator
    def _validate_custom_rule(self, config: StrategyChartConfig, report: ValidationReport) -> None:
        # Custom validation logic
        if some_condition:
            report.add_issue(ValidationIssue(
                level=ValidationLevel.WARNING,
                rule=ValidationRule.CUSTOM_RULE,
                message="Custom validation message",
                suggestion="Suggested fix"
            ))
    
  3. Add to Validator

    # Add to validate_strategy_config method
    if ValidationRule.CUSTOM_RULE in self.enabled_rules:
        self._validate_custom_rule(config, report)
    

Adding New Strategy Types

  1. Define Strategy Type

    # Add to TradingStrategy enum
    class TradingStrategy(str, Enum):
        # ... existing strategies
        GRID_TRADING = "grid_trading"
    
  2. Create Strategy Configuration

    # Add to create_default_strategy_configurations()
    strategy_configs["grid_trading"] = StrategyChartConfig(
        strategy_name="Grid Trading Strategy",
        strategy_type=TradingStrategy.GRID_TRADING,
        description="Grid trading with support/resistance levels",
        timeframes=["1h", "4h"],
        overlay_indicators=["sma_20", "sma_50"],
        # ... complete configuration
    )
    
  3. Add Example Strategy

    # Create in example_strategies.py
    def create_grid_trading_strategy() -> StrategyExample:
        config = StrategyChartConfig(...)
        return StrategyExample(
            config=config,
            description="Grid trading strategy description...",
            difficulty="Intermediate",
            risk_level="Medium"
        )
    

The configuration system is designed to be highly extensible while maintaining type safety and comprehensive validation. All additions should follow the established patterns and include appropriate tests.