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

PTrade 平台如何通过 get_fundamentals 查询市销率与市现率进行低估值选股?(附 Python 源码)

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

问题描述

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

Title: PTrade 基本面选股:结合市销率(PS)与市现率(PCF)筛选低估值股票

Question: 如何在 PTrade 中通过 get_fundamentals 查询 valuation 表中的市销率和市现率进行选股?

解决方案

PTrade 基本面选股:结合市销率(PS)与市现率(PCF)筛选低估值股票

在 PTrade 量化交易平台中,通过基本面因子(如市销率 PS 和市现率 PCF)筛选低估值标的是一种经典且高效的量化选股策略。


一、核心 API 接口说明

PTrade 提供了 get_fundamentals 函数用于获取财务三大报表及日频估值数据。

get_fundamentals 调取估值表 (valuation)

  • 语法get_fundamentals(security, 'valuation', fields=None, date=None)
  • 表名valuation(估值表)
  • 核心字段
    • ps: 市销率(PS)
    • pcf: 市现率(PCF)
    • pb: 市净率(PB)
    • pe_ttm: 动态/滚动市盈率

注意valuation 表仅支持按天查询模式(通过 date 参数),不入参 date 时回测默认取前一交易日数据以防未来函数。


二、策略编写思路

  1. 定义股票池:获取目标指数成分股(如沪深300 000300.XBHS)。
  2. 剔除异常股:过滤 ST、停牌及退市股票。
  3. 因子获取:使用 get_fundamentals 获取股票池中所有股票的 pspcf 数据。
  4. 排序与筛选:对指标大于 0 的股票按指标从小到大排序,挑选市值相对营收和现金流双低估的股票(例如各取前 10% 的交集或综合排名)。
  5. 调仓执行:根据选股结果定期调整持仓。

三、完整 Python 策略源码示例

import pandas as pd
import numpy as np

def initialize(context):
    # 设置参考基准
    set_benchmark('000300.SS')
    # 设置佣金与费率
    set_commission(commission_ratio=0.0003, min_commission=5.0)
    
    # 定义全局变量
    g.hold_count = 10  # 最终持仓股票数量
    
    # 每天 09:31 执行选股与调仓
    run_daily(context, rebalance, time='9:31')

def rebalance(context):
    # 1. 获取沪深300成分股
    stocks = get_index_stocks('000300.XBHS')
    
    # 2. 过滤 ST、停牌等股票
    st_status = get_stock_status(stocks, 'ST')
    halt_status = get_stock_status(stocks, 'HALT')
    valid_stocks = [s for s in stocks if not st_status.get(s) and not halt_status.get(s)]
    
    # 3. 查询 valuation 表中的 ps 和 pcf 字段
    # 获取上一交易日日期
    prev_date = str(get_trading_day(-1)).replace('-', '')
    df_valuation = get_fundamentals(
        security=valid_stocks,
        table='valuation',
        fields=['ps', 'pcf'],
        date=prev_date
    )
    
    if df_valuation is None or df_valuation.empty:
        log.info('未能获取到估值数据')
        return
    
    # 4. 数据清洗与筛选(剔除负值或缺失值)
    df_clean = df_valuation[(df_valuation['ps'] > 0) & (df_valuation['pcf'] > 0)].copy()
    
    # 计算综合低估值得分(排名得分之和)
    df_clean['ps_rank'] = df_clean['ps'].rank(ascending=True)
    df_clean['pcf_rank'] = df_clean['pcf'].rank(ascending=True)
    df_clean['total_score'] = df_clean['ps_rank'] + df_clean['pcf_rank']
    
    # 按综合得分从低到高排序,取前 N 只
    target_df = df_clean.sort_values(by='total_score').head(g.hold_count)
    target_stocks = list(target_df.index)
    
    log.info('本日筛选出的低估值股票: %s' % target_stocks)
    
    # 5. 执行调仓逻辑
    # 卖出不在目标池中的股票
    for stock in list(context.portfolio.positions.keys()):
        if stock not in target_stocks:
            order_target(stock, 0)
            log.info('卖出标的:%s' % stock)
            
    # 均分资金买入目标股票
    if len(target_stocks) > 0:
        target_value = context.portfolio.portfolio_value / len(target_stocks)
        for stock in target_stocks:
            order_target_value(stock, target_value)
            log.info('买入/调整标的:%s 至目标价值:%s' % (stock, target_value))

def handle_data(context, data):
    pass

四、注意事项

  1. 限流保护get_fundamentals 为 HTTP 在线调用,批量查询大股票池(如全 A 股)时,建议加入分批处理或 time.sleep(),单次请求字段不宜过多。
  2. 数据的负值处理:市现率 PCF 在企业经营现金流为负时可能为负数,在选股时需先过滤 pcf > 0ps > 0 的标的,避免将经营恶化的企业误判为低估值。