Hi Chris, I have fixed this issue by creating PERatio CustomFactor, where I manually calculated PE ratio from current close price and trailing 12-months EPS. I then compared the results with Morningstar data for the correct dates and they were pretty close. See the notebook for more details.
In short, you need to add the following code:
def get_periodic(df, periods, interval_days=252):
""" Get periodic data
df: DataFrame object.
periods(int): Number of periods to go back for.
interval_days(int): Number of trading days, default to 252 (one year).
"""
idx = [-1]
for i in range(1, periods):
idx.append(-i * interval_days)
idx.reverse()
periodic_data = df[idx]
return periodic_data
class PERatio(CustomFactor):
inputs = [USEquityPricing.close,
Fundamentals.diluted_eps_earnings_reports]
outputs = ['pe', 'close', 'eps']
quarter_days = 252/4
quarters = 5
window_length = quarter_days*quarters
def compute(self, today, assets, out, close, eps):
close_p = get_periodic(close, self.quarters, interval_days=self.quarter_days)
eps_p = get_periodic(eps, self.quarters, interval_days=self.quarter_days)
# For each company
for i in range(close_p.shape[1]):
uniq_eps_ids = np.unique(eps_p[:,i], return_index=True)[1]
uniq_eps = [eps_p[index, i] for index in sorted(uniq_eps_ids)]
out.close[i] = close_p[-1, i]
out.eps[i] = np.sum(uniq_eps[-4:])
out.pe[i] = close_p[-1, i] / out.eps[i]
And to use it simply do as follows
pe_ratio = PERatio()
Then add pe_ratio.eps in your pipeline.
Would appreciate more testing if anyone's available.