Files
stock_cursor_v0/backend/alerts.py
2026-06-14 11:54:45 +08:00

68 lines
2.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""预警引擎:拉取实时价格,评估规则,触发即生成站内事件。"""
from __future__ import annotations
import datetime as dt
from sqlalchemy import select
import akshare_service as svc
import notifier
from db import get_session
from models import AlertRule, AlertEvent
KIND_LABEL = {
"price_above": "价格突破",
"price_below": "价格跌破",
"pct_above": "涨幅达到",
"pct_below": "跌幅达到",
}
def _hit(kind, threshold, q):
price, pct = q["price"], q["pct"]
if kind == "price_above":
return price >= threshold, price
if kind == "price_below":
return price <= threshold, price
if kind == "pct_above":
return pct >= threshold, pct
if kind == "pct_below":
return pct <= -abs(threshold), pct
return False, price
def check_alerts():
with get_session() as s:
rules = s.execute(select(AlertRule).where(AlertRule.status == "active")).scalars().all()
if not rules:
return {"checked": 0, "triggered": 0}
codes = list({r.code for r in rules})
quotes = svc.realtime_quotes(codes)
triggered = 0
push_msgs = []
for r in rules:
q = quotes.get(r.code)
if not q:
continue
hit, val = _hit(r.kind, r.threshold, q)
r.last_value = q["price"]
if hit:
unit = "" if r.kind.startswith("price") else "%"
msg = (f"{q['name']} {KIND_LABEL.get(r.kind, r.kind)} {r.threshold}{unit}"
f"(现价 {q['price']}{q['pct']:+.2f}%")
s.add(AlertEvent(rule_id=r.id, code=r.code, name=q["name"], message=msg, value=val))
r.status = "triggered"
r.triggered_at = dt.datetime.now()
triggered += 1
push_msgs.append(msg)
s.commit()
# 触发后向已配置渠道推送(站外)
if push_msgs and notifier.any_enabled():
try:
notifier.notify("【Blackdata预警】" + (push_msgs[0] if len(push_msgs) == 1 else f"{len(push_msgs)} 条预警触发"),
"\n".join(push_msgs))
except Exception:
pass
return {"checked": len(rules), "triggered": triggered}