fix: xiaoguo_scanner 榜单更新+看空榜持仓预警

- 修bug:stock_rank_cxd_ths 实为'创新低',改为 stock_rank_lxsz_ths '连续上涨'
- 新增6个看多榜(险资举牌)+ 5个看空榜(创新低/持续缩量/量价齐跌/连续下跌/向下突破)
- 看空榜自动比对持仓,命中写入 xiaoguo_risk 信号
- 东财热榜静默降级(502不可修)
- 看空榜不跳过已扫描,每轮全检
This commit is contained in:
知微
2026-06-22 19:13:55 +08:00
parent 774c2e885d
commit ce687a4216
13 changed files with 8331 additions and 33663 deletions
+49 -4
View File
@@ -117,6 +117,42 @@ def get_market_mood(sectors):
return "bullish" if ratio > 0.7 else "neutral" if ratio > 0.4 else "bearish"
def get_market_verdict(up_ratio, mood, sectors):
"""Return (verdict, reason) based on sector data."""
if not sectors:
return "unknown", "数据不足"
if up_ratio < 25:
return "弱势", f"{up_ratio}%板块上涨,{mood}"
elif up_ratio < 40:
return "偏弱", f"{up_ratio}%板块上涨,结构分化"
elif up_ratio < 60:
return "均衡", f"{up_ratio}%板块上涨,涨跌均衡"
else:
return "强势", f"{up_ratio}%板块上涨,整体走强"
def get_hot_sectors(sectors, top_n=3):
"""Return sectors with highest positive change as hot sectors."""
hot = [s for s in sectors if s.get("change", 0) > 1.0]
hot.sort(key=lambda s: s.get("change", 0), reverse=True)
return [{
"name": s["name"],
"change": s.get("change", 0),
"reason": f"板块涨{s.get('change',0):.1f}%"
} for s in hot[:top_n]]
def get_danger_sectors(sectors, top_n=3):
"""Return sectors with lowest (negative) change as danger sectors."""
danger = [s for s in sectors if s.get("change", 0) < -1.0]
danger.sort(key=lambda s: s.get("change", 0))
return [{
"name": s["name"],
"change": s.get("change", 0),
"reason": f"板块跌{s.get('change',0):.1f}%"
} for s in danger[:top_n]]
# ── 主流程 ──
def main():
@@ -142,15 +178,24 @@ def main():
top_gainers = [s for s in sorted_sectors if s.get("change", 0) > 0][:5]
top_losers = [s for s in reversed(sorted_sectors) if s.get("change", 0) < 0][:3]
# 计算大盘数据
up_ratio = round(
sum(1 for s in sectors if s.get("change", 0) > 0) / max(len(sectors), 1) * 100, 1
)
mood = get_market_mood(sectors)
verdict, verdict_reason = get_market_verdict(up_ratio, mood, sectors)
market_data = {
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M"),
"source": source,
"concept_source": concept_source,
"total_sectors": len(sectors),
"up_ratio": round(
sum(1 for s in sectors if s.get("change", 0) > 0) / max(len(sectors), 1) * 100, 1
),
"mood": get_market_mood(sectors),
"up_ratio": up_ratio,
"mood": mood,
"market_verdict": verdict,
"verdict_reason": verdict_reason,
"hot_sectors": get_hot_sectors(sectors),
"danger_sectors": get_danger_sectors(sectors),
"top_gainers": top_gainers,
"top_losers": top_losers,
"sectors": sectors,