Back to Community
'numpy.ndarray' object has no attribute 'zscore' Error

I am trying to run a zscore on a custom factor which outputs a % and has window_length = 1 and keep getting this error - 'numpy.ndarray' object has no attribute 'zscore

Is there a fix for this?

8 responses

Could you please share the snippet of code where this problem arrise? My guess is that you have written array.zscore when it should be ..zscore(array) but I might be wrong.

Below is the code, thanks for the help!

class eps_growth(CustomFactor):  
    fq1_eps_cons = PeriodicConsensus.slice('EPS', 'qf', 1) #upcoming quarter  
    fq2_eps_cons = PeriodicConsensus.slice('EPS', 'qf', 2) #2 quarters into future  
    fq1_eps_mean = fq1_eps_cons.mean.latest  
    fq2_eps_mean = fq2_eps_cons.mean.latest  
    inputs = [fq1_eps_mean, fq2_eps_mean]  
    window_length = 1  
    window_safe=True  
    def compute(self, today, assets, out, fq1_eps_mean, fq2_eps_mean):  
        eps_estimated_growth_factor = (fq2_eps_mean - fq1_eps_mean) / fq1_eps_mean  
        x = eps_estimated_growth_factor  
        out[:] = x.zscore()  

Ahh well, that seems to be the problem!

lol sorry, what is the fix? I am dumb and still can't get it to work

Ahh excuse me, I suppose that slices Fq#_eps_cons are numpy arrays and therefore so is x. Numpy arrays does not have a function named zscore but a function that takes in a numpy array.

Try

out[:] = scipy.stats.zscore(x)  

I guess this is the zscore function you seek.

Thanks! I think this is a step closer to correct but I just received a different error - " NoSuchSymbols: Failed to find securities matching [] "

My code looks like this now

class eps_growth(CustomFactor):  
    fq1_eps_cons = PeriodicConsensus.slice('EPS', 'qf', 1) #upcoming quarter  
    fq2_eps_cons = PeriodicConsensus.slice('EPS', 'qf', 2) #2 quarters into future  
    fq1_eps_mean = fq1_eps_cons.mean.latest  
    fq2_eps_mean = fq2_eps_cons.mean.latest  
    inputs = [fq1_eps_mean, fq2_eps_mean]  
    window_length = 1  
    window_safe=True  
    def compute(self, today, assets, out, fq1_eps_mean, fq2_eps_mean):  
        eps_estimated_growth_factor = (fq2_eps_mean - fq1_eps_mean) / fq1_eps_mean  
        x = eps_estimated_growth_factor  
        y = scipy.stats.zscore(x)  
        out[:] = y  

Any help would be greatly appreciated!

There are always many ways to code. A lot is personal preference. I like sticking to the built in factors and methods myself. So, rather than compute zscore inside the custom factor, maybe just output the 'growth factor' and then use the built in zscore factor (see the docs https://www.quantopian.com/docs/api-reference/pipeline-api-reference#zipline.pipeline.Factor.zscore). Something like this

class EPS_Growth(CustomFactor):  
    fq1_eps_cons = PeriodicConsensus.slice('EPS', 'qf', 1) #upcoming quarter  
    fq2_eps_cons = PeriodicConsensus.slice('EPS', 'qf', 2) #2 quarters into future  
    fq1_eps_mean = fq1_eps_cons.mean.latest  
    fq2_eps_mean = fq2_eps_cons.mean.latest  
    inputs = [fq1_eps_mean, fq2_eps_mean]  
    window_length = 1  
    window_safe=True  

    def compute(self, today, assets, out, fq1_eps_mean, fq2_eps_mean):  
        eps_estimated_growth_factor = (fq2_eps_mean - fq1_eps_mean) / fq1_eps_mean  
        out[:] = eps_estimated_growth_factor 

eps_growth = EPS_Growth()  
# Good practice to mask for nan and infinite values  
# These values do not play well with zscore  
eps_growth_zscore = eps_growth.zscore(mask=eps_growth.isfinite())  

However, you don't even really need a custom factor. Just use the built in factor operations. Something like this

fq1_eps_cons = PeriodicConsensus.slice('EPS', 'qf', 1) #upcoming quarter  
fq2_eps_cons = PeriodicConsensus.slice('EPS', 'qf', 2) #2 quarters into future  
eps_growth = (fq2_eps_cons.mean.latest - fq1_eps_cons.mean.latest) / fq1_eps_cons.mean.latest  
# Good practice to mask for nan and infinite values  
# These values do not play well with zscore  
eps_growth_z_score = eps_growth.zscore(mask=eps_growth.isfinite())

See the attached notebook. Both approaches are included showing they both return the same values.

Loading notebook preview...
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.

@ Dan, Thank you for this awesome response!