Local changes: Updated model training, removed debug instrumentation, and configuration improvements
This commit is contained in:
0
src/alerts/__init__.py
Normal file
0
src/alerts/__init__.py
Normal file
26
src/alerts/channels.py
Normal file
26
src/alerts/channels.py
Normal 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
139
src/alerts/engine.py
Normal 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
78
src/alerts/manager.py
Normal 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
|
||||
Reference in New Issue
Block a user