Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Patrick O'Shaughnessy's "Millennial Money" Value Investing Algorithm #Fundamentals

Hi,

I'm implementing the Algorithm described in the book "Millennial Money" by Patrick O'Shaughnessy.
The Checklist version is ready now and in the next couple of weeks, I'll implement the ranking version.

The threshold values are slightly different in comparison to the book and the the positions are updated quarterly.

  • Stakeholder yield < 5%. Stakeholder yield = Cash from financing 12m / Market Cap Q1
  • ROIC > 20%
    ROIC = operating_income / (invested_capital - cash)
  • CFO > Net Income (Earnings Quality)
  • EV/FCF < 15 (Value)
  • 6M Relative Strength top three-quarters of the market.
    6M Relative Strength = 6M Stock Total Return / 6M Total Return S&P500 (Momentum)
13 responses

Here is the code and the backtest results: From 2002-01-03 to 2014-12-28 6417.8% returns and 49% max drawndown.

Some tools and changes to consider. Try to avoid negative cash.

Hey, Python/SQL newbie here, so this might be a silly question regarding your code, but when I'm looking at the do_screening method

.filter(fundamentals.cash_flow_statement.operating_cash_flow > fundamentals.income_statement.net_income)
        .filter((fundamentals.valuation.enterprise_value / fundamentals.cash_flow_statement.free_cash_flow) < 15)  
        .limit(context.max_num_stocks)  
    )  

the .limit query modifier appears to be for the purpose of limiting the amount of stocks in your portfolio to the maximum defined in the initalize method.

However, I don't understand what the .limit behavior is in the absence of an order_by modifier. IE, I assume there is an inherent ordering off of which the max_num_stocks cuts off of, but it's unclear to me whether that's based on the data order in Morningstar's database, or an order shift based on how the queries are run. Can you tell me how this ends up working int he context of the algorithm or where to look in the documentation?

Thanks.

Hi Don,

you're right, .order_by is essential if you use the .limit clause. The code and backtest above are quite old. I've completely redesigned my implementation of the Millennial Money Algorithm und maybe I'll publish is in the next time.

Please be aware that this strategy is almost 2000% laverage.

I just took a crack at making a simple hedged portfolio inspired by this algo. (I used the algo shared above by @garyha as the foundation). I simply short an equivalent amount of SPY (e.g. dollar-neutralize the portfolio) at each quarterly rebalance period. It does quite a good job of bringing the beta down to nearly 0 over the whole backtest as well as reducing the Max Drawdown from 47% to 25% (Yes, at the expense of overall total return).

As well, I also added a code snippet to clean up all the delisted/'dead' positions that seem to accumulate in the portfolio over time, which really affected how orders were placed/$ allocated in the latter years of the backtest (I applied the methodology discussed in this thread: https://www.quantopian.com/posts/why-does-the-number-of-positions-and-leverage-creep-up-for-this-algorithm ).

Just wanted to share it here, as well as its accompanying tearsheet.

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.

The tearsheet in the Q Research Environment

Hi can someone please convert this to the quantopian v2 syntax? I am not advanced enough to make the necessary changes yet.

Hi.

How did you calculate -0.6745? You said that it is an approximation for the top three-quarters of the market, but that doesnt make much sense to me.

Thanks

Does anyone have an update on this for 2017? Has performance still been consistent with the original?

This algo isn't exactly as the original because of the lack of historical annual fundamental data on Quantopian. It also uses a lot of leverage and this is bad. It was one of my first algo on Q. I'm going to reimplement it correctly not yet Q allows historical fundamentals with the Pipeline API.

It does

Following up here, has anybody updated this to work with the latest version of Quantopian syntax?