65 lines
2.7 KiB
Python
65 lines
2.7 KiB
Python
# sanguo_factor/sentiment_lexicon.py
|
|
"""情绪词表 v1(子串匹配零分词依赖,可解释可审计).
|
|
|
|
来源: 七项目指标调研(2026-09-22)——FinRobot catalyst_analyzer 英文词表
|
|
(正 20/负 18)+分析师短语优先范式的中文化移植;阈值/口径属因子域场景语义
|
|
(09-19 归属原则),策略域未来要消费再按 dsa 先例移交.
|
|
|
|
打分纪律(与 FinRobot 同构):
|
|
- 分析师短语优先: 命中即定方向(短语比通用词信号强一个量级);
|
|
- 否则正/负词命中**计数**多者胜,平局=0(单条新闻粒度);
|
|
- 纯计数无权重——v1 接受噪声换可解释性,IC 见真章后再升级模型
|
|
(升级路径: FinBERT/LLM,但数字纪律=词表或 LLM 均只产方向,数值另算).
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
# 分析师/机构行动短语(优先级最高,命中即定方向)
|
|
ANALYST_PATTERNS: dict[str, list[str]] = {
|
|
"pos": [
|
|
"上调评级", "上调至", "评级上调", "目标价上调", "上调目标价",
|
|
"调高目标价", "首次覆盖", "予以买入", "维持买入", "维持增持",
|
|
"看多", "强烈推荐",
|
|
],
|
|
"neg": [
|
|
"下调评级", "下调至", "评级下调", "目标价下调", "下调目标价",
|
|
"调低目标价", "维持卖出", "下调至持有", "维持减持", "看空",
|
|
"不再覆盖", "剔除出",
|
|
],
|
|
}
|
|
|
|
# 通用正面词(计数制)
|
|
POS_WORDS: tuple[str, ...] = (
|
|
"超预期", "高于预期", "好于预期", "净利增长", "净利润增长", "业绩预增",
|
|
"业绩增长", "营收增长", "中标", "签订合同", "签署合同", "订单",
|
|
"回购", "增持", "分红", "创新高", "涨停", "涨价", "供不应求",
|
|
"突破", "获批", "战略合作", "产能扩张", "扭亏", "盈利",
|
|
)
|
|
|
|
# 通用负面词(计数制)
|
|
NEG_WORDS: tuple[str, ...] = (
|
|
"低于预期", "差于预期", "不及预期", "亏损", "预亏", "首亏", "业绩预减",
|
|
"业绩下滑", "营收下滑", "负增长", "处罚", "立案", "调查", "违规",
|
|
"减持", "质押爆仓", "平仓", "诉讼", "仲裁", "商誉减值", "减值",
|
|
"退市", "警示", "违约", "债务逾期", "停产", "安全事故", "降价",
|
|
"需求疲软", "下修",
|
|
)
|
|
|
|
|
|
def score_text(text: str) -> int:
|
|
"""单条文本情绪分: +1/0/−1(短语优先,否则计数多数决,平局 0)."""
|
|
if not text:
|
|
return 0
|
|
for p in ANALYST_PATTERNS["pos"]:
|
|
if p in text:
|
|
return 1
|
|
for p in ANALYST_PATTERNS["neg"]:
|
|
if p in text:
|
|
return -1
|
|
pos = sum(text.count(w) for w in POS_WORDS)
|
|
neg = sum(text.count(w) for w in NEG_WORDS)
|
|
if pos > neg:
|
|
return 1
|
|
if neg > pos:
|
|
return -1
|
|
return 0
|