diff --git a/deploy/profile-scripts/resonance.py b/deploy/profile-scripts/resonance.py index 6106ddbb..b134df8d 100644 --- a/deploy/profile-scripts/resonance.py +++ b/deploy/profile-scripts/resonance.py @@ -51,6 +51,42 @@ def _flow_state(code): 'flow_delta': round(flow_delta, 2) if flow_delta is not None else None} +# ── 行业新闻情绪分析(2026-07-31:东方财富翻页新闻→500条/股)── +_POS_KW = ['大涨','涨停','回暖','反弹','回升','领涨','突破','创新高','资金流入','净流入','加仓','密集调研','增持','回购'] +_NEG_KW = ['大跌','跌停','回落','下跌','下挫','走弱','资金流出','净流出','减持','利空','风险','预警','亏损','预警'] + +def sector_news_sentiment(sector, days=3): + import sqlite3 + conn = sqlite3.connect('/home/hmo/MoFin/data/mofin.db') + try: + stocks = conn.execute("SELECT code FROM stock_sectors_em WHERE sector=?", (sector,)).fetchall() + if not stocks: + return {'state': 'neutral', 'pos': 0, 'neg': 0, 'total': 0} + from datetime import datetime, timedelta + since = (datetime.now() - timedelta(days=days)).strftime('%Y-%m-%d') + codes = tuple(s[0] for s in stocks) + placeholders = ','.join('?' for _ in codes) + arts = conn.execute(f"SELECT title, content FROM stock_news WHERE code IN ({placeholders}) AND date>=?", codes + (since,)).fetchall() + pos = neg = 0 + for t, c in arts: + text = (t or '') + ' ' + (c or '') + for kw in _POS_KW: + if kw in text: pos += 1; break + for kw in _NEG_KW: + if kw in text: neg += 1; break + total = pos + neg + state = 'neutral' + if total > 0 and pos / max(total, 1) > 0.6: + state = 'positive' + elif total > 0 and neg / max(total, 1) > 0.6: + state = 'negative' + return {'state': state, 'pos': pos, 'neg': neg, 'total': total} + except Exception: + return {'state': 'neutral', 'pos': 0, 'neg': 0, 'total': 0} + finally: + conn.close() + + def _news_state(code, name=None, sector=None): """消息维度: 3日内该股/该板块最新消息情绪""" since = (datetime.now() - timedelta(days=3)).strftime('%Y-%m-%d') @@ -109,7 +145,15 @@ def evaluate_resonance(code, gate, name=None): decision = 'pass' reason = '' - return {'decision': decision, 'reason': reason, 'flow': flow, 'news': news, 'sector': sector} + # ── 第四维:行业新闻情绪叠加(2026-07-31) ── + sns = sector_news_sentiment(sector) if sector else {'state': 'neutral', 'pos': 0, 'neg': 0, 'total': 0} + if decision == 'pass' and sns['state'] == 'positive' and fs in ('positive', 'strong_positive'): + decision = 'resonance' + reason = f"行业新闻确认({sns['pos']}pos/{sns['neg']}neg) + 资金流入 → 共振" + elif decision == 'pass' and sns['state'] == 'negative' and fs == 'negative': + decision = 'downgrade' + reason = f"行业新闻利空({sns['pos']}pos/{sns['neg']}neg) + 资金流出 → 降级" + return {'decision': decision, 'reason': reason, 'flow': flow, 'news': news, 'sector': sector, 'sector_news': sns} def log_resonance(code, name, price, gate, res, signal_before, signal_after):