Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Problem with Custom Factor

Hi guys, i am new to Quantopian and having a little trouble creating a custom factor. The factor should basically just return a value of 1 if the moving average of the returns is greater than 0.001 and a value of -1 otherwise.

When running the notebook i get an error message saying:
NonPipelineInputs: Unexpected input types in str. Inputs to Pipeline expressions must be Filters, Factors, Classifiers, or BoundColumns.
Got the following type(s) instead: []

I would appreciate your help!

3 responses

First off welcome to Quantopian.

When writing a custom factor it's important to understand the inputs are numpy arrays. There is a column for each asset which passes the 'mask' filter (if any). There is a row for each trading day of data. As an example, consider the following custom factor

class Sample(CustomFactor):  
    inputs=[Returns(window_length=2)]  
    window_length = 30  
    def compute(self, today, asset_ids, out, returns):  
        out[:] = returns

my_sample = Sample(mask=Q500US())

The input parameter 'returns' will be a numpy array with ~500 columns (one for each asset in the Q500US()) and 30 rows (one row for each of the previous 30 trading days - since the window_length is 30). The most recent trading day is the last row (ie index -1) and the data for 30 days ago would be the first row (ie index 0). There's more information in the docs https://www.quantopian.com/docs/api-reference/pipeline-api-reference#quantopian.pipeline.CustomFactor.

So, the problem is with the statement

        rolling_mean_returns = SimpleMovingAverage(  
        inputs=[returns],  
        window_length=20  
        )

The SimpleMovingAverage factor expects a BoundColumn or factor as an input and NOT a numpy array. The input parameter 'returns' is a numpy array. Generally, one doesn't use built in factors, such as SimpleMovingAverage, inside a compute function simply because factors don't accept numpy arrays as parameters. Use numpy, pandas, or other methods instead.

However, in this case, one can use SimpleMovingAverage as an input like this.

class Average_Returns_Signal(CustomFactor):  
    inputs=[SimpleMovingAverage(inputs=[Returns(window_length=2).log1p()], window_length=20)]  
    window_length = 1  
    def compute(self, today, asset_ids, out, returns):  
        out[:] = np.sign(returns - 0.001)  

The input parameter 'returns' will be a numpy array with values which are the 20 day average of 2 day returns. One doesn't really care about previous average values, so a window_length of 1 will return just the latest 20 day averages.

Using the np.sign method is a clever approach to outputting a -1 or 1. I believe you need to subtract, rather than add, .001 to accomplish what you want. Additionally, one cannot really average arithmetic returns (eg 10% and -10% do not average to 0%). Use log returns instead. There is a built in method to convert to log returns log1p() (see https://www.quantopian.com/docs/api-reference/pipeline-api-reference#zipline.pipeline.Factor.log1p).

Attached is a notebook which shows this custom factor.

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 a lot for your time and the perfectly clear explanation!

Oh and just as a quick add on, i meant -0.001 in the description of my problem.