← 返回《初阶量化交易:策略编写及系统搭建》
📑 查看全课大纲(第 21 / 38 节)

实现低PE股票池(1)

约 5 分钟

📺 正在播放小象官方高清录播(支持倍速与清晰度调节)

实现低PE股票池(一):价值筛选逻辑与算法设计

小象实战讲义 · 初阶量化交易:策略编写及系统搭建 本讲义仅用于编程与量化方法教学,不构成任何投资建议。

在多因子选股与量化投资体系中,股票池(Stock Pool / Universe) 是整个策略运行的标的底座。盲目对全市场数千只标的进行全覆盖监控不仅耗费计算算力,更容易引入流动性匮乏、财务造假或极端高估值的劣质资产。通过引入市盈率(PE)估值因子,在时间序列起点构建具备安全边际的候选标的集合,是价值量化策略的核心出发点。

本讲系统阐述低估值价值选股的底层投资逻辑;严密拆解 0<PE<300 < PE < 30 核心筛选阈值、剔除亏损/高估/停牌标的算法;并基于 Python 与 MongoDB 构建单期股票池的精准筛选与提取流水线。


💡 核心导读

  • 低市盈率(PE)选股的数理与经济学逻辑
    • 市盈率计算公式PE=每股市价 Close每股收益 EPS=企业总市值年度净利润PE = \frac{\text{每股市价 } Close}{\text{每股收益 } EPS} = \frac{\text{企业总市值}}{\text{年度净利润}}
    • 经济内涵:PE 代表按照当前盈利水平收回投资成本所需的年数。在同等行业与增长预期下,低 PE 往往意味着估值折价,具备更强的估值修复动力(Mean Reversion)与安全边际。
  • 低 PE 股票池的三大硬性过滤边界
    1. 排除 PE0PE \le 0 的标的:上市公司每股收益 EPS0EPS \le 0(当期严重亏损),存在极高的 ST 戴帽、退市或流动性暴雷风险,坚决剔除;
    2. 排除 PE30PE \ge 30 的标的:估值溢价过高,过度透支未来成长性,在熊市或流动性紧缩周期中极易遭遇杀估值(Drawdown),坚决剔除;
    3. 排除非交易日停牌标的(is_trading == False:停牌股无法建立仓位或执行交易,必须在选股阶段剔除。
  • 股票池容量与排序截断
    • 对通过硬性过滤的标的按 PEPE 升序(从小到大)排列;
    • 截取前 100 只估值最低的标的作为当期候选股票池,既保证了价值因子的纯粹度,又通过 100 只标的分散了个股非系统性特质风险。
┌─────────────────────────────────────────────────────────────┐
│                    低 PE 股票池筛选漏斗模型                    │
└──────────────────────────────┬──────────────────────────────┘

 全市场 5000+ 只股票 ───────────▼
 ┌───────────────────────────────────────────────────────────┐
 │ ① 剔除亏损股 (PE ≤ 0) 与 停牌股 (is_trading == False)       │
 └─────────────────────────────┬─────────────────────────────┘

 ┌───────────────────────────────────────────────────────────┐
 │ ② 剔除高估值泡沫股 (PE ≥ 30)                              │
 └─────────────────────────────┬─────────────────────────────┘

 ┌───────────────────────────────────────────────────────────┐
 │ ③ 按 PE 升序排列,截取 Top 100 价值龙头入选股票池          │
 └───────────────────────────────────────────────────────────┘

一、市盈率估值因子的工程落地与防坑

1. 动态市盈率计算公式选择

在实际工程中,有两种计算 PE 的途径:

  • 途径 A(总市值法):总市值 / 归母净利润(依赖总股本与财报总净利);
  • 途径 B(单股比值法):当日不复权收盘价 / 最新已披露每股收益(Close/EPSClose / EPS)。 在轻量级系统中,途径 B 数据依赖最少、计算最直接,但必须确保 EPSEPS 严格使用已披露财报(publish_date

2. 为什么设置 0 到 30 的阈值区间?

  • PE<0PE < 0 的陷阱:数学上负数虽然比正数小,但在金融语义中代表亏损。若简单使用 sort(PE, ASCENDING) 而未加 PE > 0 过滤,排在最前面的将全是深度亏损的暴雷公司!
  • 0<PE<300 < PE < 30 的平衡:覆盖了银行、基建、消费、公用事业等大量具备稳定现金流与盈利能力的成熟期企业。

二、单期股票池筛选代码实现

在 MongoDB 中,可以通过组合查询指令高效完成筛选:

query = {
    'date': target_date,
    'is_trading': True,
    'pe': {'<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>g</mi><msup><mi>t</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mo>:</mo><mn>0</mn><msup><mo separator="true">,</mo><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">gt&#x27;: 0, &#x27;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="katex-base"><span class="katex-strut" style="height:0.9463em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.0359em;">g</span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="katex-sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="katex-base"><span class="katex-strut" style="height:0.9463em;vertical-align:-0.1944em;"></span><span class="mord">0</span><span class="mpunct"><span class="mpunct">,</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="katex-sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span>lt': 30.0}
}
cursor = DB_CONN['daily'].find(query).sort('pe', ASCENDING).limit(100)

📝 动手练一练

下面我们用 Python 编写一段 单期低 PE 股票池筛选与排序引擎,验证在包含亏损股、高估值股与停牌股的复杂市场环境中,能否精准提取前 3 只合规低估值标的:

import pandas as pd
import numpy as np

def filter_low_pe_stock_pool(market_df, top_k=3):
    """
    单期低 PE 股票池筛选算法:
    1. 过滤 0 < PE < 30 且 is_trading = True
    2. 按 PE 升序排序
    3. 截取 Top K 只标的作为候选池
    """
    df = market_df.copy()
    
    # 严格三项过滤
    condition = (df['PE'] > 0.0) & (df['PE'] < 30.0) & (df['is_trading'] == True)
    filtered = df[condition].copy()
    
    # 升序排序取 Top K
    selected = filtered.sort_values('PE', ascending=True).head(top_k)
    return selected

def test_filter_run():
    # 模拟某交易日全市场 6 只股票的估值与交易状态
    data = pd.DataFrame({
        'code': ['600001', '600002', '600003', '600004', '600005', '600006'],
        'name': ['某银行', '某地产', '某亏损股', '某科技泡沫', '某电力', '某停牌股'],
        'PE': [6.5, 12.0, -15.2, 85.0, 9.8, 8.0],
        'is_trading': [True, True, True, True, True, False]
    })
    
    res = filter_low_pe_stock_pool(data, top_k=3)
    
    print("================ 单期低 PE 股票池筛选结果 ================")
    print(res[['code', 'name', 'PE', 'is_trading']])
    print("---------------------------------------------------------")
    print(f"成功入选股票池标的: {res['code'].tolist()}")
    print("筛选说明: 成功排除亏损股(PE<0)、高估值股(PE>30)及停牌股(is_trading=False)!")
    print("=========================================================")

if __name__ == "__main__":
    test_filter_run()

运行结果输出:

================ 单期低 PE 股票池筛选结果 ================
     code  name    PE  is_trading
0  600001   某银行   6.5        True
4  600005   某电力   9.8        True
1  600002   某地产  12.0        True
---------------------------------------------------------
成功入选股票池标的: ['600001', '600005', '600002']
筛选说明: 成功排除亏损股(PE<0)、高估值股(PE>30)及停牌股(is_trading=False)!
=========================================================

本章小结

  1. 掌握股票池筛选核心逻辑:以 0<PE<300 < PE < 30 构筑安全边际,剔除亏损暴雷与高估值资产。
  2. 严防数学负数排序陷阱:在 MongoDB 或 Pandas 排序前必须显式加入 PE > 0 条件,杜绝将巨亏股票选入组合。
  3. 容量适度分散:截取前 100 只标的,平衡因子收益集中度与投资组合风险分散度。

📋 行动清单 (Action Checklist)

  • 运行本讲筛选代码,确认 600003(亏损)与 600006(停牌)被成功过滤;
  • 检查本地数据库查询条件,确保包含 {'pe': {'<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>g</mi><msup><mi>t</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mo>:</mo><mn>0</mn><msup><mo separator="true">,</mo><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">gt&#x27;: 0, &#x27;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="katex-base"><span class="katex-strut" style="height:0.9463em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.0359em;">g</span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="katex-sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="katex-base"><span class="katex-strut" style="height:0.9463em;vertical-align:-0.1944em;"></span><span class="mord">0</span><span class="mpunct"><span class="mpunct">,</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="katex-sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span>lt': 30}}
  • 预习下一讲,学习如何设计 7 日定期调仓周期与股票池调入调出集合运算。

— 小象教研组

配套学习资源与课件
  • 第3章课件:上手搭建最简单的交易系统(PDF · 3.8MB)
    下载
  • 开发环境准备:软件安装指导(PDF · 0.9MB · 建议第3章动手实践前先通读)
    下载
  • 量化入门推荐书单(PDF · 318KB)
    下载
🎁 免费学习资源

领取《小象 11GB VIP 课件资料包与大厂真题手册》

包含全套实战 Jupyter 源码、清洗后数据集、大厂高频面试真题与专属学员答疑交流群。

  • 完整 Python / 数据分析 Jupyter 实战源码
  • 大厂真实业务数据集与练习题
  • 微信扫码添加课程顾问,免费获取网盘下载链接
微信二维码:扫码添加课程顾问微信扫码添加顾问