Phase 1: initial codes
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
from __future__ import annotations
|
||||
from PyQt6.QtCore import QThread, pyqtSignal
|
||||
from core.market_data import get_quote
|
||||
from utils.notifications import send_toast
|
||||
|
||||
|
||||
class AlertWorker(QThread):
|
||||
alert_triggered = pyqtSignal(str, str, str) # symbol, type, message
|
||||
check_complete = pyqtSignal()
|
||||
|
||||
def __init__(self, interval_seconds: int = 300):
|
||||
super().__init__()
|
||||
self._interval = interval_seconds
|
||||
self._running = False
|
||||
|
||||
def run(self):
|
||||
self._running = True
|
||||
while self._running:
|
||||
self._check_alerts()
|
||||
self.check_complete.emit()
|
||||
for _ in range(self._interval * 10):
|
||||
if not self._running:
|
||||
return
|
||||
self.msleep(100)
|
||||
|
||||
def stop(self):
|
||||
self._running = False
|
||||
|
||||
def _check_alerts(self):
|
||||
from db.database import get_session
|
||||
from db.models import Alert
|
||||
from datetime import datetime
|
||||
|
||||
with get_session() as session:
|
||||
active = session.query(Alert).filter_by(is_active=True).all()
|
||||
for alert in active:
|
||||
try:
|
||||
quote = get_quote(alert.symbol, force=True)
|
||||
price = quote.get("price", 0.0)
|
||||
volume = quote.get("volume", 0)
|
||||
triggered = False
|
||||
message = ""
|
||||
|
||||
if alert.alert_type == "price_above" and price >= alert.target_value:
|
||||
triggered = True
|
||||
message = f"{alert.symbol} hit ${price:.2f} (above ${alert.target_value:.2f})"
|
||||
elif alert.alert_type == "price_below" and price <= alert.target_value:
|
||||
triggered = True
|
||||
message = f"{alert.symbol} hit ${price:.2f} (below ${alert.target_value:.2f})"
|
||||
elif alert.alert_type == "volume_spike":
|
||||
avg_vol = quote.get("avg_volume") or (volume / 1.5)
|
||||
if avg_vol and volume >= avg_vol * alert.target_value:
|
||||
triggered = True
|
||||
message = f"{alert.symbol} volume spike: {volume:,} ({alert.target_value:.1f}x avg)"
|
||||
|
||||
if triggered:
|
||||
alert.is_active = False
|
||||
alert.triggered_at = datetime.utcnow()
|
||||
session.commit()
|
||||
send_toast("StockMind Alert", message)
|
||||
self.alert_triggered.emit(alert.symbol, alert.alert_type, message)
|
||||
except Exception:
|
||||
continue
|
||||
Reference in New Issue
Block a user