TCPDashboard/config/indicators/config_utils.py

167 lines
5.4 KiB
Python
Raw Normal View History

"""
Utility functions for loading and managing indicator configurations.
"""
import json
import os
import logging
from typing import List, Dict, Any, Optional
logger = logging.getLogger(__name__)
def load_indicator_templates() -> Dict[str, Dict[str, Any]]:
"""Load all indicator templates from the templates directory.
Returns:
Dict[str, Dict[str, Any]]: Dictionary mapping indicator type to template configuration
"""
templates = {}
try:
# Get the templates directory path
templates_dir = os.path.join(os.path.dirname(__file__), 'templates')
if not os.path.exists(templates_dir):
logger.error(f"Templates directory not found at {templates_dir}")
return {}
# Load all JSON files from templates directory
for filename in os.listdir(templates_dir):
if filename.endswith('_template.json'):
file_path = os.path.join(templates_dir, filename)
try:
with open(file_path, 'r', encoding='utf-8') as f:
template = json.load(f)
indicator_type = template.get('type')
if indicator_type:
templates[indicator_type] = template
else:
logger.warning(f"Template {filename} missing 'type' field")
except json.JSONDecodeError as e:
logger.error(f"Error decoding JSON from {filename}: {e}")
except Exception as e:
logger.error(f"Error loading template {filename}: {e}")
except Exception as e:
logger.error(f"Error loading indicator templates: {e}")
return templates
def get_indicator_dropdown_options() -> List[Dict[str, str]]:
"""Generate dropdown options for indicator types from templates.
Returns:
List[Dict[str, str]]: List of dropdown options with label and value
"""
templates = load_indicator_templates()
options = []
for indicator_type, template in templates.items():
option = {
'label': template.get('name', indicator_type.upper()),
'value': indicator_type
}
options.append(option)
# Sort by label for consistent UI
options.sort(key=lambda x: x['label'])
return options
def get_indicator_parameter_schema(indicator_type: str) -> Optional[Dict[str, Any]]:
"""Get parameter schema for a specific indicator type.
Args:
indicator_type (str): The indicator type (e.g., 'sma', 'ema')
Returns:
Optional[Dict[str, Any]]: Parameter schema or None if not found
"""
templates = load_indicator_templates()
template = templates.get(indicator_type)
if template:
return template.get('parameter_schema', {})
return None
def get_indicator_default_parameters(indicator_type: str) -> Optional[Dict[str, Any]]:
"""Get default parameters for a specific indicator type.
Args:
indicator_type (str): The indicator type (e.g., 'sma', 'ema')
Returns:
Optional[Dict[str, Any]]: Default parameters or None if not found
"""
templates = load_indicator_templates()
template = templates.get(indicator_type)
if template:
return template.get('default_parameters', {})
return None
def get_indicator_default_styling(indicator_type: str) -> Optional[Dict[str, Any]]:
"""Get default styling for a specific indicator type.
Args:
indicator_type (str): The indicator type (e.g., 'sma', 'ema')
Returns:
Optional[Dict[str, Any]]: Default styling or None if not found
"""
templates = load_indicator_templates()
template = templates.get(indicator_type)
if template:
return template.get('default_styling', {})
return None
def generate_parameter_fields_config(indicator_type: str) -> Optional[Dict[str, Any]]:
"""Generate parameter field configuration for dynamic UI generation.
Args:
indicator_type (str): The indicator type (e.g., 'sma', 'ema')
Returns:
Optional[Dict[str, Any]]: Configuration for generating parameter input fields
"""
schema = get_indicator_parameter_schema(indicator_type)
defaults = get_indicator_default_parameters(indicator_type)
if not schema or not defaults:
return None
fields_config = {}
for param_name, param_schema in schema.items():
# Skip timeframe as it's handled separately in the modal
if param_name == 'timeframe':
continue
field_config = {
'type': param_schema.get('type', 'int'),
'label': param_name.replace('_', ' ').title(),
'default': defaults.get(param_name, param_schema.get('default')),
'description': param_schema.get('description', ''),
'input_id': f'{indicator_type}-{param_name.replace("_", "-")}-input'
}
# Add validation constraints if present
if 'min' in param_schema:
field_config['min'] = param_schema['min']
if 'max' in param_schema:
field_config['max'] = param_schema['max']
if 'step' in param_schema:
field_config['step'] = param_schema['step']
fields_config[param_name] = field_config
return fields_config