Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Stock Screener for Value Investing

Hi Q Community,

I just joined Quantopian and am writing my first algorithm. Now, before I get into more complex algorithms (love statistics yey :) I want to code my own stock screener. It's to return a condensed list of stocks that one could evaluate by hand later on. It's supposed to do pretty much the same as the common ones from Yahoo! Finance etc., but obviously you can decide much more flexibly what to search for. Also I am not overly confident about the quality of data behind those free screeners on the Internet ...

So the screener saves all the fundamentals and prices for specific dates. Note that I've put this into a new order - I am not saving data for every single day and then pick out the dates I need, because this uses too much capacity. Instead, I decide (within initialize()) on which days to save data.

However, I am having difficulties with my filtering - it just filters out every stock. The established 'requirements' are rather loose, so the screener should find stocks.

Maybe some of the more experienced community members can take a look at this. Would be much appreciated.

Thanks
Toby

Edit: I found out that the screener is indeed finding stocks - but it's just Apple. I've created a context.stocks list with only Apple in, it basically to "shut up" the error that results from having no sids in your universe. Not really surprising, because I can only determine my universe on the last day of the backtest (the day I filter my fundamentals - the days before I am just saving the fundamentals for every stock there is in the Morningstar database). Is there a way to go around this? I haven't found a way yet. Actually, I don't want to set a universe at all, I just want to save the data until the last day in order to analyse it then. But I get an error either way - either for having to many stocks in my universe or none at all.

7 responses

Hi Toby,

You have the fundamental data with your unfiltered query with get_fundamentals()

But we restrict the amount of pricing data we provide in handle_data() to 200 securities currently. That's the purpose of the update_universe() in before_trading_start(). You screen for stocks there and then update your universe to focus on the stocks you want to trade in handle_data() using update_universe(). update_universe() is one way to dynamically set your trade-able universe. You're setting your trade-able universe manually at the top, with your line 11:

    context.stocks = [sid(24)]  

That's why you're only getting data for Apple (Apple is sid 24)

You're making calls like data[stock].price that rely on pricing data and the stock being a part of your universe.

Hope that clears things up.

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.

Hi Josh,

thanks for your reply. Is there any way to get pricing data for ALL stocks? Because that was the reason I shifted my filtering from before_trading_start() to handle_data(). I want to save pricing data for all stocks in order to use it for filtering at the end of the backtest.

You said pricing data in handle_data() is restricted to 200 securities currently. Is there a way to get pricing data for all securities via before_trading_start() ?

One more point: Morningstar does offer a fundamentals value 'pe_ratio'. I am not sure what type of EPS the denominator for that ratio is, but you could get the price over the fundamentals by multiplying EPS with the P/E. However, the question remains whether this price is a point-in-time or average price and if it is an average, over what period.

Hi Tobias,

You've hit a use case we're not supporting very well right now, but we're working on solving it from multiple angles.

The optimum place for solving this problem is in our research environment. Research provides access to pricing data, using a hosted iPython platform. All entrants to the Quantopian Open will get access to the tool (it's currently in beta). We're actively working on adding fundamental data to Research in the coming weeks. Since you're less interested in creating a trading algorithm, research seems like the right place for you to do this screening work.

Likewise, we're seeing more of a need for pricing data in before_trading_start() for screening purposes for trading algos (backtest and otherwise). But a solution to this part of the problem is probably farther out.

I now calculate my prices as a function of the fundamental pe_ratio multiplied by the sum of the previous 4 quarters diluted_eps. The problem here is, I get a whole slew of NaNs when doing so, and I am not sure why. Can it be possible that the database is missing so much data or am I "creating" these NaNs through a wrong code? Here is my current status quo:

Tobias,

One thing that we did in our initial implementation of fundamentals for the backtester is that we constrained the scope to metrics just in USD.

If the data is provided in non-USD currency, we filter out the value. For diluted_eps, I suspect we have lots NaNs because of this (eye balling the tickers like BT, ORAN, etc.

Hi Josh,

does this apply only to a number of metrics? Because I don't see why a stock would have a non-USD currency for diluted_eps and USD for, say, basic_eps. After filtering out all NaNs I get ~800 stocks which seems a bit unreasonable (before filtering NaNs out, it's ~4,600 stocks). So effectively, I can really only work with about 800 stocks.

Hi Tobias,

Not sure how you're getting to only 800 stocks with basc_eps populated. I get about 4500 stocks with a value for basis_eps and about 500 without.

Of the 500 that don't have basic_eps, 250 are ADR. Presumably those ADRs are reporting their earnings in non-USD
The other ~250, I examined 10 of their raw values for basic_eps (i.e. what Morningstar directly provides us) and of those ten, 5 simply did not have any values for this metric. This is certainly possible, depending on the type of stock it is. The other 5 had non USD currencies for their EPS as well (3 Canadian, 2 Chinese Yuan).

We definitely have handling non-USD currencies on our roadmap.

Let me know if I am misunderstanding your situation in terms of only getting to 800 stocks with valid data.