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

Hi,

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 quantopian.pipeline.data.builtin import USEquityPricing  
from quantopian.pipeline.factors import Returns, AverageDollarVolume, Latest, CustomFactor  
from quantopian.pipeline.filters import QTradableStocksUS, StaticAssets

from quantopian.pipeline.data 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 = 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(  
            columns={  
                '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,  
            },  
            screen=universe,  
      )

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