115 lines
3.2 KiB
Python
115 lines
3.2 KiB
Python
#!/usr/bin/env python3
|
|
|
|
"""
|
|
ui_models.py - Pydantic Models and Data Structures
|
|
|
|
Defines all API request/response models and data validation schemas
|
|
"""
|
|
|
|
from datetime import datetime
|
|
from decimal import Decimal
|
|
from typing import Dict, List, Optional, Any, Union
|
|
from pydantic import BaseModel, Field, validator
|
|
|
|
|
|
# Pydantic models for API requests/responses
|
|
|
|
class TradingPairConfig(BaseModel):
|
|
"""Configuration for a trading pair"""
|
|
symbol: str
|
|
enabled: bool
|
|
priority: int = 1
|
|
record_from_date: Optional[str] = None
|
|
|
|
|
|
class TradingPairAdd(BaseModel):
|
|
"""Request to add a new trading pair"""
|
|
symbol: str
|
|
priority: int = 1
|
|
record_from_date: Optional[str] = None
|
|
|
|
|
|
class BulkDownloadRequest(BaseModel):
|
|
"""Request for bulk historical data download"""
|
|
symbols: List[str] # Changed from 'symbol' to 'symbols' to support multiple
|
|
start_date: str
|
|
end_date: Optional[str] = None
|
|
intervals: Optional[List[str]] = None
|
|
|
|
|
|
class GapFillRequest(BaseModel):
|
|
"""Request to fill data gaps"""
|
|
symbol: str
|
|
interval: str
|
|
gap_start: str
|
|
gap_end: str
|
|
|
|
|
|
class AutoGapFillRequest(BaseModel):
|
|
"""Request to automatically fill gaps for a symbol"""
|
|
symbol: str
|
|
intervals: Optional[List[str]] = None
|
|
fill_genuine_gaps: bool = True
|
|
|
|
|
|
class GapDetectionRequest(BaseModel):
|
|
"""Request to detect gaps"""
|
|
symbol: Optional[str] = None
|
|
interval: Optional[str] = None
|
|
|
|
|
|
class TechnicalIndicatorsConfig(BaseModel):
|
|
"""Complete technical indicators configuration (matching config.conf structure)"""
|
|
enabled: Optional[List[str]] = None
|
|
periods: Optional[Dict[str, Any]] = None
|
|
calculation_intervals: Optional[List[str]] = None
|
|
|
|
class Config:
|
|
extra = "allow" # Allow additional fields
|
|
|
|
|
|
class ConfigUpdate(BaseModel):
|
|
"""Update application configuration - accepts partial updates"""
|
|
trading_pairs: Optional[List[TradingPairConfig]] = None
|
|
technical_indicators: Optional[Dict[str, Any]] = None
|
|
collection: Optional[Dict[str, Any]] = None
|
|
gap_filling: Optional[Dict[str, Any]] = None
|
|
database: Optional[Dict[str, Any]] = None
|
|
ui: Optional[Dict[str, Any]] = None
|
|
monitoring: Optional[Dict[str, Any]] = None
|
|
alerts: Optional[Dict[str, Any]] = None
|
|
data_quality: Optional[Dict[str, Any]] = None
|
|
features: Optional[Dict[str, Any]] = None
|
|
system: Optional[Dict[str, Any]] = None
|
|
|
|
class Config:
|
|
extra = "allow" # Allow additional config sections
|
|
|
|
|
|
class EnvVarUpdate(BaseModel):
|
|
"""Update environment variable"""
|
|
key: str
|
|
value: str
|
|
|
|
|
|
class ChartDataRequest(BaseModel):
|
|
"""Request chart data for visualization"""
|
|
symbol: str
|
|
interval: str = "1h"
|
|
limit: int = 500
|
|
|
|
|
|
# Utility functions for JSON serialization
|
|
|
|
def serialize_for_json(obj: Any) -> Any:
|
|
"""Recursively serialize datetime and Decimal objects in nested structures"""
|
|
if isinstance(obj, datetime):
|
|
return obj.isoformat()
|
|
elif isinstance(obj, Decimal):
|
|
return float(obj)
|
|
elif isinstance(obj, dict):
|
|
return {k: serialize_for_json(v) for k, v in obj.items()}
|
|
elif isinstance(obj, list):
|
|
return [serialize_for_json(item) for item in obj]
|
|
return obj
|