Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Checked this for loop inside CustomFactor, but getting unexpected results

This factor should be able to find if the low price of any 3 consecutive days within the 20 days is within very close proximity. It should scan this for every security and trail backwards around 20 times.

So it sums the low price of three previous days and finds a mean.
If the difference between the first day and the mean is lower than the arbitrary value of 0.15 then the variable increment (that is like a rank score) should increase by 1.
The days increment backwards so that it scans first -1, -2, -3 days, then -2, -3, -4 days etc.

The result I get every time is just 1 whereas it should vary for 520 stocks I got the result for. Pulling the increment = 0 variable out of the while loop results in the out[:] increment being always 19. I checked the delta_low_three value and it varies greatly and should produce a value other than 1 for the increment.

(and another weird thing is that it wouldn't let me compare with the 0.15 without np.all() or np.any() on the delta_low_three). It throws an error about the truth ambiguity with numpy.

class Previous_Strong(CustomFactor):  
    inputs = [USEquityPricing.low] #USEquityPricing.high, USEquityPricing.close]  
    # outputs =  
    window_length = 22  
    mask = is_tradable_long  
    def compute(self, today, asset_id, out, low):  
        day = -1  
        while np.abs(day) < 20:  
            x = (low[day]+low[day-1]+low[day-2])/3  
            delta_low_three = low[day] - x  
            delta_low_three = np.abs(delta_low_three)  
            day -= 1  
            increment = 0  
            if np.abs(np.all(delta_low_three)) < 0.15:  
                increment += 1  
            out[:] = increment  
2 responses

Since you are trying to do calculations on a rolling 3 day window, I would suggest using a 'rolling' method. Numpy doesn't have a good way to do rolling functions but pandas does. First convert the 'low' data, which is a numpy array, into a pandas dataframe. Then use the pandas rolling method and apply your function, which will be True or False, to each group of 3 days. Finally, sum up the number of Trues. That will be the 'score'. Definitely stay away from loops if possible. So something like this will do what you want

class Previous_Strong(CustomFactor):  
    inputs = [USEquityPricing.low]  
    window_length = 22  

    def compute(self, today, asset_id, out, low):  
        # Make a pandas dataframe so we can use the rolling methods  
        low_df = pd.DataFrame(low)

        # Set True whenever the first value of the window minus the mean is less than a constant  
        MIN_DELTA = .15  
        first_lower_than_mean = low_df.rolling(3).apply(lambda group: (group[0]-group.mean() < MIN_DELTA))

        # Sum the number of times the above condition is true  
        score = first_lower_than_mean.sum()  
        out[:] = score 

One thing to remember is there may be nans in pricing data. Fortunately, pandas handles nans pretty well in both the mean and the comparison. However, the comparison will be False if the first price is a nan. Therefore it won't get summed. This is probably what's desired but it should be considered.

Good luck.

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. Very helpful as always. One more thing, how can I register the price of the day where the score incremented by 1?
I'm trying to do this via the if statement, but realizing that nesting anything other than numbers and bools inside the "ifs" always results in an error.