股吧人气排名因子
(alpha_guba_popularity_rank_data)
数据描述:
文档
数据简介
> 英文名:**Guba Popularity Rank**(`guba_popularity_rank`)
## 1. 因子定位
**股吧人气排名因子**(`alpha_guba_popularity_rank`)是一个**股吧人气 / 关注度排名型因子**。
- **思路**:条件选股「股吧人气排名」方案(方案 id `xc13e91a5065c200db1c`)的结果集,
该方案本身就是「当日股吧人气最高」的选股模板——条件文本为
`股吧人气排名;不要st股及不要退市股;`,即取当日全市场股吧人气榜,并剔除 ST 与退市股。
- **取值**:`factor = -guba_rank`,其中 `guba_rank` = 页面**「股吧人气排名」**列(1 = 当日股吧人气最高)。
因排名越小人气越高,取负号以满足平台约定 `factor_direction = 1`(因子值越大越看多)。
示例日值域 `factor ∈ [-5565.0, -1.0]`,**非稀疏**(示例口径日 5361 只全部有值)。
- **跨日可比性**:`guba_rank` 是全市场口径的绝对名次(含跳号),
因此同一只票在不同交易日的 `factor` 可直接纵向比较(名次是否上升),
便于做「当日股吧人气变化」类的时序加工。
用例
脚本:`xuangu_guba_popularity_rank.py`(与本文件同目录) | 定时:每天 21:08(`run_guba_popularity_rank_daily.bat`)
前置约定:
- 工作目录 `c:\Users\Administrator\Documents\trae_projects\股吧人气排名\`;
- 本地 Python:`C:\Users\Administrator\AppData\Local\Programs\Python\Python314\python.exe`;
- 依赖:`requests` + `pandas`(本地即可跑通取数与落 CSV);`dai` / `bigalpha` 仅 AIStudio 提供,
本地缺失时脚本**自动降级**(只打印提示、跳过落库与提交,不抛异常);
- 目标页:`https://xuangu.eastmoney.com/Result?color=w&type=stock&id=xc13e91a5065c200db1c&a=edit_way`
(方案 id `xc13e91a5065c200db1c`)。
> 本因子**不做本地回测**,因此下列用例只核对「明细表数值」与「因子面板口径」,
> 不含 IC / 绩效校验。
>
> 下列输出中的日期与行数取自实测示例日 **2026-09-17**(5361 行),实际运行随当日数据变化。
---
## 用例 1:每日定时运行(无需人工干预)
**前置**:计划任务 `XuanguGubaPopularityRank_DailyUpdate` 已按「文档」第 7 节注册,触发时间 21:08:00;
运行身份为 `SYSTEM`(`LogonType=ServiceAccount`,不依赖用户登录),且已勾选「错过启动时间后尽快启动」。
**执行**:不干预,等待 21:08 自动触发 `run_guba_popularity_rank_daily.bat`。
**预期**
1. 日志 `guba_popularity_rank.log` 追加 `START` / `RUN` / `OK -` 三行(时间戳格式为
`[周X YYYY/MM/DD HH:MM:SS.cc]`;日期随运行日变化):
```
[周四 2026/09/17 21:08:00.12] ===== START daily guba popularity rank =====
[周四 2026/09/17 21:08:00.12] RUN xuangu_guba_popularity_rank.py
[周四 2026/09/17 21:08:12.31] OK - daily run finished, see row counts in the log below
```
2. 日志正文含脚本自己的分页回显与落表回显(实测示例日 5361 只 / 6 页):
```
第 1 页:1000 行(累计 1000 / 共 5361)
第 2 页:1000 行(累计 2000 / 共 5361)
第 3 页:1000 行(累计 3000 / 共 5361)
第 4 页:1000 行(累计 4000 / 共 5361)
第 5 页:1000 行(累计 5000 / 共 5361)
第 6 页:361 行(累计 5361 / 共 5361)
=== 股吧人气排名因子:2026-09-17(接口共 5361 只,取到 5361 行)===
名次分布:guba_rank ∈ [1, 5565],共 5361 只,跳号 204 个(被方案条件排除的个股仍占名次)
明细表:本次 5361 行 / 日期 2026-09-17,增量 5361 行 -> ...\股吧人气排名\a_guba_popularity_rank.csv
重复日期数据检查:无重复日期数据(5361 行,(date, instrument) 唯一)
```
3. `a_guba_popularity_rank.csv` 在口径日推进时追加当日 4 列横截面(按 `(date, instrument)` 去重),
口径日未推进时增量为 0;
4. 任务退出码 0(日志无 `FAILED -` 行)。
**检查点**:`a_guba_popularity_rank.csv` 中 `date` 最大值 = 当日;当日行数与接口 `total` 一致;
文件名与列名仍为 `date,instrument,name,guba_rank`(4 列,无多余列)。
**异常**:日志出现 `FAILED - aborted, a_guba_popularity_rank.csv NOT refreshed` ⇒ 脚本 `errorlevel` 非 0,
按「用例 7」排查。**非交易日**属预期:接口给出的口径日仍是上一交易日,
脚本按 `(date, instrument)` 去重后打印「增量 0 行」并正常退出(`OK -` 行照常写)。
---
## 用例 2:本地手工运行
### 2.1 默认(抓最新快照 + 增量落 CSV,不提交)
```powershell
cd c:\Users\Administrator\Documents\trae_projects\股吧人气排名
python xuangu_guba_popularity_rank.py --no-submit
```
**预期输出**(实测示例日)
```
方案条件文本(接口返回):股吧人气排名;不要st股及不要退市股;
第 1 页:1000 行(累计 1000 / 共 5361)
第 2 页:1000 行(累计 2000 / 共 5361)
第 3 页:1000 行(累计 3000 / 共 5361)
第 4 页:1000 行(累计 4000 / 共 5361)
第 5 页:1000 行(累计 5000 / 共 5361)
第 6 页:361 行(累计 5361 / 共 5361)
=== 股吧人气排名因子:2026-09-17(接口共 5361 只,取到 5361 行)===
名次分布:guba_rank ∈ [1, 5565],共 5361 只,跳号 204 个(被方案条件排除的个股仍占名次)
明细表:本次 5361 行 / 日期 2026-09-17,增量 5361 行 -> ...\股吧人气排名\a_guba_popularity_rank.csv
重复日期数据检查:无重复日期数据(5361 行,(date, instrument) 唯一)
因子分布:5361 行 | guba_rank ∈ [1, 5565] | factor ∈ [-5565.0, -1.0]
date instrument factor
2026-09-17 600105.SH -1.0
2026-09-17 002584.SZ -2.0
2026-09-17 002617.SZ -3.0
2026-09-17 600206.SH -4.0
2026-09-17 002491.SZ -5.0
--no-submit:跳过因子数据源落库与提交
```
**检查点**:
- 6 页累计 = 接口 `total` = 5361;
- `跳号数 = (5565 − 1 + 1) − 5361 = 204`;
- `factor = -guba_rank` 逐行成立(第 1 行 `-1.0`;第 3 行 `-3.0` 说明名次 3 未被排除个股占用);
- CSV 列恰为 `date,instrument,name,guba_rank`,且「股吧人气排名」已翻译为英文列名 `guba_rank`。
### 2.2 重复运行(增量去重)
```powershell
python xuangu_guba_popularity_rank.py --no-submit
```
**预期**:输出与 2.1 相同,但落表回显变为 `增量 0 行`,**文件内容不变**。
**检查点**:`(Get-Item a_guba_popularity_rank.csv).LastWriteTime` 不变;行数不变。
### 2.3 指定日期
```powershell
python xuangu_guba_popularity_rank.py --date 2026-09-17 --no-submit
```
**预期**:`date` 列强制写为 `2026-09-17`(覆盖接口给出的口径日)。
**检查点**:脚本回显 `=== 股吧人气排名因子:2026-09-17(...)===`;
若接口实际口径日已是 2026-09-17,则同样「增量 0 行」。
### 2.4 只取少量行(调试)
```powershell
python xuangu_guba_popularity_rank.py --limit 100 --no-submit
```
**预期**:只发第 1 页请求并截取前 100 行;**勿据此落库**(结果不完整,
会污染 `(date, instrument)` 去重口径——同日已存在的行不会被覆盖)。
### 2.5 用已有明细表直接提交(不联网)
```powershell
python xuangu_guba_popularity_rank.py --from-csv
```
**预期**:打印 `=== 股吧人气排名因子:复用明细表 a_guba_popularity_rank.csv(N 行 / M 个日期)===`,
随后走落库 + 提交链路;本地无 `dai`/`bigalpha` 时依次打印两条跳过提示:
```
未检测到 dai SDK(当前非 AIStudio 环境),跳过因子数据源落库
未检测到 bigalpha SDK(当前非 AIStudio 环境),跳过因子提交;本地结果见 a_guba_popularity_rank.csv
```
**检查点**:`--from-csv` **不访问网络**;会先做一次重复日期数据检查,若有重复则删行(见用例 5)。
### 2.6 指定输出路径
```powershell
python xuangu_guba_popularity_rank.py --out D:\tmp\a_guba_popularity_rank.csv --no-submit
```
**预期**:明细写到指定路径(目录须已存在),控制台回显的路径随之变化。
---
## 用例 3:读取产物
```python
import pandas as pd
df = pd.read_csv("a_guba_popularity_rank.csv", encoding="utf-8-sig")
print(df.dtypes)
print(df.shape) # 单日示例:(5361, 4)
print(df.columns.tolist()) # ['date', 'instrument', 'name', 'guba_rank']
print(df["date"].max()) # 2026-09-17
print(sorted(df["guba_rank"])[:3], sorted(df["guba_rank"])[-3:])
# [1, 2, 3] [5563, 5564, 5565]
# 因子面板口径复核
panel = df.assign(factor=-df["guba_rank"].astype("float64"))
print(panel["factor"].min(), panel["factor"].max()) # -5565.0 -1.0
```
**检查点**:
- `date` / `instrument` / `name` 为 `object`,`guba_rank` 为 `int64`;
- `df.duplicated(subset=["date", "instrument"]).sum() == 0`;
- 行数 = 接口 `total`(示例日 5361)。
---
## 用例 4:口径核对(「股吧人气排名」vs 页面「序号」)
**目的**:确认 `guba_rank` 取的是**「股吧人气排名」**(接口 `GUBA_TOP_REAL_TIME*`),
不是页面第一列「序号」(接口 `SERIAL`)。
**执行**
```powershell
python -c "import pandas as pd; d=pd.read_csv('a_guba_popularity_rank.csv',encoding='utf-8-sig'); print(len(d), d['guba_rank'].min(), d['guba_rank'].max(), (d['guba_rank'].max()-d['guba_rank'].min()+1)-len(d))"
```
**预期**:`5361 1 5565 204`(示例日)。
**判定**:若 `guba_rank` 落在 `1..5361` 且恰好连续(跳号 0),则说明取到的是 `SERIAL`(序号),
口径取错——应检查 `parse_rows()` 里对 `GUBA_TOP_REAL_TIME` 前缀的匹配。
**辅助核对(市场分布)**:
```powershell
python -c "import pandas as pd; d=pd.read_csv('a_guba_popularity_rank.csv',encoding='utf-8-sig'); print(d['instrument'].str.split('.').str[-1].value_counts().to_dict(), (d['instrument'].str.startswith('688')).sum())"
```
**预期**:`{'SZ': 2782, 'SH': 2238, 'BJ': 341} 604`。
**判定**:方案条件只写了「不要 st 股及不要退市股」,**未排除北交所与科创板**,
因此 `.BJ` 必须有值(示例日 341 只)、688 开头必须存在(示例日 604 只)。
若 `.BJ` 为 0 或 688 为 0,说明取错了方案或方案条件已被改动。
**另一项核对(条件回显)**:接口响应里 `data.responseConditionList` 会回显方案条件与命中数,
可直接与脚本口径比对(示例日):
```
股吧人气排名 且 非[ST股票] 且 非[退市股] -> stockCount = 5361
```
---
## 用例 5:重复日期数据检查与删除(用户指定要求)
**目的**:确认明细表中**同一 `(date, instrument)` 不会出现重复行**;一旦出现,
脚本会**删除该行**并整表重写。
### 5.1 正常情况(无重复)
```powershell
python xuangu_guba_popularity_rank.py --check-dup
```
**预期**
```
=== 股吧人气排名因子:重复日期数据检查 a_guba_popularity_rank.csv ===
重复日期数据检查:无重复日期数据(5361 行,(date, instrument) 唯一)
```
**检查点**:文件未被改写(`LastWriteTime` 不变)。
### 5.2 构造重复并验证删除(实测通过)
**步骤 1**:复制原始 CSV 并人为注入 3 行重复日期数据(复制第 0 行 1 次 + 第 1 行 2 次):
```python
import pandas as pd
df = pd.read_csv("a_guba_popularity_rank.csv", dtype=str, encoding="utf-8-sig")
print("orig rows", len(df)) # 5361
extra = pd.concat([df.iloc[[0]], df.iloc[[1]], df.iloc[[1]]], ignore_index=True)
pd.concat([df, extra], ignore_index=True).to_csv("_tmp_dup_test.csv", index=False, encoding="utf-8-sig")
print("injected rows", len(pd.read_csv("_tmp_dup_test.csv", encoding="utf-8-sig"))) # 5364
```
**步骤 2**:对含重复的文件执行检查:
```powershell
python xuangu_guba_popularity_rank.py --out "_tmp_dup_test.csv" --check-dup
```
**预期(实测输出)**
```
=== 股吧人气排名因子:重复日期数据检查 _tmp_dup_test.csv ===
重复日期数据检查:删除 3 行重复的日期数据 -> _tmp_dup_test.csv(剩余 5361 行)
```
**步骤 3**:复核
```powershell
python -c "import pandas as pd; d=pd.read_csv('_tmp_dup_test.csv',encoding='utf-8-sig'); print('rows', len(d), 'dup', d.duplicated(subset=['date','instrument']).sum())"
```
**预期**:`rows 5361 dup 0`。
**检查点**:
- 删除行数 = 注入行数(3);
- 保留的是**最早出现**的那一行(`keep="first"`);
- 重写后仍为 `utf-8-sig` 编码、列顺序不变、`date` 为 `YYYY-MM-DD`;
- 清理临时文件 `_tmp_dup_test.csv`。
> **日常无需手工干预**:每次正常运行在落盘后都会自动调用一次重复日期数据检查
> (回显 `重复日期数据检查:...` 一行);`--check-dup` 只是给它一个独立的触发入口。
---
表结构
| 字段 |
字段类型 |
字段描述 |
| instrument |
string |
-
|
| date |
timestamp[ns] |
-
|
| factor |
double |
-
|
表名:alpha_guba_popularity_rank_data
起始时间:
最近更新时间: