龙虎榜席位多空因子 (alpha_yyb_seat_duokong_data)

数据描述: 字段类型按 **平台(BigQuant AIStudio / DAI)口径** 给出;本地 CSV 落盘时 `date` 与文本列为 `object`(ISO 字符串 / UTF-8 文本),整数列为 `int64`,浮点列为 `float64`,与下表一一对应。- 上传到平台的因子表:`yyb_seat_duokong_factor.csv`(本文件「1. 因子表」) - 因子值的本地来源:`yyb_rise_prob_return.csv` → `yyb_duokong_stats_YYYY-MM-DD.csv` → `yyb_seat_duokong_factor.csv` - 平台侧 `factor_sql` 的输入:数据源 `cn_stock_top_inst_te_raw`(本文件「5.」) ---

文档
数据简介

# 龙虎榜席位多空因子 · 文档 - 因子 ID:`alpha_yyb_seat_duokong` - 因子名称:龙虎榜席位多空因子 - 因子类型:资金流席位因子 - 数据源(平台侧):`cn_stock_top_inst_te_raw`(龙虎榜机构明细) - 本地落盘:`yyb_seat_duokong_factor.csv` / `yyb_seat_duokong_factor_analysis.json` / `yyb_seat_duokong_factor_analysis.html` - 定时更新:每天 **20:40**(计划任务 `EastMoneyYYBPH_DailyUpdate`) - 提交方式:AIStudio(`factors.submit_factor`) --- ## 1. 因子定位 龙虎榜每日披露每只上榜股票的**买入前 5 / 卖出前 5 营业部(席位)**。同一只股票今天上榜, 是「哪一路资金在做」的直接证据,但席位名本身不可比较——有的营业部历史上上榜后大概率上涨 (偏多席位,如活跃游资席位),有的则相反(偏空席位,如高频兑现席位)。 本因子把「**资金方向(谁在买、谁在卖)**」与「**席位历史画像(这个席位偏多还是偏空)**」 相乘,得到一个横截面上可排序的分数: * 因子值 **> 0**:当日买盘由偏多席位主导(或卖盘由偏空席位主导),看多; * 因子值 **< 0**:当日买盘由偏空席位主导(或卖盘由偏多席位主导),看空; * 值域约 **[−50, +50]**,`0` 为中性。 --- ## 2. 数据来源与计算链路 ``` 东方财富 数据中心 API(data.eastmoney.com,公开接口,无需登录) ├── RPT_RATEDEPT_RETURNT_RANKING 营业部排行(近一年,CYCLE_CODE="04") │ └─▶ yyb_rise_prob_return.csv ├── RPT_BILLBOARD_DAILYDETAILSBUY/SELL 龙虎榜买入/卖出前 5 席位明细 └── RPT_DAILYBILLBOARD_DETAILSNEW 龙虎榜明细(含前向收益、最新交易日) yyb_rise_prob_return.csv └─ yyb_duokong.py ─▶ yyb_duokong_stats_YYYY-MM-DD.csv(席位画像:综合多空分 0~100) 席位明细 × 席位画像 └─ eastmoney_yybph.py: build_factor_panel() ─▶ yyb_seat_duokong_factor.csv └─ analyze_factor() ─▶ 分析 JSON / HTML └─ submit_factor() ─▶ AIStudio 因子库 ``` **为什么需要席位名归一**:两个数据源对同一营业部的写法不同 (席位明细写「国泰海通证券股份有限公司武汉紫阳东路证券营业部」,排行表写 「国泰海通证券武汉紫阳东路证券营业部」)。`norm_seat()` 只做「剥离公司后缀」 「统一『证券营业部』写法」两项确定性替换,不做模糊猜测,因此匹配不上就是真的对不上。 `机构专用 / 深股通专用 / 沪股通专用 / 其他席位` 属交易所汇总席位,单独剔除、不计入匹配失败。 --- ## 3. 因子定义 ### 3.1 本地口径(`build_factor_panel`) 对每个交易日 T、每只上榜股票 i: ``` factor(T, i) = Σ_s s · amt(s) · (score(s) − 50) / Σ_s amt(s) ``` * `s` —— 该股 T 日的买卖前 5 席位(每侧只取金额最大的前 5 个); * `s = +1` 若席位出现在**买入**前 5;`s = −1` 若出现在**卖出**前 5; * `amt(s)` —— 买入方向取买入额,卖出方向取卖出额(单位元); * `score(s)` —— 该席位近一年的**综合多空分**(0~100,50 为中性),由 `yyb_duokong.py` 用东财「营业部排行」的近一年上涨概率横截面反解得到; * 画像匹配不上的席位(含交易所汇总席位)**整条剔除**,不参与分子分母。 ### 3.2 平台口径(`FACTOR_SQL`) 平台没有「营业部排行」这张表,因此席位画像改为**在同一数据源内自洽推导**: 取该席位最近 242 个上榜日(**不含当日,杜绝前视**)的净买占比 ``` net_ratio = (Σ买入额 − Σ卖出额) / (Σ买入额 + Σ卖出额) ∈ [−1, +1] ``` 并令 `画像分 − 50 = 50 · net_ratio`,与本地 `综合多空分 − 50 ∈ [−50, +50]` **同量纲、同方向**。 其余口径(`sign`、`amt`、加权公式)与本地完全一致。席位首次上榜时 `net_ratio` 为 `NULL`, 该席位当日不参与加权,语义等价于本地的「画像匹配不上则剔除」。 ```sql WITH seat_day AS ( -- 席位 × 日 汇总(同一席位的买、卖金额合并到一行) SELECT date, exalter, SUM(COALESCE(buy, 0)) AS buy_amt, SUM(COALESCE(sell, 0)) AS sell_amt FROM cn_stock_top_inst_te_raw GROUP BY date, exalter ), seat_profile AS ( -- 席位画像:最近 242 个上榜日的净买占比(不含当日) SELECT date, exalter, (SUM(buy_amt) OVER w - SUM(sell_amt) OVER w) / NULLIF(SUM(buy_amt) OVER w + SUM(sell_amt) OVER w, 0) AS net_ratio FROM seat_day WINDOW w AS (PARTITION BY exalter ORDER BY date ROWS BETWEEN 242 PRECEDING AND 1 PRECEDING) ), seat_signed AS ( -- 逐条席位明细 → 带方向的金额 SELECT date, instrument, exalter, CASE WHEN side = '0' THEN 1 ELSE -1 END AS sgn, CASE WHEN side = '0' THEN COALESCE(buy, 0) ELSE COALESCE(sell, 0) END AS amt FROM cn_stock_top_inst_te_raw ) SELECT s.date AS date, s.instrument AS instrument, SUM(s.sgn * s.amt * 50.0 * p.net_ratio) / NULLIF(SUM(s.amt), 0) AS factor FROM seat_signed s JOIN seat_profile p ON p.date = s.date AND p.exalter = s.exalter WHERE p.net_ratio IS NOT NULL GROUP BY s.date, s.instrument HAVING SUM(s.amt) > 0 ``` * `side`:`'0'` = 买入前 5,`'1'` = 卖出前 5(字符串); * `242` 与 `PERIODS_PER_YEAR` 对齐(近一年交易日数); * 窗口为 `ROWS BETWEEN 242 PRECEDING AND 1 PRECEDING`,**当日不进窗口**,因此 T 日盘后即可算出 因子值,不存在前视。 ### 3.3 两版口径的差异(唯一一处) | 环节 | 本地版 | 平台版 | | --- | --- | --- | | 席位画像来源 | 东财「营业部排行」近一年上涨概率反解(`综合多空分`,0~100) | 同一数据源内自洽推导 `net_ratio`,令 `画像分−50 = 50·net_ratio` | | 画像窗口 | 近一年(东财给定,含全部上榜记录) | 最近 242 个**上榜日**,不含当日 | | 匹配不上的席位 | 剔除 | `net_ratio IS NULL` → 剔除 | | 方向符号 / 金额口径 / 加权公式 | `+1` 买、`−1` 卖;买取买入额、卖取卖出额;`Σ s·amt·(score−50)/Σ amt` | **完全一致** | --- ## 4. 因子分析口径(对齐 AlphaMiner) `analyze_factor()` 复现参考文档 `因子提交因子分析.txt` 的 AlphaMiner 绩效口径, 使本地算出的指标可直接填进 `submit_factor` 的 `performance_index`。 | 项目 | 口径 | | --- | --- | | 前向收益 | 龙虎榜明细自带的 `D1_CLOSE_ADJCHRATE`(T 日收盘 → T+1 日收盘,单位 %)。T 日盘后因子即得,已含前视对齐,**不再做 `shift(1)`** | | 分层 | 按日横截面等分位,`group_num` 组(默认 10) | | 多头 / 空头 | 多头 = 因子值**最大**组,空头 = 因子值**最小**组,`long_short = long − short` | | IC | 逐日 Spearman 秩相关;`IC` = 均值,`IR` = 均值 / 标准差,另给 `|IC|>0.02` 占比与近 3/10/21/63/126/252 日 IC 均值 | | 收益类指标 | `return_ratio`(区间累计)、`annual_return_ratio`(年化)、`ex_return_ratio` / `ex_annual_return_ratio`(超额,基准 = 样本内等权)、`sharp_ratio`、`return_volatility`、`information_ratio`、`max_drawdown`、`win_percent` | | 年化 | `PERIODS_PER_YEAR = 242`,无风险利率 `RISK_FREE = 0.035 / 242`(日频) | | 区间收益 | `RET_WINDOWS = (3, 10, 21, 63, 126, 252)`,样本不足则为 `null` | | 换手率 | `1 − |前一日持仓 ∩ 当日持仓| / |当日持仓|`,逐日取均值 | | 股票池 / 基准 | 本地:龙虎榜上榜个股 / 样本内等权;AIStudio:`params['instruments']` / `params['benchmark']` | 提交时 `perf_dict` 的构造(见 `submit_factor()`): ```python perf_dict = {"factor_direction": params["factor_direction"], "IC": np.nanmean(alpha_instance.ic["g_ic"])} for portfolio, row in result["whole"].iterrows(): for column, value in row.items(): perf_dict[f"{portfolio}_{column}"] = value # long_return_ratio / short_ic / ... perf_dict.update(params) # inf / nan → None,避免 JSON 序列化报错 ``` --- ## 5. 参数(`params`) | 参数 | 取值 | 说明 | | --- | --- | --- | | `group_num` | `10` | 分层组数(`--group-num`) | | `factor_field` | `"factor"` | 因子列名(固定,与因子表列名一致) | | `instruments` | `"全市场"` | 股票池,可选 沪深300 / 中证500 / 中证1000 / 全市场(`--instruments`) | | `factor_direction` | `1` | 因子方向,`1` = 因子值越大越看多(`-1` 反之) | | `benchmark` | `"中证500"` | 基准(`--benchmark`) | | `data_process` | `True` | 是否做因子预处理(去极值 / 标准化) | --- ## 6. 产物清单 | 文件 | 说明 | | --- | --- | | `yyb_seat_duokong_factor.csv` | **因子表**(date / instrument / factor),按 (date, instrument) 增量去重 | | `yyb_seat_duokong_factor_analysis.json` | 分析结果(窗口、params、coverage、ic_summary、whole_perf、yearly_perf、extreme) | | `yyb_seat_duokong_factor_analysis.html` | 自包含分析报告(净值曲线 + 整体/年度绩效 + IC + 因子值极值个股) | | `yyb_rise_prob_return.csv` | 席位画像原始表(19 列,见「表结构」文档) | | `yyb_duokong_stats_YYYY-MM-DD.csv` | 席位画像派生表(43 列,`综合多空分` 即画像分) | | `lhb_seat_duokong_tag_YYYY-MM-DD.csv` | 席位明细 × 画像的人工核对表(辅助产物) | | `yybph_daily.log` | 定时任务的追加日志 | 覆盖度(`coverage`,写进 JSON)示例:`seat_rows` 席位明细行数、`matched_rows` 匹配到画像的行数、 `matched_amount_ratio` 金额级匹配率、`panel_rows` 因子行数、`trading_days` 交易日数、 `factor_min` / `factor_max`。 > 注意:`matched_amount_ratio` 是**金额级**匹配率,因交易所汇总席位(机构专用、沪深股通专用)金额 > 天然较大且不参与匹配,该比值偏低(约 0.24)属正常,不代表画像质量差。 --- ## 7. 定时运行(每天 20:40) Windows 计划任务 `EastMoneyYYBPH_DailyUpdate`,触发时间 **20:40:00**,执行 `run_yybph_daily.bat`(`cd` 到脚本所在目录,逐步骤带 `errorlevel` 中断): | 步骤 | 命令 | 作用 | | --- | --- | --- | | 1 | `python eastmoney_yybph.py --no-factor` | 采集营业部排行(近一年),按 (date, dept_code) 增量落盘 | | 2 | `python yyb_duokong.py` | 由排行表派生席位画像,写 `yyb_duokong_stats_YYYY-MM-DD.csv` | | 3 | `python eastmoney_yybph.py --factor-only` | 抓席位 → 构因子 → 分析 → 落盘 → 提交 | 任一步 `errorlevel` 非 0 即 `goto fail` 中止,日志追加到 `yybph_daily.log`。 选择 20:40 的原因:交易所龙虎榜数据在盘后 18:00~20:00 之间陆续披露完毕,20:40 取数可拿到当日 完整席位明细,且早于次日开盘,保证 T 日盘后即可出因子。 `.bat` 文件必须保持 **ASCII-only**(`cmd` 按 ANSI 代码页解析),中文说明只写在本文件里。 --- ## 8. 提交到 AIStudio ### 8.1 提交通路 本地沙箱**无法提交**:环境中不存在 `bigalpha` / `factors` 模块,`bq.dai.query` 也会被服务端 拒绝(`FlightUnavailableError: 请先申请SDK使用权限`)。因此提交走 **AIStudio 在线环境(Notebook / 网页端因子库)**:把 `FACTOR_SQL` 与第 6 节的产物一起提交。 `submit_factor()` 已按参考文档写好,在 AIStudio 里执行 `python eastmoney_yybph.py --factor-only` 即会自动提交;本地执行时只打印「未检测到 bigalpha SDK,跳过因子提交」,**不报错**。 ### 8.2 `factors.submit_factor` 参数对照 | 参数 | 取值 | | --- | --- | | `id` | `alpha_yyb_seat_duokong` | | `performance_index` | 第 4 节的 `perf_dict`(`factor_direction` + `IC` + `{long,short,long_short}_{指标}` + `params` 全量,inf/nan 置 `None`) | | `performance_report` | `yyb_seat_duokong_factor_analysis.html` 的内容 | | `metadata` | `{}` | | `docs` | `{"因子类型": "资金流席位因子"}` | | `name` | `龙虎榜席位多空因子` | | `desc` | 因子定义 + 方向 + 样本窗口 | | `factor_sql` | 第 3.2 节的 `FACTOR_SQL` | ### 8.3 提交前检查 1. 在 AIStudio 中先单独跑一遍 `FACTOR_SQL`,确认能从 `cn_stock_top_inst_te_raw` 出数、 列名恰为 `date / instrument / factor`(本地因无 DAI 取数权限,只能离线校验); 2. 确认 `date` 已转为 `timestamp[ns]`、`instrument` 带交易所后缀; 3. 确认 `perf_dict` 中无 `inf` / `nan`(构造时已统一置 `None`)。 --- ## 9. 已知限制 1. `FACTOR_SQL` **尚未在真实 DAI 环境执行过**(本地无取数权限),只用 `duckdb` 建同构表做了 语法、列名、数值口径与「无前视」的等价验证; 2. 平台版画像用 `net_ratio` 近似本地 `综合多空分`,**两者数值不完全相等**,只保证同量纲、同方向; 3. 本地分析的前向收益只到 T+1(`D1_CLOSE_ADJCHRATE`),`ic_63` / `ic_126` / `ic_252` 与 `ret_63` / `ret_126` / `ret_252` 在 60 天回补窗口下为 `null`,需加大 `--factor-days` 才有值; 4. 席位画像为「近一年」样本,跨日复用不改变画像结论(见 `lhb_seat_duokong.py` 的说明)。 ## 1. 因子表(提交给平台,主表) 文件:`yyb_seat_duokong_factor.csv` | 规模:2825 行 × 3 列(2026-07-17 ~ 2026-09-14) | 字段 | 字段类型 | 字段描述 | | --- | --- | --- | | date | timestamp[ns] | 交易日期(龙虎榜上榜日 T 日) | | instrument | string | 股票代码,带交易所后缀(如 000566.SZ、600000.SH) | | factor | double | 因子值 = Σ(买/卖方向符号 × 金额 × (席位综合多空分 − 50)) / Σ金额,值域约 [−50, +50],>0 表示买方席位整体偏多 | 说明:`date + instrument + factor` 即平台标准因子表结构,可直接作为 `factor_field = factor` 的输入;同一 (date, instrument) 唯一,重复执行按该键去重(增量追加)。 --- ## 2. 席位画像表(上游 1,营业部排行) 文件:`yyb_rise_prob_return.csv` | 规模:4715 行 × 19 列 来源:东方财富 `RPT_RATEDEPT_RETURNT_RANKING`,统计周期「近一年」(`CYCLE_CODE="04"`) | 字段 | 字段类型 | 字段描述 | | --- | --- | --- | | date | timestamp[ns] | 统计截止日(采集当日) | | rank | int32 | 营业部排名 | | dept_code | int64 | 营业部代码 | | dept_name | string | 营业部名称 | | buy_times_1d | int64 | 上榜后 1 日的买入次数 | | avg_increase_1d | double | 上榜后 1 日平均涨幅,单位 % | | rise_probability_1d_factor | double | 上榜后 1 日上涨概率,单位 %(尾部 `_factor` 标记的因子列) | | buy_times_2d | int64 | 上榜后 2 日的买入次数 | | avg_increase_2d | double | 上榜后 2 日平均涨幅,单位 % | | rise_probability_2d_factor | double | 上榜后 2 日上涨概率,单位 %(`_factor` 列) | | buy_times_3d | int64 | 上榜后 3 日的买入次数 | | avg_increase_3d | double | 上榜后 3 日平均涨幅,单位 % | | rise_probability_3d_factor | double | 上榜后 3 日上涨概率,单位 %(`_factor` 列) | | buy_times_5d | int64 | 上榜后 5 日的买入次数 | | avg_increase_5d | double | 上榜后 5 日平均涨幅,单位 % | | rise_probability_5d_factor | double | 上榜后 5 日上涨概率,单位 %(`_factor` 列) | | buy_times_10d | int64 | 上榜后 10 日的买入次数 | | avg_increase_10d | double | 上榜后 10 日平均涨幅,单位 % | | rise_probability_10d_factor | double | 上榜后 10 日上涨概率,单位 %(`_factor` 列) | --- ## 3. 营业部多空统计表(上游 2,席位画像) 文件:`yyb_duokong_stats_YYYY-MM-DD.csv`(每日一份快照) | 规模:4715 行 × 43 列 由 `yyb_duokong.py` 从「2.」派生,`综合多空分` 即因子公式中的席位画像分。 | 字段 | 字段类型 | 字段描述 | | --- | --- | --- | | date | timestamp[ns] | 统计截止日(快照日) | | 多空排名 | int64 | 按综合多空分降序的排名 | | rank | int64 | 原始营业部排名 | | dept_code | int64 | 营业部代码 | | dept_name | string | 营业部名称(与席位明细关联时的归一前名称) | | 下跌概率_1d | double | 上榜后 1 日下跌概率 = 100 − 上涨概率,单位 % | | 多空比_1d | double | 上榜后 1 日多空比(上涨概率 / 下跌概率) | | 多空概率差_1d | double | 上榜后 1 日多空概率差 = 上涨概率 − 下跌概率,单位 % | | 下跌概率_2d | double | 上榜后 2 日下跌概率,单位 % | | 多空比_2d | double | 上榜后 2 日多空比 | | 多空概率差_2d | double | 上榜后 2 日多空概率差,单位 % | | 下跌概率_3d | double | 上榜后 3 日下跌概率,单位 % | | 多空比_3d | double | 上榜后 3 日多空比 | | 多空概率差_3d | double | 上榜后 3 日多空概率差,单位 % | | 下跌概率_5d | double | 上榜后 5 日下跌概率,单位 % | | 多空比_5d | double | 上榜后 5 日多空比 | | 多空概率差_5d | double | 上榜后 5 日多空概率差,单位 % | | 下跌概率_10d | double | 上榜后 10 日下跌概率,单位 % | | 多空比_10d | double | 上榜后 10 日多空比 | | 多空概率差_10d | double | 上榜后 10 日多空概率差,单位 % | | 可信度 | string | 画像可信度档位(按上榜次数分档) | | 多空一致性 | int64 | 各档位多空方向一致的个数(0~5) | | 多空概率差_加权 | double | 按上榜次数加权的多空概率差,单位 % | | 期望收益_加权 | double | 按上榜次数加权、由多空概率差反解的期望收益,单位 % | | 多空评分 | double | 由多空概率差_加权映射的评分 | | 期望评分 | double | 由期望收益_加权映射的评分 | | 综合多空分 | double | 多空评分与期望评分的合成,0~100,50 为中性;因子公式中减 50 后使用 | | 方向 | string | 画像方向标签(偏多 / 中性 / 偏空) | | buy_times_1d | int64 | 上榜后 1 日的买入次数(原始列) | | avg_increase_1d | double | 上榜后 1 日平均涨幅,单位 %(原始列) | | rise_probability_1d_factor | double | 上榜后 1 日上涨概率,单位 %(`_factor` 列) | | buy_times_2d | int64 | 上榜后 2 日的买入次数(原始列) | | avg_increase_2d | double | 上榜后 2 日平均涨幅,单位 %(原始列) | | rise_probability_2d_factor | double | 上榜后 2 日上涨概率,单位 %(`_factor` 列) | | buy_times_3d | int64 | 上榜后 3 日的买入次数(原始列) | | avg_increase_3d | double | 上榜后 3 日平均涨幅,单位 %(原始列) | | rise_probability_3d_factor | double | 上榜后 3 日上涨概率,单位 %(`_factor` 列) | | buy_times_5d | int64 | 上榜后 5 日的买入次数(原始列) | | avg_increase_5d | double | 上榜后 5 日平均涨幅,单位 %(原始列) | | rise_probability_5d_factor | double | 上榜后 5 日上涨概率,单位 %(`_factor` 列) | | buy_times_10d | int64 | 上榜后 10 日的买入次数(原始列) | | avg_increase_10d | double | 上榜后 10 日平均涨幅,单位 %(原始列) | | rise_probability_10d_factor | double | 上榜后 10 日上涨概率,单位 %(`_factor` 列) | --- ## 4. 席位多空标注表(辅助产物,不入因子) 文件:`lhb_seat_duokong_tag_YYYY-MM-DD.csv` | 规模:570 行 × 25 列 由 `lhb_seat_duokong.py` 生成:当日席位明细(买卖前 5)逐条挂上席位画像,用于人工核对 「哪个席位在买 / 在卖、画像偏多还是偏空」。 | 字段 | 字段类型 | 字段描述 | | --- | --- | --- | | 交易日期 | timestamp[ns] | 席位明细所属交易日 | | 代码 | int64 | 股票代码(纯数字,无交易所后缀) | | 名称 | string | 股票名称 | | 方向 | string | 该席位当日方向(买 / 卖) | | 排名 | int64 | 席位在该方向上的金额排名 | | 营业部 | string | 营业部名称(席位明细口径) | | 买入额 | double | 买入金额,单位元 | | 卖出额 | double | 卖出金额,单位元 | | 净额 | double | 净成交额 = 买入额 − 卖出额,单位元 | | 3日上涨概率% | double | 该席位近一年「上榜后 3 日」上涨概率,单位 % | | 3日上榜次数 | double | 该席位近一年「上榜后 3 日」样本数 | | 买入占比% | double | 买入额占该股龙虎榜成交额比,单位 % | | 卖出占比% | double | 卖出额占该股龙虎榜成交额比,单位 % | | 上榜原因 | string | 交易所在龙虎榜上给出的上榜原因 | | 匹配方式 | string | 影像匹配结果(名称归一匹配 / 汇总席位 / 未匹配) | | dept_code | double | 营业部代码(来自多空统计表,未匹配为空) | | 综合多空分 | double | 该席位画像的综合多空分,0~100 | | 多空评分 | double | 该席位画像的多空评分 | | 期望评分 | double | 该席位画像的期望评分 | | 席位多空方向 | string | 该席位画像方向(偏多 / 中性 / 偏空) | | 可信度 | string | 该席位画像可信度档位 | | 多空一致性 | double | 该席位画像多空一致档数(0~5) | | 多空概率差_加权 | double | 该席位画像加权多空概率差,单位 % | | 期望收益_加权 | double | 该席位画像加权期望收益,单位 % | | 近一年上榜次数 | double | 该席位近一年上榜次数 | --- ## 5. 平台侧输入数据源(`factor_sql` 的输入) 数据源:`cn_stock_top_inst_te_raw`(中文名「龙虎榜机构明细」,分类 `/用户分享数据/股票数据`) | 字段 | 字段类型 | 字段描述 | | --- | --- | --- | | date | timestamp[ns] | 交易日期 | | instrument | string | 股票代码,带交易所后缀(.SH/.SZ/.BJ) | | exalter | string | 营业部(席位)名称 | | side | string | 买卖类型,`'0'` = 买入前 5、`'1'` = 卖出前 5 | | buy | double | 买入额,单位元 | | sell | double | 卖出额,单位元 | | net_buy | double | 净成交额 = 买入额 − 卖出额,单位元 | | buy_rate | double | 买入占比(该数据源中为空) | | sell_rate | double | 卖出占比(该数据源中为空) | | reason | string | 上榜原因 | 类型说明:`date` / `instrument` / `exalter` / `side` / `reason` 的取值形态已按实际数据确认; 浮点列的精确精度(`double` / `float`)以平台 `bqdai.get_datasource_schema("cn_stock_top_inst_te_raw")` 的返回为准。 关联关系(本地链路): ``` cn_stock_top_inst_te_raw(平台侧,等价的龙虎榜席位明细) │ │ 席位名称归一 norm_seat():剥离公司后缀、统一「证券营业部」写法 ▼ yyb_rise_prob_return.csv ──yyb_duokong.py──▶ yyb_duokong_stats_YYYY-MM-DD.csv │ │ └────────── 席位画像(综合多空分)───────────────────┘ │ │ factor = Σ s·amt·(综合多空分 − 50) / Σ amt ▼ yyb_seat_duokong_factor.csv(date / instrument / factor) ```

用例
# 龙虎榜席位多空因子 · 用例 覆盖四类场景:**定时运行**、**本地手工运行**、**结果读取与核对**、**AIStudio 提交**。 所有命令的工作目录均为本仓库根目录(`c:\Users\Administrator\Documents\trae_projects`)。 --- ## 用例 1:每日定时运行(无需人工干预) **前置**:计划任务 `EastMoneyYYBPH_DailyUpdate` 已存在,触发时间 20:40:00。 **执行** ```powershell schtasks /query /tn "EastMoneyYYBPH_DailyUpdate" /v /fo LIST | Select-String "任务名|Task To Run|开始时间|Start Time|下次运行时间|Next Run Time" ``` **预期** - 「开始时间 / Start Time」为 `20:40:00`; - 「要运行的任务 / Task To Run」指向 `run_yybph_daily.bat`,且「起始于 / Start In」为仓库目录; - 次日检查日志出现三步的成功标记: ```powershell Get-Content .\yybph_daily.log -Tail 20 ``` 预期结尾为: ``` [<日期> <时间>] OK - csv refreshed + duokong table written + seat factor analysed ``` **异常**:日志出现 `FAILED - aborted, csv NOT refreshed`,说明三步中某一步 `errorlevel` 非 0, 按用例 6 排查。 --- ## 用例 2:本地手工运行 ### 2.1 全流程(采集 + 因子分析) ```powershell & "C:\Users\Administrator\AppData\Local\Programs\Python\Python314\python.exe" .\eastmoney_yybph.py ``` 预期:打印营业部排行前几行、`共采集 4715 条数据`、`已追加 0 条`(当日已采过则为 0), 接着进入因子环节并打印整体绩效与 IC 分析,最后提示 `未检测到 bigalpha SDK(当前非 AIStudio 环境),跳过因子提交`(本地不报错)。 ### 2.2 只采集排行(对应定时链路第 1 步) ```powershell python .\eastmoney_yybph.py --no-factor ``` ### 2.3 只做因子(对应定时链路第 3 步,用已有数据) ```powershell python .\eastmoney_yybph.py --factor-only ``` ### 2.4 加长回补窗口(让 `ic_63` / `ic_126` 出值) ```powershell python .\eastmoney_yybph.py --factor-only --factor-days 400 ``` 说明:默认 60 自然日窗口下,`ic_63` / `ic_126` / `ic_252`、`ret_63` / `ret_126` / `ret_252` 必然为 `null`(样本不足)。 ### 2.5 只算不提交 ```powershell python .\eastmoney_yybph.py --factor-only --no-submit ``` ### 2.6 自定义分层 / 股票池 / 基准 ```powershell python .\eastmoney_yybph.py --factor-only --group-num 5 --instruments 中证500 --benchmark 沪深300 ``` --- ## 用例 3:读取产物 ### 3.1 读因子表(提交到平台的那张) ```python import pandas as pd df = pd.read_csv("yyb_seat_duokong_factor.csv", encoding="utf-8-sig", parse_dates=["date"]) print(df.shape) # (2825, 3) print(df.dtypes.to_dict()) # date: datetime64[ns] / instrument: object / factor: float64 print(df.head()) # date instrument factor # 0 2026-07-17 000566.SZ -8.405071 ``` **检查点**:列名恰为 `['date', 'instrument', 'factor']`;(date, instrument) 无重复; `instrument` 全部带 `.SH` / `.SZ` / `.BJ` 后缀。 ```python assert list(df.columns) == ["date", "instrument", "factor"] assert not df.duplicated(["date", "instrument"]).any() assert df["instrument"].str.contains(r"\.(SH|SZ|BJ)$").all() ``` ### 3.2 读分析结果 JSON ```python import json with open("yyb_seat_duokong_factor_analysis.json", encoding="utf-8") as f: rep = json.load(f) print(rep["window"], rep["params"]) print(rep["ic_summary"]) # {'IC': 0.2188, 'IC_ABS_GT_0.02': 0.9762, 'IR': 1.3947, 'trading_days': 42} print(rep["coverage"]) # matched_amount_ratio 偏低属正常,见文档第 6 节 ``` ### 3.3 看 HTML 报告 ```powershell start .\yyb_seat_duokong_factor_analysis.html ``` **检查点**:净值曲线出现三条线(long / short / long_short)+ benchmark;表格含 「整体绩效 / 年度绩效 / IC 分析 / 因子值最大 5 只 / 因子值最小 5 只」。 --- ## 用例 4:因子值口径核对(离线,不依赖平台权限) **目的**:本地无 DAI 取数权限,但 DAI SQL 是 DuckDB 方言,可用本地 `duckdb` 建同构表验证 `FACTOR_SQL` 的语法、输出列名、数值口径与「无前视」性质。 ```python import duckdb from eastmoney_yybph import FACTOR_SQL DDL = """ CREATE TABLE cn_stock_top_inst_te_raw ( date TIMESTAMP, instrument VARCHAR, exalter VARCHAR, side VARCHAR, buy DOUBLE, sell DOUBLE, net_buy DOUBLE, buy_rate DOUBLE, sell_rate DOUBLE, reason VARCHAR); """ # 席位A 历史净买为正(偏多);席位B 历史净卖为正(偏空);席位C 首次上榜无历史 ROWS = [ ("2026-09-01", "600000.SH", "席位A", "0", 1000.0, 0.0), ("2026-09-01", "600000.SH", "席位B", "1", 0.0, 500.0), ("2026-09-02", "600000.SH", "席位A", "0", 2000.0, 0.0), ("2026-09-02", "600000.SH", "席位B", "1", 0.0, 1000.0), ("2026-09-03", "600000.SH", "席位A", "0", 1000.0, 0.0), # 当日:偏多的 A 在买 ("2026-09-03", "600000.SH", "席位A", "1", 0.0, 3000.0), # 当日:偏多的 A 同时在卖(反向,负贡献) ("2026-09-03", "600000.SH", "席位B", "0", 1000.0, 0.0), # 当日:偏空的 B 在买(反向,负贡献) ("2026-09-03", "600000.SH", "席位C", "0", 3000.0, 0.0), # 当日:C 首次上榜,无历史 → 剔除 ] con = duckdb.connect() con.execute(DDL) con.executemany("INSERT INTO cn_stock_top_inst_te_raw VALUES (?,?,?,?,?,?,NULL,NULL,NULL,NULL)", ROWS) df = con.execute(FACTOR_SQL).fetchdf() assert list(df.columns) == ["date", "instrument", "factor"] got = df[df["date"].astype(str).str.startswith("2026-09-03")]["factor"].iloc[0] # 手工推导:A 的 net_ratio=1(09-01 买1000/卖0),B 的 net_ratio=-1(09-01 买0/卖500),C 被剔除 num = (1 * 1000.0 * 50.0 * 1.0) + ((-1) * 3000.0 * 50.0 * 1.0) + (1 * 1000.0 * 50.0 * (-1.0)) den = 1000.0 + 3000.0 + 1000.0 assert abs(got - num / den) < 1e-9 # -30.0 days = sorted(df["date"].astype(str).str.slice(0, 10).tolist()) assert days == ["2026-09-02", "2026-09-03"] # 09-01 窗口内无更早历史,被剔除 print("校验通过:语法可执行、列名正确、口径与手工计算一致、无前视") ``` **预期输出** ``` 校验通过:语法可执行、列名正确、口径与手工计算一致、无前视 2026-09-03 的 factor = -30.0000 ``` --- ## 用例 5:AIStudio 提交 ### 5.1 在真机(AIStudio)上先验 SQL ```python from bigquant import dai as bqdai # 1) 确认数据源与字段 print(bqdai.get_datasource_schema("cn_stock_top_inst_te_raw")) # 2) 跑因子 SQL(替换为 eastmoney_yybph.FACTOR_SQL 的全文) sql = """ SELECT date, instrument, exalter, side, buy, sell FROM cn_stock_top_inst_te_raw WHERE date >= DATE '2026-09-01' ORDER BY date DESC, instrument LIMIT 20 """ print(bqdai.query(sql)) ``` **检查点**:`side` 取值为字符串 `'0'` / `'1'`;`date` 为日期类型;`instrument` 带交易所后缀。 若 `bqdai.query` 报 `FlightUnavailableError: 请先申请SDK使用权限`,说明当前环境没有 DAI 取数权限, 需在平台侧申请后再验证。 ### 5.2 提交因子 在 AIStudio 中执行(`submit_factor()` 会自动完成,无需手写): ```python from bigalpha import factors import json import pandas as pd from eastmoney_yybph import FACTOR_ID, FACTOR_NAME, FACTOR_SQL with open("yyb_seat_duokong_factor_analysis.json", encoding="utf-8") as f: rep = json.load(f) with open("yyb_seat_duokong_factor_analysis.html", encoding="utf-8") as f: html = f.read() params = rep["params"] perf_dict = {"factor_direction": params["factor_direction"], "IC": rep["ic_summary"]["IC"]} for row in rep["whole_perf"]: portfolio = row.pop("portfolio") for column, value in row.items(): perf_dict[f"{portfolio}_{column}"] = value # long_return_ratio / short_ic / ... perf_dict.update(params) factors.submit_factor( id=FACTOR_ID, performance_index=perf_dict, performance_report=html, metadata={}, docs={"因子类型": "资金流席位因子"}, name=FACTOR_NAME, desc="龙虎榜营业部席位多空因子:按买卖前5席位金额加权席位近一年综合多空分;" "因子方向 %s;样本窗口 %s ~ %s" % (params["factor_direction"], rep["window"]["start"], rep["window"]["end"]), factor_sql=FACTOR_SQL, ) ``` **检查点**:提交成功后在因子库中能看到 `alpha_yyb_seat_duokong`,`factor_sql` 可复算出与 `yyb_seat_duokong_factor.csv` 同量纲的因子值;`performance_index` 中不含 `inf` / `nan`(已统一置 `None`)。 ### 5.3 一键式(AIStudio 里直接跑脚本) ```bash python eastmoney_yybph.py --factor-only ``` 输出中出现 `已提交因子 alpha_yyb_seat_duokong(龙虎榜席位多空因子)` 即为成功。 --- ## 用例 6:常见问题排查 | 现象 | 原因 | 处理 | | --- | --- | --- | | 本地提示 `未检测到 bigalpha SDK...跳过因子提交` | 本地无 `bigalpha` 模块 | 正常行为,改在 AIStudio 提交 | | `FlightUnavailableError: 请先申请SDK使用权限` | 当前环境无 DAI 取数权限 | 在平台侧申请权限后再查数 | | 日志 `FAILED - aborted, csv NOT refreshed` | 三步中某步失败 | 逐步手工执行用例 2.2 / `python yyb_duokong.py` / 2.3 定位 | | `因子表与前向收益没有重叠样本,无法分析` | `--factor-days` 窗口内没有已披露前向收益的样本 | 加大 `--factor-days`,或确认当日龙虎榜是否已披露 | | `matched_amount_ratio` 只有 0.2 上下 | 交易所汇总席位(机构专用 / 沪深股通专用)金额大但不参与匹配 | 属正常,见文档第 6 节 | | 席位大规模「未匹配」 | 两个数据源的营业部命名出现新写法 | 检查 `lhb_seat_duokong.py` 的 `CORP_SUFFIXES` / 分支写法归一规则,按实际情况补充(只做确定性替换) | | `ic_63` / `ret_63` 等为 `null` | 60 天窗口样本不足 | 正常,用 `--factor-days 400` 复算 | | `.bat` 执行后中文乱码或直接报错 | `.bat` 内混入了非 ASCII 字符 | `.bat` 必须保持 ASCII-only,中文说明写在 `.md` 文档里 | | `python -c "..."` 在 PowerShell 报 `ParserError: Unexpected token '-c'` | PowerShell 解析引号的方式 | 改为写临时 `.py` 探针再运行 | --- ## 用例 7:席位标注表人工核对(可选) ```powershell python .\lhb_seat_duokong.py --date 2026-09-15 ``` 输出 `lhb_seat_duokong_tag_2026-09-15.csv`,并打印行级与金额级匹配率、未匹配席位排名。 两日对比(反手买 / 反手卖): ```powershell python .\lhb_seat_duokong.py --compare 2026-09-14 2026-09-15 ``` **检查点**:`匹配方式` 列只应出现「名称归一匹配 / 汇总席位 / 未匹配」三类; `综合多空分` 与 `yyb_duokong_stats_*.csv` 中同 `dept_code` 的取值一致。
表结构
字段 字段类型 字段描述
instrument string -
date timestamp[ns] -
factor double -

表名:alpha_yyb_seat_duokong_data

起始时间:

最近更新时间: