I've been implementing the algorithm in quantitative value for some time now in quantopian, which some success and much aggravation. I've implemented the algorithm to work through pipelines. For those unfamiliar with the book, here's an amazon link:
https://www.amazon.com/Quantitative-Value-Web-Site-Practitioners/dp/1118328078
I'm not sure if I want to share the implementation yet, given that it is still in progress, but here's a picture of the partial pipeline for the algorithm:
Edit: The image is rediculously large, better if you download it from here: https://dl.dropboxusercontent.com/u/61360917/index.png
This pipeline represents only one year history for the fundamental factors (that's two time periods one year apart), whereas the text recommends 8 years. With two year history the pipeline execution dies from being out of memory. I haven't been able to run a backtest, again because the pipeline runs out of memory. I have a feeling there might be a memory leak, since the pipeline runs once, starts the backtest, then dies on the next rebalance.
What's missing
Financial stability. This is almost implemented. I can't figure out how to implement a computation over a factor, such that f(x) = 1 if x > 0 else 0. If anyone can suggest an implementation of this function for pipeline factors, I will be grateful. I tried writing a custom factor, but that fails with an error. It might have to do with factors being restricted to take bound columns or "on factors which are deemed safe for use as inputs to other factors". Safe transformations are hardcoded into zipline, and it doesn't appear you can declare custom factors to be safe.
class PositiveToOne(CustomFactor):
window_length = 1
def compute(self, today, assets, out, data):
out[:] = data[-1].apply(lambda x: 1.0 if x > 0 else 0.0)
Edit: Positive-to-one is implemented as (x/|x| + 1)/2. This will not work if x is 0, but that should be an unlikely circumstance for the particular factors being thresholded.
Potential Fraud Detection. In principle this should be possible, I just haven't done it. It's just a long algebraic expression.
Output for Franchise Power, Computed Over One Year
Here's what the research environment spits out:
pout[pout['longs_filter']].sort('quality')[:32].index.get_level_values(1)
Index([ Equity(28450 [AGX]), Equity(13698 [MYGN]), Equity(8613 [CHDN]),
Equity(6458 [RGR]), Equity(45771 [MMI]), Equity(26563 [WLK]),
Equity(11645 [GBX]), Equity(3660 [HRB]), Equity(37869 [VRTS]),
Equity(18917 [HZO]), Equity(20284 [SKX]), Equity(812 [BEN]),
Equity(27413 [NSR]), Equity(36372 [SNI]), Equity(32860 [CPLA]),
Equity(27997 [WNR]), Equity(41 [ARCB]), Equity(36735 [IILG]),
Equity(6736 [SMG]), Equity(24799 [MTN]), Equity(9514 [BWA]),
Equity(4654 [MAN]), Equity(7990 [VLO]), Equity(45506 [PINC]),
Equity(39546 [LYB]), Equity(15397 [STRA]), Equity(33016 [ALGT]),
Equity(13718 [POOL]), Equity(915 [BKE]), Equity(36930 [DISC_A]),
Equity(21697 [NTRI]), Equity(1287 [CBI])],
dtype='object')