Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
CustomFactor question

Hello everyone,

I have a CustomFactor question. Suppose I want to write a CustomFactor whose value today depends on it's value yesterday. What is a good way to write this. Can I access the past values of my CustomFactor when calculating it's value today?
Second case, suppose I have a CustomFactor1 which needs value of CustomFactor2 to be computed today, and CustomFactor2 needs the value of CustomFactor1 yesterday to be computed today. How can I handle this? Initial condition for CustomFactor2 can be 0.

Thanks

8 responses

What you are asking is 'can one have recursive factors'? The answer is yes with a big caveat. Factors can be recursive but cannot be 'infinitely recursive'. They must have an independent initial value.

Both cases above are basically the same. The first case is something like this (using pseudo code)

# Here a factor depends upon the previous value of the factor  
factor1[1] <- factor1[0]

The second case is the same but interjects an 'intermediary' factor

# Here an intermediate factor (factor2) is used but basically the same as above  
factor1[1] <- factor2[1]  
factor2[1] <-  factor1[0]

# Really have this situation (the same as above)  
factor1[1]  <-  factor1[0]

So, yes one can use a factor as an input (even the same factor). However, there must be a finite number of 'recursions'. Take a simple custom factor which adds one to the previous input value. If the input is the same factor it will add one to the previous value of the factor.

class Plus_1(CustomFactor):  
    window_length=2  
    window_safe = True  
    def compute(self, today, assets, out, factor_value):  
        out[:] = factor_value[0] + 1

However, there must be a finite number of times this is called, and it must be given an initial value. Something like this

constant_0 = Constant_0()  
plus_1 = Plus_1(inputs=[constant_0])  
plus_2 = Plus_1(inputs=[plus_1])  
plus_3 = Plus_1(inputs=[plus_2])  
my_pipe = Pipeline(columns={'plus_3': plus_3}  )  

Notice the first time it uses a constant as an input but after that it simply 'calls' itself. This could also be done in a for loop so no need to explicitly write out each iteration. However, don't do this. This isn't the best approach.

The best approach is to put all the recursion into a single custom factor. There is no escaping a for loop. Almost by definition, recursive calculations cannot be 'vectorized'. So something like this

class Plus_N(CustomFactor):  
    """  
    Set the window_length to the N value. This will get the function value after N days.  
    The initial value is set in self.initial_value  
    """  
    inputs = []  
    window_safe = True  

    initial_value = 0

    def my_function(self, x):  
        """  
        This is the recursive function.  
        Here it just adds 1 but it could be any function.  
        The input x is the previous value used to generate the new value.  
        """  
        return x+1

    def compute(self, today, assets, out,):  
        # First set the starting value  
        value = self.initial_value

        # Iterate to get the final value  
        for i in range(0, self.window_length):  
            value = self.my_function(value)

        out[:] = value


The attached notebook shows this in more detail. To customize the factor simply define your own code in my_function.

Disclaimer

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by Quantopian. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. No information contained herein should be regarded as a suggestion to engage in or refrain from any investment-related course of action as none of Quantopian nor any of its affiliates is undertaking to provide investment advice, act as an adviser to any plan or entity subject to the Employee Retirement Income Security Act of 1974, as amended, individual retirement account or individual retirement annuity, or give advice in a fiduciary capacity with respect to the materials presented herein. If you are an individual retirement or other investor, contact your financial advisor or other fiduciary unrelated to Quantopian about whether any given investment idea, strategy, product or service described herein may be appropriate for your circumstances. All investments involve risk, including loss of principal. Quantopian makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances.

Thank you Dan for your succint reply and help.

What I wanted to do is have an ema type computation so that every new value in my factor value series is simply an update on the previous value of my factor series and in this way I wanted to somehow avoid the for loop and the window_length. I was hoping this way of setting it up would make the entire calculation faster(reduce number of calculations from window_length to 1). Is it possible to achieve this?

There's generally no escaping a for loop. If a value relies on a previous value then one needs to iterate over all those values. Those calculations cannot be done in parallel because they are not independent and rely on previous results. Now, there are some tricks. Can your computation be re-written to not require recursion? For example EMA can be estimated very well using a simple (non-recursive) formula (see https://en.wikipedia.org/wiki/Moving_average).

Also, you can still vectorize the individual calculations across assets. Those presumably aren't dependent. You will just need to loop through the days.

Dan,

Thanks again for your quick reply. I am sorry, I believe I have been unclear in what I am asking.

With respect to the EMA example,
St = alpha * Yt + (1-alpha) * St-1

If I make a CustomFactor to do this, I would need the value of St-1(value at time t-1) available to me when computing St(value at time t). Can I get this in a CustomFactor?

class MyEMA(CustomFactor):  
    def compute(self, today, assets, out, factor_value):  
        #out[:] = alpha * factor_value[-1] + (1-alpha) * what would I put here as I would need the value of out before the update I am guessing

It may help if you could provide a notebook with an attempt at your custom factor. Get it working as best you can and then it can be debugged. I don't want to be misunderstanding what you are trying to do. Better to work with a concrete example. Thanks.

Hi Dan,

Thank you again for your response and patience. Attaching a notebook, I hope I am able to explain it better now.

Best
Aashutosh

Here is a notebook showing three ways to get EWMA of price. The custom factor version can be modified to implement any custom 'recursive' function and not just EWMA. Perhaps this can give you some ideas. As mentioned, you really can't escape a for loop and some way to store the interim factor values.

Hope that helps.

Dan,

Thanks for your patience and help . I understand it now.

Best