feat: 新增行业领涨股扫描 xiaoguo_scanner
- 新增 fetch_sector_leaders() 从 market.json 读取热门行业领涨股 - 三路并行:同花顺技术榜 + 行业领涨 + 东财热榜(502降级) - 优先级排序:行业领涨 > 同花顺榜 > 东财热榜 - 名称→代码映射使用本地缓存,避免频繁调用akshare - 更新文档
This commit is contained in:
+56
-3
@@ -45,6 +45,10 @@ BEARISH_BOARDS = [
|
||||
ALL_BOARDS = BULLISH_BOARDS + BEARISH_BOARDS
|
||||
BULLISH_COUNT = len(BULLISH_BOARDS)
|
||||
|
||||
# 行业领涨股扫描(不轮换,每轮都跑)
|
||||
# 从 market.json 读热门行业领涨股
|
||||
SECTOR_HOT_THRESHOLD = 2.5 # 板块涨幅>2.5%时捞它的领涨股
|
||||
|
||||
|
||||
def clean_proxy():
|
||||
for k in ['http_proxy','https_proxy','HTTP_PROXY','HTTPS_PROXY']:
|
||||
@@ -112,6 +116,53 @@ def fetch_rotating_board():
|
||||
return [], is_bullish
|
||||
|
||||
|
||||
def fetch_sector_leaders():
|
||||
"""从 market.json 读热门行业领涨股"""
|
||||
mkt_path = DATA_DIR / "market.json"
|
||||
if not mkt_path.exists():
|
||||
return []
|
||||
try:
|
||||
mkt = json.loads(mkt_path.read_text())
|
||||
sectors = mkt.get("sectors", [])
|
||||
|
||||
# 代码→名称映射(优先用本地缓存,避免每次跑都调akshare)
|
||||
cache_path = DATA_DIR / "stock_name_code_cache.json"
|
||||
name_to_code = {}
|
||||
if cache_path.exists():
|
||||
name_to_code = json.loads(cache_path.read_text())
|
||||
if not name_to_code:
|
||||
try:
|
||||
import akshare as ak
|
||||
df = ak.stock_info_a_code_name()
|
||||
for _, r in df.iterrows():
|
||||
name_to_code[r["简称"]] = r["代码"]
|
||||
cache_path.write_text(json.dumps(name_to_code, ensure_ascii=False))
|
||||
print(f" 名称代码映射: {len(name_to_code)}只已缓存", flush=True)
|
||||
except Exception as e:
|
||||
print(f" 名称代码映射加载失败: {e}", flush=True)
|
||||
|
||||
leaders = []
|
||||
seen = set()
|
||||
for s in sectors:
|
||||
chg = s.get("change", 0) or 0
|
||||
lead_name = s.get("lead_stock", "")
|
||||
if chg < SECTOR_HOT_THRESHOLD or not lead_name or lead_name in seen:
|
||||
continue
|
||||
seen.add(lead_name)
|
||||
code = name_to_code.get(lead_name, "")
|
||||
if not code:
|
||||
continue
|
||||
leaders.append({
|
||||
"code": code,
|
||||
"name": lead_name,
|
||||
"source": f"行业领涨-{s['name']}+{chg:+.1f}%",
|
||||
})
|
||||
return leaders
|
||||
except Exception as e:
|
||||
print(f" 行业领涨获取失败: {e}", flush=True)
|
||||
return []
|
||||
|
||||
|
||||
def get_scanned_codes(conn):
|
||||
"""取1小时内已扫描过的代码"""
|
||||
rows = conn.execute(
|
||||
@@ -192,10 +243,11 @@ def main():
|
||||
# 1. 拉板
|
||||
hot = fetch_hot_board()
|
||||
rotating, is_bullish = fetch_rotating_board()
|
||||
leaders = fetch_sector_leaders()
|
||||
elapsed = time.time() - start_time
|
||||
print(f"榜单: 东方财富{len(hot)}只, 同花顺{len(rotating)}只 ({elapsed:.0f}s)", flush=True)
|
||||
print(f"榜单: 东方财富{len(hot)}只, 同花顺{len(rotating)}只, 行业领涨{len(leaders)}只 ({elapsed:.0f}s)", flush=True)
|
||||
|
||||
if not hot and not rotating:
|
||||
if not hot and not rotating and not leaders:
|
||||
conn.close()
|
||||
return
|
||||
|
||||
@@ -210,7 +262,8 @@ def main():
|
||||
|
||||
# 2. 合并去重 + 看空榜只保留持仓股
|
||||
all_stocks = {}
|
||||
for s in hot + rotating:
|
||||
# 行业领涨优先(热门板块龙头)
|
||||
for s in (leaders if is_bullish else []) + hot + rotating:
|
||||
code = s["code"]
|
||||
code_stripped = code.lstrip("0")
|
||||
if not is_bullish:
|
||||
|
||||
Reference in New Issue
Block a user