问题描述
# 导入函数库
from jqfactor import Factor, calc_factors
class BookToPriceRatio(Factor):
name = 'book_to_price_ratio'
max_window = 1
dependencies = ['book_to_price_ratio']
def calc(self, data):
return data['book_to_price_ratio'].iloc[0]
# 定义股票池
securities = ['600519.XSHG']
# 计算因子值
factors = calc_factors(securities, [BookToPriceRatio()], start_date='2017-01-01', end_date='2017-03-01', use_real_price=False, skip_paused=False)
# 查看因子值
factors['book_to_price_ratio'].head()
600519.XSHG
2017-01-03 -1.572684
2017-01-04 -1.602377
2017-01-05 -1.593870
2017-01-06 -1.621405
2017-01-09 -1.610634
book_to_price_ratio怎么是负的?
解决方案
您好!您在使用 calc_factors 获取 book_to_price_ratio(账面市值比)时发现贵州茅台(600519.XSHG)的数据为负数,这是因为聚宽因子库中的风格因子(Style Factors)在底层已经经过了标准化(Z-score)处理。
原因解析
根据 JoinQuant API 文档中关于风格因子数据处理说明的规定,系统会对风格因子(如 book_to_price_ratio、size、momentum 等)进行以下正规化处理:
- 去极值:将2.5倍标准差之外的值,赋值成2.5倍标准差的边界值。
- 标准化:采用市值加权标准化,公式为:
$$x = \frac{x - mean(x)}{std(x)}$$
为什么茅台是负数?
book_to_price_ratio(账面市值比)是市净率(PB)的倒数。贵州茅台(600519)作为典型的高估值、高股价白马股,其市净率(PB)远高于市场平均水平,因此其账面市值比(1/PB)远低于市场平均水平。在经过上述 $x = (x - mean) / std$ 的标准化处理后,低于均值的数据就会呈现为负数。这代表该股票的账面市值比在全市场中处于较低的分位数位置。
解决方案
如果您希望获取原始的、未经过标准化的账面市值比或市净率数据,建议不要直接使用风格因子库中的 book_to_price_ratio,而是通过财务数据 API get_fundamentals 来获取市净率(pb_ratio),然后自行取倒数。
获取原始 PB 数据的代码示例:
from jqdata import *
# 查询 600519 在指定日期的市净率 (PB)
q = query(valuation.code, valuation.pb_ratio).filter(valuation.code == '600519.XSHG')
df = get_fundamentals(q, date='2017-01-03')
# 计算原始的账面市值比 (1 / PB)
if not df.empty:
raw_book_to_price = 1 / df['pb_ratio'][0]
print("原始账面市值比:", raw_book_to_price)
总结来说,您代码中获取的负值是正确的标准化因子暴露度(Factor Exposure),常用于多因子模型的回归和打分;如果用于基本面绝对值分析,请改用 get_fundamentals 获取原始财务指标。