|
@@ -10,8 +10,7 @@ from .position_tracker import PositionTracker
|
|
from .pending_orders_manager import PendingOrdersManager
|
|
from .pending_orders_manager import PendingOrdersManager
|
|
from .risk_manager import RiskManager
|
|
from .risk_manager import RiskManager
|
|
from .alarm_manager import AlarmManager
|
|
from .alarm_manager import AlarmManager
|
|
-from .drawdown_monitor import DrawdownMonitor
|
|
|
|
-from .rsi_monitor import RSIMonitor
|
|
|
|
|
|
+# DrawdownMonitor and RsiMonitor will be lazy-loaded to avoid circular imports
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@@ -31,9 +30,14 @@ class MonitoringCoordinator:
|
|
self.position_tracker = PositionTracker(hl_client, notification_manager)
|
|
self.position_tracker = PositionTracker(hl_client, notification_manager)
|
|
self.pending_orders_manager = PendingOrdersManager(hl_client, notification_manager)
|
|
self.pending_orders_manager = PendingOrdersManager(hl_client, notification_manager)
|
|
self.risk_manager = RiskManager(hl_client, notification_manager, config)
|
|
self.risk_manager = RiskManager(hl_client, notification_manager, config)
|
|
- self.alarm_manager = AlarmManager(hl_client, notification_manager, config)
|
|
|
|
- self.drawdown_monitor = DrawdownMonitor(hl_client, notification_manager, config)
|
|
|
|
- self.rsi_monitor = RSIMonitor(hl_client, notification_manager, config)
|
|
|
|
|
|
+ self.alarm_manager = AlarmManager() # AlarmManager only needs alarms_file (defaults to data/price_alarms.json)
|
|
|
|
+
|
|
|
|
+ # DrawdownMonitor and RSIMonitor will be lazy-loaded to avoid circular imports
|
|
|
|
+ self.drawdown_monitor = None
|
|
|
|
+ self.rsi_monitor = None
|
|
|
|
+ self._hl_client = hl_client
|
|
|
|
+ self._notification_manager = notification_manager
|
|
|
|
+ self._config = config
|
|
|
|
|
|
async def start(self):
|
|
async def start(self):
|
|
"""Start all monitoring components"""
|
|
"""Start all monitoring components"""
|
|
@@ -48,9 +52,16 @@ class MonitoringCoordinator:
|
|
await self.position_tracker.start()
|
|
await self.position_tracker.start()
|
|
await self.pending_orders_manager.start()
|
|
await self.pending_orders_manager.start()
|
|
await self.risk_manager.start()
|
|
await self.risk_manager.start()
|
|
- await self.alarm_manager.start()
|
|
|
|
- await self.drawdown_monitor.start()
|
|
|
|
- await self.rsi_monitor.start()
|
|
|
|
|
|
+ # AlarmManager doesn't have start() method - it's always ready
|
|
|
|
+
|
|
|
|
+ # Lazy-load optional monitors to avoid circular imports
|
|
|
|
+ self._init_optional_monitors()
|
|
|
|
+
|
|
|
|
+ # Start optional monitors if they have async start methods
|
|
|
|
+ if hasattr(self.drawdown_monitor, 'start'):
|
|
|
|
+ await self.drawdown_monitor.start()
|
|
|
|
+ if hasattr(self.rsi_monitor, 'start'):
|
|
|
|
+ await self.rsi_monitor.start()
|
|
|
|
|
|
logger.info("All monitoring components started successfully")
|
|
logger.info("All monitoring components started successfully")
|
|
|
|
|
|
@@ -71,12 +82,39 @@ class MonitoringCoordinator:
|
|
await self.position_tracker.stop()
|
|
await self.position_tracker.stop()
|
|
await self.pending_orders_manager.stop()
|
|
await self.pending_orders_manager.stop()
|
|
await self.risk_manager.stop()
|
|
await self.risk_manager.stop()
|
|
- await self.alarm_manager.stop()
|
|
|
|
- await self.drawdown_monitor.stop()
|
|
|
|
- await self.rsi_monitor.stop()
|
|
|
|
|
|
+ # AlarmManager doesn't have stop() method - nothing to stop
|
|
|
|
+
|
|
|
|
+ # Stop optional monitors if they exist and have stop methods
|
|
|
|
+ if self.drawdown_monitor and hasattr(self.drawdown_monitor, 'stop'):
|
|
|
|
+ await self.drawdown_monitor.stop()
|
|
|
|
+ if self.rsi_monitor and hasattr(self.rsi_monitor, 'stop'):
|
|
|
|
+ await self.rsi_monitor.stop()
|
|
|
|
|
|
logger.info("Monitoring system stopped")
|
|
logger.info("Monitoring system stopped")
|
|
|
|
|
|
|
|
+ def _init_optional_monitors(self):
|
|
|
|
+ """Initialize optional monitors with lazy loading to avoid circular imports"""
|
|
|
|
+ try:
|
|
|
|
+ if self.drawdown_monitor is None:
|
|
|
|
+ # DrawdownMonitor needs a TradingStats instance
|
|
|
|
+ from ..stats.trading_stats import TradingStats
|
|
|
|
+ from .drawdown_monitor import DrawdownMonitor
|
|
|
|
+ stats = TradingStats()
|
|
|
|
+ self.drawdown_monitor = DrawdownMonitor(stats)
|
|
|
|
+
|
|
|
|
+ if self.rsi_monitor is None:
|
|
|
|
+ # RsiMonitor class from rsi_monitor module
|
|
|
|
+ from .rsi_monitor import RsiMonitor
|
|
|
|
+ self.rsi_monitor = RsiMonitor(self._hl_client, self._notification_manager)
|
|
|
|
+
|
|
|
|
+ except Exception as e:
|
|
|
|
+ logger.warning(f"Could not initialize optional monitors: {e}")
|
|
|
|
+ # Set to dummy objects that won't break the system
|
|
|
|
+ if self.drawdown_monitor is None:
|
|
|
|
+ self.drawdown_monitor = type('DummyMonitor', (), {'start': lambda: None, 'stop': lambda: None, 'is_running': False})()
|
|
|
|
+ if self.rsi_monitor is None:
|
|
|
|
+ self.rsi_monitor = type('DummyMonitor', (), {'start': lambda: None, 'stop': lambda: None, 'is_running': False})()
|
|
|
|
+
|
|
async def add_pending_stop_loss(self, symbol: str, stop_price: float, size: float, side: str, expires_hours: int = 24):
|
|
async def add_pending_stop_loss(self, symbol: str, stop_price: float, size: float, side: str, expires_hours: int = 24):
|
|
"""Add a pending stop loss order"""
|
|
"""Add a pending stop loss order"""
|
|
await self.pending_orders_manager.add_pending_stop_loss(symbol, stop_price, size, side, expires_hours)
|
|
await self.pending_orders_manager.add_pending_stop_loss(symbol, stop_price, size, side, expires_hours)
|