Back to Community
O'Shaugnessy "What works on wall street"

I just finished reading O'Shaughnessy's book. OK, more like I skimmed it.

He tests various value metrics and came to the conclusion that EV/EBITDA was the best. However, he made a composite metric: Value Composite 2, which supposedly outperforms EV/EBITDA and more consistently. He also describes a portfolio called "Trending Value" where he takes the top decile of VC2 and selects the top 25 stocks based on 12 month momentum.

First, here is VC2. Its returns outpaces pure ev/ebitda, which has returned about 800% in the same time period.

Sharpe ratio is much higher as well.

Clone Algorithm
633
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Backtest ID: 5580d5361ae62e0dea37bc9f
There was a runtime error.
22 responses

Here is the VC2 with momentum. In the book it's supposed to improve consistency. However, I found the results very disappointing. I couldn't exactly replicate his strategy because there are limits on stock universe, but I think I have a pretty close approximation here.
I rebalanced every month as that tends to improve returns. In the book, he uses 12 months.

Oh, the drawdowns were terrible so I added an exit to TLT. The backtest without TLT yields similar returns with higher volatility.

I'm starting to have doubts about this value+momentum business.

Clone Algorithm
633
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Backtest ID: 5580ccf5cdb7110dd6a4e7a2
There was a runtime error.

The custom chart does smoothing, a good thing, so on this one the actual value for the leverage spike of over 2.2 on 2008-07-01 can be seen by using the sliders to zoom in on it. (In the IDE the value/number would be displayed, just temporarily out of service here for awhile).

Or here's a simple bit of code some might find handy:

    if 'max_lvrg' not in context: context.max_lvrg = 0 # Or init this in initialize()  
    if context.account.leverage > context.max_lvrg:  
        context.max_lvrg = context.account.leverage  
        log.info('lvrg ' + str(context.max_lvrg))      # Log any new leverage high  

I guess there are various schools of thought about momentary margin, I tend to think that since over $2M was spent at any point, once the calculations are done with maxspent, the profit was really only around 260%, sad to say, since that's not too bad of a curve otherwise to be working with as a starting point, would be great if you can find a way to reduce that blip.

what is your leverage use in this strategy/algo, Mr. Wu?

The intention is to use zero leverage.

Here is a modified version of Gary's max leverage code. Instead of printing whenever a max_leverage has been reached, it will simply record it in the chart. It appears leverage increases towards the end to a max of 1.24 in 2015. Before 2015, the max leverage was 1.1

Leverage probably does not explain the out-performance of this strategy. In feb-march 2010, there is a blip, apparently caused by two stocks NCX and RYI. The current stocks with that ticker does not go back to 2010, leaving open the possibility that the blip may be an error in the price database.

Oops, forgot to attach the backtest

Clone Algorithm
633
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Backtest ID: 5588327bd7900412616b1ce5
There was a runtime error.

Interesting...I was curious because it seems that such a study would involve at least 3:1 leverage based on returns. I tried running the backtest with 10k initial margin and it produced 1400% ROC, which is very interesting, but obviously due to drawn downs. The bulk of the profits seem to start during the recession of 09 and continue to build immensely from that point forward - which makes me inclined to say it is leverage because of the bull market from 09-15. What is nice is that it does not use more than 1.02 leverage in such times, but i am curious if you have tried this strategy with 1) no penny stocks, and 2) adding the ability to short the security?

Shorting securities is too expensive to implement in real life. At least that's what I gather from the performance of past Quantopian contest winners according to Simon.

I put a filter for market cap larger than 250mil. I hope this is sufficient to filter out penny stocks.

i might raise that to 500mil to be safe. Either way, appears to do well as is haha. Pardon me for the immense questions, I'm just new to coding but have a lot of experience within the markets. Why does your algo skip the first few months of trading?

It doesn't skip the first few months, but it does skip the first month. This is because the algo only runs once a month on the first trading day of the month. The backtest starts near the start of January but not on the exact first day of the month. If you start the backtest right on new year, it should start running right away.

Need to filter out non us stocks and a few sectors.

There is an REIT that takes out 10+% of the entire portfolio at some point!

Low valuation staples only is a strategy that looks pretty stable

I thought Quantopian only includes US stocks. Or do you mean we want to eliminate ADRs? Is there a rationale for eliminating some sectors? which sectors should we filter out?

Also, which REIT and when does the portfolio holds them.

Thanks for looking into the algo in detail!

Yeah ADRs /OTC as they will often trade at low multiples indefinitely. Same with US listed Chinese stocks as everyone assumes they are a scam. I like to remove real estate + financials because I don't think the metrics like ev/ebitda are that relevant for valuation. Utilities companies often play lots of shenanigans with accounting figures.

Not sure which REIT as it was a night or two ago. You can click the gains page and drag the bar up or down to find quickly find outliers.

Not sure if consumer defensive is the same as staples.... but I changed a few numbers / this is defensive only, usa only and higher mcap

Clone Algorithm
147
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Backtest ID: 558a636f2b9c9b123f26e3e1
There was a runtime error.

going forward I wouldn't use TLT as the stress hedge, as it did so well during QE, it had a positive influence but the next dip will likely have increased rates. Maybe cash is a safer alternative? Or a basket with TLT, GLD,TIPS and some other things?

d36,
Why does your leverage creep up in 2012 and 2013?

Not sure!

I only adjusted filters and sma

has anyone tried implementing a short side ability for this algo?

HI all,

I am confused the schedule_function and transaction detail, in this algorithm have been set to rebalance monthly on the first day of the month at market open, but in transaction detail why have the transaction not on the first day of the month, and even in same day have multiple transaction on different time.
enter link description here

    schedule_function(rebalance,  
                      date_rule=date_rules.month_start(),  
                      time_rule=time_rules.market_open(minutes=30))  

That's a good question. I don't know why..

Does anyone know how to add a method for rolling 12 month backtest?

For example, I want to purchase a set of 20 stocks that meet the criteria in January, a set in February, a set in March, and so on. From there, I want to sell annually. Supposedly, this is supposed to smooth out the results.

Hi, Johnny,

I am trying to replicate your second code, but why do I get a different result if we just compare the same trading period?

Clone Algorithm
22
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Backtest ID: 589e26deb74994615e2ffd9f
There was a runtime error.