问题描述
解决方案
在PTrade中,get_fundamentals 函数获取的估值数据(如市盈率)通常是基于前一个交易日收盘价计算的静态数据,盘中不会实时更新。
要在盘中计算实时的动态市盈率,我们需要利用“昨收动态市盈率”和“实时股价涨跌幅”进行推算。
计算逻辑
由于当天的每股收益(EPS)在盘中是固定的(除非当天发布财报,但通常财报在盘后发布),动态市盈率的变化仅由股价变化引起。
公式如下:
$$ \text{实时动态市盈率} = \text{昨日动态市盈率} \times \frac{\text{当前最新价}}{\text{昨日收盘价}} $$
或者理解为:
- 先算出动态EPS:$ \text{动态EPS} = \frac{\text{昨日收盘价}}{\text{昨日动态市盈率}} $
- 再算实时PE:$ \text{实时动态市盈率} = \frac{\text{当前最新价}}{\text{动态EPS}} $
策略代码实现
以下是一个完整的策略示例,展示了如何在盘中每隔几秒计算并打印实时的动态市盈率。
def initialize(context):
# 设置我们要操作的股票,以恒生电子为例
g.security = '600570.SS'
set_universe(g.security)
# 设置每3秒运行一次计算函数,模拟盘中实时监控
run_interval(context, calculate_realtime_pe, seconds=3)
def calculate_realtime_pe(context):
# 1. 获取基础数据:昨日的动态市盈率 (pe_dynamic)
# get_fundamentals 默认获取的是最近一个交易日结束后的数据
# 注意:PTrade文档指出 pe_dynamic 返回类型为 str,需要转换
q = get_fundamentals(g.security, 'valuation', ['pe_dynamic'])
if q is None or len(q) == 0:
log.info("未获取到财务数据")
return
# 获取昨日动态PE字符串并转为浮点数
# get_fundamentals 返回的是DataFrame,索引是股票代码
try:
pe_dynamic_yesterday = float(q['pe_dynamic'][g.security])
except:
log.info("财务数据格式转换失败")
return
# 2. 获取实时行情快照
snapshot = get_snapshot(g.security)
if not snapshot:
log.info("未获取到行情快照")
return
# 获取当前最新价 (last_px) 和 昨日收盘价 (preclose_px)
current_price = snapshot[g.security].get('last_px')
pre_close = snapshot[g.security].get('preclose_px')
# 数据有效性检查
if current_price == 0 or pre_close == 0:
log.info("当前集合竞价或停牌,无有效价格")
return
# 3. 计算实时动态市盈率
# 公式:实时PE = 昨日PE * (当前价 / 昨收价)
realtime_pe = pe_dynamic_yesterday * (current_price / pre_close)
# 4. 打印结果
log.info("股票: %s" % g.security)
log.info("昨日收盘价: %.2f, 昨日动态PE: %.2f" % (pre_close, pe_dynamic_yesterday))
log.info("当前最新价: %.2f" % current_price)
log.info("实时动态市盈率: %.4f" % realtime_pe)
log.info("-" * 30)
def handle_data(context, data):
pass
代码详解
-
获取基准PE (
get_fundamentals):- 我们查询
valuation表中的pe_dynamic字段。 - 在PTrade中,这个数据通常是基于前一交易日的收盘数据计算好的。
- 注意类型转换:文档说明该字段返回类型为
str,因此代码中使用float()进行了转换。
- 我们查询
-
获取实时价格 (
get_snapshot):- 使用
get_snapshot获取毫秒级的实时行情。 - 提取
last_px(最新成交价) 和preclose_px(昨收价)。
- 使用
-
计算逻辑:
- 利用比例关系:
实时PE / 昨日PE = 当前价 / 昨收价。 - 这种方法避免了手动去计算EPS(每股收益)和处理复杂的财报季度年化问题,直接利用了PTrade系统已经计算好的昨日基准数据,计算速度快且准确。
- 利用比例关系:
Q&A
Q: 为什么不直接用 get_fundamentals 获取实时的 PE?
A: get_fundamentals 是基于财务报表和日终数据更新的,它不会随着盘中股价的每一笔跳动而更新。如果在盘中调用它,返回的仍然是昨日收盘时的静态市盈率。
Q: 这个计算方法适用于 pe_ttm (滚动市盈率) 吗?
A: 适用。如果你想计算实时的 TTM 市盈率,只需将代码中的 pe_dynamic 替换为 pe_ttm 即可,计算逻辑完全一致。
Q: 如果股票停牌了怎么办?
A: 如果股票停牌,get_snapshot 返回的 last_px 通常为 0 或者等于 preclose_px(取决于停牌类型和时间),且成交量为0。代码中加入了 if current_price == 0 的判断来防止数据异常。