Local changes: Updated model training, removed debug instrumentation, and configuration improvements

This commit is contained in:
kfox
2025-12-26 01:15:43 -05:00
commit cc60da49e7
388 changed files with 57127 additions and 0 deletions

0
src/alerts/__init__.py Normal file
View File

26
src/alerts/channels.py Normal file
View File

@@ -0,0 +1,26 @@
"""Alert delivery channels."""
from typing import Optional
from src.ui.utils.notifications import get_notification_manager
from src.core.logger import get_logger
logger = get_logger(__name__)
class AlertChannel:
"""Manages alert delivery channels."""
def __init__(self):
"""Initialize alert channel."""
self.notifications = get_notification_manager()
self.logger = get_logger(__name__)
def send(self, alert_type: str, message: str):
"""Send alert through all channels.
Args:
alert_type: Alert type
message: Alert message
"""
self.notifications.notify_alert(alert_type, message)

139
src/alerts/engine.py Normal file
View File

@@ -0,0 +1,139 @@
"""Alert rule engine."""
from decimal import Decimal
from typing import Dict, Optional, Callable, List
from datetime import datetime
from sqlalchemy.orm import Session
from src.core.database import get_database, Alert
from src.core.logger import get_logger
from .channels import AlertChannel
logger = get_logger(__name__)
class AlertEngine:
"""Alert rule engine."""
def __init__(self):
"""Initialize alert engine."""
self.db = get_database()
self.logger = get_logger(__name__)
self.channel = AlertChannel()
self._active_alerts: Dict[int, Dict] = {}
def evaluate_price_alert(
self,
alert_id: int,
symbol: str,
current_price: Decimal
) -> bool:
"""Evaluate price alert.
Args:
alert_id: Alert ID
symbol: Trading symbol
current_price: Current price
Returns:
True if alert should trigger
"""
session = self.db.get_session()
try:
alert = session.query(Alert).filter_by(id=alert_id).first()
if not alert or not alert.enabled:
return False
condition = alert.condition
alert_type = condition.get('type')
threshold = Decimal(str(condition.get('threshold', 0)))
operator = condition.get('operator', '>') # >, <, >=, <=
if alert_type == 'price_above':
return current_price > threshold
elif alert_type == 'price_below':
return current_price < threshold
elif alert_type == 'price_change':
# Would need previous price
return False
return False
finally:
session.close()
def evaluate_indicator_alert(
self,
alert_id: int,
indicator_value: float
) -> bool:
"""Evaluate indicator alert.
Args:
alert_id: Alert ID
indicator_value: Current indicator value
Returns:
True if alert should trigger
"""
session = self.db.get_session()
try:
alert = session.query(Alert).filter_by(id=alert_id).first()
if not alert or not alert.enabled:
return False
condition = alert.condition
threshold = float(condition.get('threshold', 0))
operator = condition.get('operator', '>')
if operator == '>':
return indicator_value > threshold
elif operator == '<':
return indicator_value < threshold
elif operator == 'crosses_above':
# Would need previous value
return False
elif operator == 'crosses_below':
# Would need previous value
return False
return False
finally:
session.close()
def trigger_alert(self, alert_id: int, message: str):
"""Trigger an alert.
Args:
alert_id: Alert ID
message: Alert message
"""
session = self.db.get_session()
try:
alert = session.query(Alert).filter_by(id=alert_id).first()
if not alert:
return
alert.triggered = True
alert.triggered_at = datetime.utcnow()
session.commit()
# Send notification
self.channel.send(alert.alert_type, message)
logger.info(f"Alert {alert_id} triggered: {message}")
except Exception as e:
session.rollback()
logger.error(f"Failed to trigger alert {alert_id}: {e}")
finally:
session.close()
# Global alert engine
_alert_engine: Optional[AlertEngine] = None
def get_alert_engine() -> AlertEngine:
"""Get global alert engine instance."""
global _alert_engine
if _alert_engine is None:
_alert_engine = AlertEngine()
return _alert_engine

78
src/alerts/manager.py Normal file
View File

@@ -0,0 +1,78 @@
"""Alert management."""
from typing import Dict, Optional, List
from sqlalchemy import select
from src.core.database import get_database, Alert
from src.core.logger import get_logger
logger = get_logger(__name__)
class AlertManager:
"""Manages alerts."""
def __init__(self):
"""Initialize alert manager."""
self.db = get_database()
self.logger = get_logger(__name__)
async def create_alert(
self,
name: str,
alert_type: str,
condition: Dict
) -> Alert:
"""Create a new alert.
Args:
name: Alert name
alert_type: Alert type (price, indicator, risk, system)
condition: Alert condition configuration
Returns:
Alert object
"""
async with self.db.get_session() as session:
try:
alert = Alert(
name=name,
alert_type=alert_type,
condition=condition,
enabled=True
)
session.add(alert)
await session.commit()
await session.refresh(alert)
return alert
except Exception as e:
await session.rollback()
logger.error(f"Failed to create alert: {e}")
raise
async def list_alerts(self, enabled_only: bool = False) -> List[Alert]:
"""List all alerts.
Args:
enabled_only: Only return enabled alerts
Returns:
List of alerts
"""
async with self.db.get_session() as session:
stmt = select(Alert)
if enabled_only:
stmt = stmt.where(Alert.enabled == True)
result = await session.execute(stmt)
return result.scalars().all()
# Global alert manager
_alert_manager: Optional[AlertManager] = None
def get_alert_manager() -> AlertManager:
"""Get global alert manager instance."""
global _alert_manager
if _alert_manager is None:
_alert_manager = AlertManager()
return _alert_manager