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

I am trying to compute a custom factor using this class:

class EMA(CustomFactor):  
    inputs = [USEquityPricing.close]  
    window_length = 100  
    def compute(self, today, assets, out,vol):  
        out[:] = talib.EMA(vol, timeperiod=50)[-1]  

However, I get the following error:
``` talib/func.pyx in talib.func.EMA (talib/func.c:63497)()

AssertionError: real has wrong dimensions
```

What am I doing wrong?

Also, I would like to call the class with a window length:

ema50 = EMA(mask=tradeable_stocks, window_length=50)  

and then use the following class:

class EMA(CustomFactor):  
    inputs = [USEquityPricing.close]  
    def compute(self, today, assets, out,vol):  
        out[:] = talib.EMA(vol, timeperiod=window_length)[-1]  

but it doesn't like it.

2 responses

First off a little refresher on custom factor inputs and outputs. The parameter(s) passed to the compute function (in your case 'vol') is a 2 dimensioned numpy array with rows and columns. The number of rows are the number of trading days you are requesting data for (ie the window_length). The number of columns are the number of securities being passed. This is normally every security in the Quantopian database but can be a subset of those if a mask is used when instantiating the custom factor (eg mask=my_mask).

The output of the compute function is a 1 dimensioned numpy array with length equal to the number of securities which is the number of columns (ie securities) in the input data. There is one value for each security (ie not an array of values for each security).

The problem(s) in your custom factor are 1) the talib.EMA function expects a 1 dimensioned array as input and not a 2 dimensioned array and 2) talib.EMA returns an array of averages but the factor ultimately expects only a single value for each security (you must have picked up on this by trying to use the [-1] index).

The solution is to iterate over each column of the inputs (ie each security), do your ta-lib function for that one security and set a specific value in the output array (eg output[column] = result). This isn't the most 'pythonic' way but it works.

A good place to start is to look at this excellent post by Scott Sanderson https://www.quantopian.com/posts/using-ta-lib-functions-in-pipeline.

You can instantiate the class with a window length just as you indicated. To reference that window_length value within a custom factor use 'self.window_length'. Something like this

 results = talib.EMA(vol[:, col_ix],  timeperiod=self.window_length)  

This is also demonstrated in Scotts post. Good luck.

Thanks Dan, that is really helpful.