问题描述
from jqdata import *
获取当前ETF的估值PE_TTM(前3个交易日,取平均)
df1 = get_valuation('510050.XSHG', end_date=context.previous_date, count=3, fields=['pe_ratio'])
print(df1)
PE_TTM = mean(df1['pe_ratio'])
但总是显示:
INFO - Empty DataFrame
日期,我也调整了最近的时间,但还是这样的,为什么呢?是否这个API不提供估值PE_TTM的数据?!
解决方案
您好!您在使用 get_valuation 获取 ETF(如 510050.XSHG)的 PE 数据时返回 Empty DataFrame,是因为 get_valuation API 仅支持获取上市股票的市值和估值数据,不支持直接获取 ETF 基金或指数的估值数据。
为什么不支持?
pe_ratio(市盈率)等财务估值指标是基于上市公司的财务报表(如净利润)计算得出的。ETF 作为一种基金,本身并不直接产生营业收入和净利润,它的估值本质上是其底层跟踪的指数(如上证50指数 000016.XSHG)成分股的整体估值。
如何正确获取 ETF/指数的 PE_TTM?
如果您需要获取 ETF 的估值,通常的做法是计算该 ETF 所跟踪指数的成分股加权 PE。指数 PE 的经典计算公式为:指数 PE = 成分股总市值 / 成分股总净利润。
以下是为您编写的在 JoinQuant 中计算特定指数(如上证50)PE_TTM 的替代代码方案:
from jqdata import *
import pandas as pd
def get_index_pe_ttm(index_code, date):
"""
计算指定指数在指定日期的 PE_TTM
:param index_code: 指数代码,例如上证50为 '000016.XSHG'
:param date: 查询日期
:return: 指数的 PE_TTM
"""
# 1. 获取指数成分股
stocks = get_index_stocks(index_code, date)
if not stocks:
return None
# 2. 查询成分股的市值 (market_cap) 和 市盈率 (pe_ratio)
q = query(
valuation.code,
valuation.market_cap,
valuation.pe_ratio
).filter(
valuation.code.in_(stocks)
)
df = get_fundamentals(q, date=date)
if df.empty:
return None
# 3. 剔除 PE 为负或为空的异常数据(亏损企业通常不计入或特殊处理,这里做简单剔除)
df = df[df['pe_ratio'] > 0]
# 4. 计算隐含的净利润:净利润 = 市值 / PE
df['earnings'] = df['market_cap'] / df['pe_ratio']
# 5. 计算指数整体 PE:总市值 / 总净利润
total_market_cap = df['market_cap'].sum()
total_earnings = df['earnings'].sum()
if total_earnings > 0:
index_pe = total_market_cap / total_earnings
return index_pe
else:
return None
# --- 在策略中的使用示例 ---
def initialize(context):
run_daily(market_open, time='09:30')
def market_open(context):
# 510050.XSHG 跟踪的是上证50指数 (000016.XSHG)
index_code = '000016.XSHG'
# 获取前一个交易日的 PE_TTM
pe_ttm = get_index_pe_ttm(index_code, context.previous_date)
log.info(f"上证50指数在 {context.previous_date} 的 PE_TTM 为: {pe_ttm:.2f}")
总结
- 不要将 ETF 代码(如
510050.XSHG)传入get_valuation或get_fundamentals。 - 找到 ETF 对应的底层指数代码(如上证50为
000016.XSHG)。 - 通过提取指数成分股的市值和 PE,自行汇总计算出指数级别的 PE_TTM。