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

PTrade 基本面选股策略:如何利用 get_fundamentals 接口筛选低 PE/PB 股票?

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

问题描述

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

Title: PTrade 基本面选股:使用 get_fundamentals 筛选低 PE/PB 估值股票

Question: 如何通过 PTrade 的 get_fundamentals 接口查询并筛选全市场的估值数据?

解决方案

核心概念:PTrade 的 get_fundamentals 接口

在 PTrade 量化平台中,get_fundamentals 接口用于获取上市公司财务报表数据及日频估值数据。通过查询 valuation(估值表),量化交易者可以快速获取全市场股票的静态市盈率(pe_static)、动态市盈率(pe_dynamic)、市净率(pb)、总市值(total_value)等关键财务指标。


接口调用语法及关键参数

get_fundamentals(security, table, fields=None, date=None)
  • security: 股票代码或代码列表(如 get_Ashares() 获取的全市场股票)。
  • table: 财务数据表名,此处传入 'valuation' 表示查询估值数据。
  • fields: 查询字段,可选 'pe_dynamic'(动态PE)、'pe_ttm'(TTM市盈率)、'pb'(市净率)、'total_value'(总市值)等。
  • date: 查询日期,格式如 '20231010'。建议传入上一交易日日期,避免盘中数据未更新导致返回 NaN

实现步骤与策略源码

以下是一个完整的 PTrade 基本面选股示例:每日开盘前获取全市场 A 股,筛选出 动态 PE < 20PB < 2 的低估值股票,并自动建仓。

import pandas as pd

def initialize(context):
    # 设置基准为沪深300
    set_benchmark('000300.SS')
    # 每天 09:31 执行选股与交易
    run_daily(context, select_and_trade, time='9:31')

def select_and_trade(context):
    # 1. 获取当前交易日及前一交易日
    prev_date = context.previous_date.strftime('%Y%m%d')
    
    # 2. 获取全市场 A 股列表
    all_stocks = get_Ashares(date=prev_date)
    
    # 3. 过滤 ST、停牌及退市股票
    valid_stocks = filter_stock_by_status(all_stocks, filter_type=["ST", "HALT", "DELISTING"])
    
    # 4. 通过 get_fundamentals 获取估值数据
    df_valuation = get_fundamentals(
        security=valid_stocks,
        table='valuation',
        fields=['pe_dynamic', 'pb', 'total_value'],
        date=prev_date
    )
    
    if df_valuation.empty:
        log.warning("未获取到估值数据")
        return
    
    # 5. 数据数据清洗与类型转换
    df_valuation['pe_dynamic'] = pd.to_numeric(df_valuation['pe_dynamic'], errors='coerce')
    df_valuation['pb'] = pd.to_numeric(df_valuation['pb'], errors='coerce')
    
    # 6. 条件筛选:低 PE (0 < pe_dynamic < 20) 且 低 PB (0 < pb < 2)
    filtered_df = df_valuation[
        (df_valuation['pe_dynamic'] > 0) & (df_valuation['pe_dynamic'] < 20) &
        (df_valuation['pb'] > 0) & (df_valuation['pb'] < 2)
    ]
    
    # 按市净率升序排序,取前 10 只股票
    target_stocks = filtered_df.sort_values(by='pb').head(10).index.tolist()
    log.info("筛选出的目标股票池: %s" % target_stocks)
    
    # 7. 调仓逻辑:卖出不在目标池中的持仓
    current_positions = context.portfolio.positions
    for stock in list(current_positions.keys()):
        if stock not in target_stocks and current_positions[stock].amount > 0:
            order_target(stock, 0)
            log.info("卖出非目标股: %s" % stock)
            
    # 8. 平均分配资金买入目标股票
    if target_stocks:
        value_per_stock = context.portfolio.cash / len(target_stocks)
        for stock in target_stocks:
            order_target_value(stock, value_per_stock)
            log.info("买入股票: %s,目标价值: %.2f" % (stock, value_per_stock))

注意事项与优化建议

  1. 流量与频次限制get_fundamentals 为在线接口,单次查询上限为 50,000 个单元格数据。建议先通过 filter_stock_by_status 剔除停牌/ST股票,减少数据传输量。
  2. 数据类型处理:估值表中部分字段返回可能包含非数值类型,在进行条件判断前,使用 pd.to_numeric 进行转换以防程序报错。
  3. 未来函数规避:在回测或盘前阶段查询财务数据时,date 参数应传入上一交易日(如 context.previous_date),以防止在交易时间内引入未来数据。