diff --git a/src/quant/engine.py b/src/quant/engine.py index 44655a5..9ce6e66 100644 --- a/src/quant/engine.py +++ b/src/quant/engine.py @@ -42,16 +42,38 @@ class QuantEngine: def universe(self, n=UNIVERSE_N): import akshare as ak + # 1) 新浪全市场快照 try: df = ak.stock_zh_a_spot() df['amt'] = pd.to_numeric(df.get('成交额'), errors='coerce') df['code'] = df.get('代码').astype(str).str[-6:] df = df[df['code'].str[:2].isin(('60', '00', '30', '68'))] df = df.sort_values('amt', ascending=False).head(n) - return list(df['code']), dict(zip(df['code'], df['名称'].astype(str))) + pairs = list(zip(df['code'], df['名称'].astype(str))) + if pairs: + return [c for c, _ in pairs], dict(pairs) except Exception as e: - print('[quant] 宇宙获取失败:', e, flush=True) - return [], {} + print('[quant] 新浪宇宙失败,改用东财:', e, flush=True) + # 2) 东财全市场快照兜底 + try: + df = ak.stock_zh_a_spot_em() + df['amt'] = pd.to_numeric(df.get('成交额'), errors='coerce') + df['code'] = df.get('代码').astype(str).str[-6:] + df = df[df['code'].str[:2].isin(('60', '00', '30', '68'))] + df = df.sort_values('amt', ascending=False).head(n) + pairs = list(zip(df['code'], df['名称'].astype(str))) + if pairs: + return [c for c, _ in pairs], dict(pairs) + except Exception as e: + print('[quant] 东财宇宙失败:', e, flush=True) + # 3) 兜底:资金流表中的活跃股 + conn = self.fetcher._conn() + try: + rows = conn.execute("SELECT DISTINCT ts_code FROM money_flow LIMIT ?", + (n,)).fetchall() + return [r[0] for r in rows], {} + finally: + pass def _kline_worker(self): """后台轮询:持续刷新宇宙内 K 线(day 全量 + 30/5 分钟)"""