🚀 AI 一键生成 ptrade 策略代码
立即体验

ptrade 基本面选股:如何结合 EPS 与市盈率(PE)筛选优质股票?(附 Python 源码)

ptrade | 发布时间: 2026/7/25
以下内容由 EasyQuant 生成。

问题描述

请根据以下 SEO 主题生成完整页面内容:

Title: ptrade 基本面选股:结合每股指标(EPS)与估值筛选优质股票

Question: 如何使用 get_fundamentals 结合 EPS 和市盈率进行多条件量化选股?

解决方案

ptrade 基本面选股:结合每股指标(EPS)与估值筛选优质股票

在 ptrade 量化交易平台中,基于基本面的选股策略是寻找中长期优质标的的核心手段。通过结合**每股收益(EPS)市盈率(PE)**等估值指标,可以有效筛选出兼具盈利能力与价格吸引力的股票。

本文将详细讲解如何使用 ptrade 的 get_fundamentals 接口进行基本面数据查询,并提供一个完整的多条件选股策略示例。


核心接口:get_fundamentals

get_fundamentals 接口用于获取财务三大报表、估值数据以及各项财务能力指标。

1. 查询估值数据 (valuation 表)

用于获取市盈率(PE)、市净率(PB)等日频估值指标:

# 获取股票池在指定日期的动态市盈率
df_val = get_fundamentals(stocks, 'valuation', date='20230901', fields=['pe_dynamic', 'pb'])

2. 查询每股指标 (eps 表)

用于获取基本每股收益(basic_eps)等财务指标:

# 获取季度财务数据中的基本每股收益
df_eps = get_fundamentals(stocks, 'eps', fields=['basic_eps'], date='20230901', report_types='4')

策略实现思路

  1. 标的池预筛选:获取沪深 300 或全 A 股代码列表,过滤掉 ST、停牌及退市股票。
  2. 基本面条件筛选
    • 盈利能力:每股收益 basic_eps > 0.3 元;
    • 估值合理性:动态市盈率 pe_dynamic 在 0 到 30 之间(排除亏损及高估值标的)。
  3. 建仓与调仓:定期执行筛选,对符合条件的标的进行等权重买入或持仓调整。

ptrade 策略源码示例

import pandas as pd

def initialize(context):
    # 设置初始基准为沪深300
    set_benchmark('000300.SS')
    # 设定定时任务:每周一开盘前运行选股与调仓
    run_daily(context, rebalance, time='09:31')

def filter_stocks(context):
    # 获取全A股代码
    all_stocks = get_Ashares()
    
    # 1. 过滤 ST、停牌和退市股票
    valid_stocks = filter_stock_by_status(all_stocks, filter_type=["ST", "HALT", "DELISTING"])
    
    # 2. 查询估值数据 (pe_dynamic)
    val_df = get_fundamentals(valid_stocks, 'valuation', fields=['pe_dynamic'])
    if val_df is None or val_df.empty:
        return []
    
    # 转为数值类型并筛选:0 < pe_dynamic < 30
    val_df['pe_dynamic'] = pd.to_numeric(val_df['pe_dynamic'], errors='coerce')
    pe_filtered = val_df[(val_df['pe_dynamic'] > 0) & (val_df['pe_dynamic'] < 30)].index.tolist()
    
    # 3. 查询每股指标数据 (basic_eps)
    eps_df = get_fundamentals(pe_filtered, 'eps', fields=['basic_eps'], report_types='4')
    if eps_df is None or eps_df.empty:
        return []
    
    eps_df['basic_eps'] = pd.to_numeric(eps_df['basic_eps'], errors='coerce')
    eps_filtered = eps_df[eps_df['basic_eps'] > 0.3].index.tolist()
    
    # 取满足条件的前10只股票
    return eps_filtered[:10]

def rebalance(context):
    # 获取符合条件的股票池
    target_stocks = filter_stocks(context)
    log.info("今日筛选出的目标股票池:%s" % target_stocks)
    
    if not target_stocks:
        return
    
    # 清仓不在目标池中的股票
    positions = context.portfolio.positions
    for stock in list(positions.keys()):
        if stock not in target_stocks:
            order_target(stock, 0)
            log.info("卖出不在目标池中的股票:%s" % stock)
            
    # 等权重买入目标股票
    target_value = context.portfolio.portfolio_value / len(target_stocks)
    for stock in target_stocks:
        order_target_value(stock, target_value)
        log.info("目标买入股票:%s,目标金额:%.2f" % (stock, target_value))

def handle_data(context, data):
    pass

注意事项

  1. 流量与频率限制get_fundamentals 为在线接口,单次查询上限为 500 条数据记录,且调用频率建议不要超过 100 次/秒。在多股多字段查询时,建议分批或加入 time.sleep()
  2. 未来函数规避:在回测场景中,不传 date 参数默认取前一交易日数据;若手动指定 date,请确保传入的日期早于当前回测时间,避免引入未来数据。
  3. 数据类型转换:财务数据返回的部分字段类型可能为字符串,在进行逻辑比较前建议使用 pd.to_numeric 进行类型转换。