Improve key monitor form with bar period, box direction, and labeled fields.
Match order-monitor layout; persist bar_period and enforce upper-direction filter for box breakouts. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+49
-10
@@ -27,8 +27,38 @@ ZONE_TYPES = (TYPE_ZONE, "关键阻力位", "关键支撑位")
|
||||
ALERT_MAX_PUSH = 3
|
||||
ALERT_INTERVAL_SEC = 300
|
||||
SL_TICK_BUFFER = 2
|
||||
BAR_PERIOD = "5m"
|
||||
BAR_MINUTES = 5
|
||||
DEFAULT_BAR_PERIOD = "5m"
|
||||
|
||||
PERIOD_MINUTES_MAP = {
|
||||
"1m": 1, "2m": 2, "3m": 3, "5m": 5, "15m": 15, "30m": 30,
|
||||
"1h": 60, "2h": 120, "4h": 240, "d": 1440, "1d": 1440,
|
||||
}
|
||||
|
||||
|
||||
def key_monitor_periods() -> list[dict[str, str]]:
|
||||
"""关键位监控可选 K 线周期(触发用)。"""
|
||||
from kline_chart import MARKET_PERIODS
|
||||
|
||||
allowed = frozenset({"5m", "15m", "30m", "1h", "2h", "4h", "d"})
|
||||
return [p for p in MARKET_PERIODS if p["key"] in allowed]
|
||||
|
||||
|
||||
def normalize_bar_period(raw: str) -> str:
|
||||
valid = {p["key"] for p in key_monitor_periods()}
|
||||
k = (raw or DEFAULT_BAR_PERIOD).strip()
|
||||
return k if k in valid else DEFAULT_BAR_PERIOD
|
||||
|
||||
|
||||
def bar_period_label(key: str) -> str:
|
||||
k = normalize_bar_period(key)
|
||||
for p in key_monitor_periods():
|
||||
if p["key"] == k:
|
||||
return p["label"]
|
||||
return k
|
||||
|
||||
|
||||
def bar_period_minutes(period: str) -> int:
|
||||
return PERIOD_MINUTES_MAP.get(normalize_bar_period(period), 5)
|
||||
|
||||
|
||||
def normalize_monitor_type(raw: str) -> str:
|
||||
@@ -95,14 +125,19 @@ def _parse_bar_time(raw: str) -> Optional[datetime]:
|
||||
return None
|
||||
|
||||
|
||||
def last_closed_bar(bars: list[dict], now: Optional[datetime] = None) -> Optional[dict]:
|
||||
def last_closed_bar(
|
||||
bars: list[dict],
|
||||
period_minutes: int = 5,
|
||||
now: Optional[datetime] = None,
|
||||
) -> Optional[dict]:
|
||||
"""取最近一根已收盘 K 线。"""
|
||||
dnow = now or datetime.now(TZ)
|
||||
mins = max(1, int(period_minutes or 5))
|
||||
for bar in reversed(bars or []):
|
||||
dt = _parse_bar_time(str(bar.get("time") or ""))
|
||||
if not dt:
|
||||
continue
|
||||
bar_end = dt + timedelta(minutes=BAR_MINUTES)
|
||||
bar_end = dt + timedelta(minutes=mins)
|
||||
if dnow >= bar_end:
|
||||
return bar
|
||||
return None
|
||||
@@ -116,24 +151,26 @@ def detect_break_side(close: float, upper: float, lower: float) -> Optional[str]
|
||||
return None
|
||||
|
||||
|
||||
def fetch_closed_5m_bar(
|
||||
def fetch_closed_bar(
|
||||
sym: str,
|
||||
period: str,
|
||||
*,
|
||||
db_path: str,
|
||||
trading_mode: str,
|
||||
) -> Optional[dict]:
|
||||
p = normalize_bar_period(period)
|
||||
try:
|
||||
data = fetch_market_klines(
|
||||
sym,
|
||||
BAR_PERIOD,
|
||||
p,
|
||||
db_path=db_path,
|
||||
trading_mode=trading_mode,
|
||||
prefer_ctp=True,
|
||||
)
|
||||
bars = data.get("bars") or []
|
||||
return last_closed_bar(bars)
|
||||
return last_closed_bar(bars, bar_period_minutes(p))
|
||||
except Exception as exc:
|
||||
logger.debug("key monitor kline %s: %s", sym, exc)
|
||||
logger.debug("key monitor kline %s %s: %s", sym, p, exc)
|
||||
return None
|
||||
|
||||
|
||||
@@ -201,9 +238,10 @@ def format_auto_breakout_msg(
|
||||
break_label, _ = break_direction_label(break_side)
|
||||
dir_cn = "做多" if direction == "long" else "做空"
|
||||
rr = float(row.get("risk_reward") or 2)
|
||||
period_label = bar_period_label(row.get("bar_period") or DEFAULT_BAR_PERIOD)
|
||||
lines = [
|
||||
f"{'✅' if ok else '❌'} {name} {typ}自动单",
|
||||
f"⏱ 5m 收盘:{bar_time}",
|
||||
f"⏱ {period_label} 收盘:{bar_time}",
|
||||
f"🎯 {break_label} · {trade_mode} · {dir_cn}",
|
||||
f"💹 入场:{entry:g} 止损:{sl:g} 止盈:{tp:g}(盈亏比 {rr:g})",
|
||||
f"📦 手数:{lots}",
|
||||
@@ -333,7 +371,8 @@ def run_key_monitor_check(
|
||||
archive_monitor(conn, pid)
|
||||
continue
|
||||
|
||||
bar = fetch_closed_5m_bar(sym, db_path=db_path, trading_mode=mode)
|
||||
bar_period = normalize_bar_period(row.get("bar_period") or DEFAULT_BAR_PERIOD)
|
||||
bar = fetch_closed_bar(sym, bar_period, db_path=db_path, trading_mode=mode)
|
||||
if not bar:
|
||||
continue
|
||||
bar_time = str(bar.get("time") or "")[:19]
|
||||
|
||||
Reference in New Issue
Block a user