Pretty cool algo Seong!!
Going through your code I noticed that the returns calculation has an error that's in the original as well. The good news is that both the correct and incorrect versions are monotonic in that they will produce the same results when used as a ranking system. The difference is that the correct version produces fewer NaN/inf values so fewer stocks get dropped from the resulting array.
The error is that the log returns should be: R = log(P2 / P1), or log(P2) - log(P1)
Here the returns are calculated as, R = log(P2) / log(P1)
This backtest has the correct returns calculation. The results are similar, but there seems to be a bit more noise.
Just for fun, here's the factor I came up with for this using just numpy functions.
inputs = [USEquityPricing.close,]
window_length = 300
lookback_window = 50
log_returns = True
def compute(self, today, assets, out, close_price):
n = self.lookback_window
returns = np.log(close_price[n:] / close_price[:-n])
# log_px = np.log(close_price)
# returns = log_px[n:] - log_px[:-n]
returns = close_price[n:] / close_price[:-n] - 1
means = np.nanmean(returns, axis=1)
demeaned_returns = (returns.T - means).T
out[:] = np.nanmean(demeaned_returns, axis=0)