Sentinel_V2 / monitor.py
Asish Karthikeya Gogineni
Deploy Sentinel AI 2026-02-26_17:09:25
5d2eba0
# monitor.py
import time
import json
import os
import sys
import logging
from datetime import datetime
from agents.tool_calling_agents import MarketDataAgent, WebResearchAgent
# --- Configuration ---
WATCHLIST_FILE = "watchlist.json"
ALERTS_FILE = "alerts.json"
CHECK_INTERVAL = 300 # 5 minutes (preserves API quota; free tier = 25 requests/day)
PRICE_ALERT_THRESHOLD = 0.5 # More sensitive alerts
# --- Logging Setup ---
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler(sys.stdout)
]
)
logger = logging.getLogger("Aegis_Monitor")
# --- Initialize Agents ---
market_agent = MarketDataAgent()
web_agent = WebResearchAgent()
def load_watchlist():
if not os.path.exists(WATCHLIST_FILE):
return []
try:
with open(WATCHLIST_FILE, 'r') as f:
return json.load(f)
except Exception as e:
logger.error(f"Error loading watchlist: {e}")
return []
def save_alert(alert):
alerts = []
if os.path.exists(ALERTS_FILE):
try:
with open(ALERTS_FILE, 'r') as f:
alerts = json.load(f)
except:
pass
# Prepend new alert
alerts.insert(0, alert)
# Keep only last 100 alerts (increased from 50)
alerts = alerts[:100]
with open(ALERTS_FILE, 'w') as f:
json.dump(alerts, f, indent=2)
def check_market_data(symbol):
try:
logger.info(f"Checking market data for {symbol}...")
# Use GLOBAL_QUOTE (free tier) instead of INTRADAY (premium)
result = market_agent.get_global_quote(symbol=symbol)
if result.get("status") != "success":
logger.warning(f"Failed to get market data for {symbol}")
return None
data = result.get("data", {})
if not data or data.get("price") == "0":
return None
price = float(data.get("price", 0))
change_str = data.get("change_percent", "0%").replace("%", "")
pct_change = float(change_str) if change_str else 0
return {
"price": price,
"change": pct_change,
"timestamp": datetime.now().isoformat(),
"source": result.get("source", "Alpha Vantage")
}
except Exception as e:
logger.error(f"Error checking market data for {symbol}: {e}")
return None
except Exception as e:
logger.error(f"Error checking market data for {symbol}: {e}")
return None
def check_news(symbol):
try:
logger.info(f"Checking news for {symbol}...")
query = f"breaking news {symbol} stock today"
result = web_agent.research(queries=[query], search_depth="basic")
if result.get("status") != "success":
return None
# Just return the first result title for now as a "headline"
data = result.get("data", [])
if data and data[0].get("results"):
first_hit = data[0]["results"][0]
return {
"title": first_hit.get("title"),
"url": first_hit.get("url"),
"content": first_hit.get("content")[:200] + "..."
}
return None
except Exception as e:
logger.error(f"Error checking news for {symbol}: {e}")
return None
def run_monitor_loop():
logger.info("--- 🛡️ Aegis Proactive Monitor Started ---")
logger.info(f"Monitoring watchlist every {CHECK_INTERVAL} seconds ({CHECK_INTERVAL/60:.0f} minutes).")
logger.info(f"Price alert threshold: {PRICE_ALERT_THRESHOLD}%")
while True:
watchlist = load_watchlist()
if not watchlist:
logger.info("Watchlist is empty. Waiting...")
for symbol in watchlist:
try:
# 1. Market Check
market_info = check_market_data(symbol)
if market_info:
# Alert Logic: Price moved more than threshold
if abs(market_info['change']) > PRICE_ALERT_THRESHOLD:
direction = "📈 UP" if market_info['change'] > 0 else "📉 DOWN"
alert_msg = f"{direction} ALERT: {symbol} moved {market_info['change']:+.2f}% to ${market_info['price']:.2f}"
logger.info(alert_msg)
save_alert({
"timestamp": datetime.now().isoformat(),
"type": "MARKET",
"symbol": symbol,
"message": alert_msg,
"details": market_info
})
# 2. News Check (Simplified: Just log latest headline)
news_info = check_news(symbol)
if news_info:
# Check if this is "significant" news based on keywords
keywords = [
"acquisition", "merger", "earnings", "crash", "surge", "plunge",
"fda", "lawsuit", "sec", "filing", "8-k", "10-k", "insider",
"partnership", "deal", "bankruptcy", "recall", "investigation",
"upgrade", "downgrade", "target", "buyback", "dividend"
]
if any(k in news_info['title'].lower() for k in keywords):
alert_msg = f"📰 NEWS ALERT: {symbol} - {news_info['title']}"
logger.info(alert_msg)
save_alert({
"timestamp": datetime.now().isoformat(),
"type": "NEWS",
"symbol": symbol,
"message": alert_msg,
"details": news_info
})
except Exception as e:
logger.error(f"Error processing {symbol}: {e}")
logger.info(f"Cycle complete. Sleeping for {CHECK_INTERVAL}s...")
time.sleep(CHECK_INTERVAL)
if __name__ == "__main__":
# Ensure we can import agents
sys.path.append(os.path.abspath(os.path.dirname(__file__)))
run_monitor_loop()