Back to Community
Standard deviation / computation on results from custom factor


First time posting in the forum so please excuse any odd formatting.

I wonder if anyone could help me with a problem. I created a custom factor called LastTwelveQuarters(...), inspired by Jamie McCorriston where I get the 12 latest quarters of e.g. revenue. I want to take these 12 latest quarters to do as following within the pipeline:

Step 1) Calculate the percentage difference between the quarter one year vs the same quarter the year before. An example could be 2019Q1 / 2018Q1, 2018Q1 / 2017Q1 etc. This would give me a total of 8 values from the 12 latest quarters.
Step 2) Create a filter that only includes stocks with a revenue growth of at least 10% on average based on the 8 values from step 1.
Step 3) Rank the stocks based on the standard deviation of the revenue growth from the 8 values, so that the stocks with the lowest standard deviation has the best rank. The hypothesis is that stocks with non-sporadic and consistent revenue growth are better.

I would like to do this in the pipeline but am having trouble understanding how to use my custom factor as a base for step 1-3. I understand that I could use the data from LastTwelveQuarters(...) to send the data for each quarter outside of the pipeline (as shown in the pipeline columns) and then process it there, but I would like all of this to be done in the pipeline.

Below is my current code.

Thank you in advance!

from quantopian.pipeline import Pipeline  
from quantopian.research import run_pipeline  
from import USEquityPricing  
from quantopian.pipeline.factors import Returns, AverageDollarVolume, Latest, CustomFactor  
from quantopian.pipeline.filters import QTradableStocksUS, StaticAssets

from import Fundamentals  
import numpy as np  
import pandas as pd

class LastTwelveQuarters(CustomFactor):  
    # Get the last 12 reported values of the given timestamp + field.  
    outputs = ['q1', 'q2', 'q3', 'q4', 'q5', 'q6', 'q7', 'q8', 'q9', 'q10', 'q11', 'q12']  
    window_length = (195 + 65)*3  
    # Tell pipeline that this is window_safe even though it really isn't  
    window_safe = True

    def compute(self, today, assets, out, timestamp, values):  
        for column_ix in range(timestamp.shape[1]):  
            _, unique_indices = np.unique(timestamp[:, column_ix], return_index=True)  
            quarterly_values = values[unique_indices, column_ix]  
            if len(quarterly_values) < 12:  
                quarterly_values = np.hstack([  
                    np.repeat([np.nan], 12 - len(quarterly_values)),  
            quarterly_values = quarterly_values[-12:]  
            out[column_ix] = quarterly_values   

def make_pipeline():

    universe = StaticAssets(symbols(['AAPL']))  
    rev_quarters = LastTwelveQuarters(inputs = [Fundamentals.total_revenue_timestamp, Fundamentals.total_revenue], mask=universe)  

   # Step 1)  
   # Step 2)  
   # Step 3)

    billion = 1000000000  
    return Pipeline(  
                'Rev_1': rev_quarters.q1 / billion,  
                'Rev_2': rev_quarters.q2 / billion,  
                'Rev_3': rev_quarters.q3 / billion,  
                'Rev_4': rev_quarters.q4 / billion,  
                'Rev_5': rev_quarters.q5 / billion,  
                'Rev_6': rev_quarters.q6 / billion,  
                'Rev_7': rev_quarters.q7 / billion,  
                'Rev_8': rev_quarters.q8 / billion,  
                'Rev_9': rev_quarters.q9 / billion,  
                'Rev_10': rev_quarters.q10 / billion,  
                'Rev_11': rev_quarters.q11 / billion,  
                'Rev_12': rev_quarters.q12 / billion,  

df = run_pipeline(make_pipeline(), '2019-07-01', '2019-07-01')