feat(ai_news): show stock name (ticker) in telegram top 5/5

This commit is contained in:
2026-05-14 00:36:10 +09:00
parent c3659eb6c5
commit 06162b1e6e
3 changed files with 20 additions and 4 deletions

View File

@@ -21,10 +21,13 @@ def _row_line(idx: int, r: Dict[str, Any]) -> str:
score = r["score_raw"]
# score 문자열 자체를 _escape 통과 — '+', '-', '.' 모두 MarkdownV2 reserved
score_str = _escape(f"{score:+.1f}")
return (
f"{idx}\\. {_escape(r['ticker'])} \\({score_str}\\) — "
f"{_escape(r['reason'])}"
name = r.get("name") or ""
ticker = r["ticker"]
label = (
f"{_escape(name)} \\({_escape(ticker)}\\)"
if name else _escape(ticker)
)
return f"{idx}\\. {label} \\({score_str}\\) — {_escape(r['reason'])}"
def build_message(

View File

@@ -291,6 +291,18 @@ async def post_refresh_news_sentiment(asof: Optional[str] = None):
return {"asof": asof_date.isoformat(), "status": "skipped_holiday"}
with _conn() as c:
summary = await _ai_pipeline.refresh_daily(c, asof_date)
# top_pos/top_neg 항목에 종목명 주입 (텔레그램 가독성)
tickers = {r["ticker"] for r in summary["top_pos"] + summary["top_neg"]}
if tickers:
placeholders = ",".join("?" * len(tickers))
name_map = {
row[0]: row[1] for row in c.execute(
f"SELECT ticker, name FROM krx_master WHERE ticker IN ({placeholders})",
list(tickers),
).fetchall()
}
for r in summary["top_pos"] + summary["top_neg"]:
r["name"] = name_map.get(r["ticker"], "")
summary["telegram_text"] = _ai_telegram.build_message(
asof=summary["asof"],
top_pos=summary["top_pos"], top_neg=summary["top_neg"],

View File

@@ -18,7 +18,8 @@ def test_build_message_includes_top_sections():
assert "호재 Top" in msg
assert "악재 Top" in msg
assert "005930" in msg
assert "8.5" in msg
# score는 MarkdownV2 escape 거쳐 "8\.5" 형태 ('.' 가 reserved)
assert "8\\.5" in msg
assert "HBM" in msg
assert "373220" in msg