Back to Community
Combining and Ranking Documentation Question

Hi there!

New to the forums here, and really enjoying getting up and running on Quantopian.

Not sure if this question is a fit for the forums or not, but here it is:

From the "Combining and Ranking" algorithm in the documentation, why was this factor chosen to rank securities:

# Combined factors to create new factors  
    sma_quotient = sma_short / sma_long  

What information does sma_quotient give you? Why would you rank on it? Or was it just arbitrarily chosen for the sake of example?

Here's some additional code for context:

    # Combined factors to create new factors  
    sma_quotient = sma_short / sma_long

    # Create and apply a screen to remove penny stocks  
    remove_penny_stocks = sma_short > 1.0

    sma_rank = sma_quotient.rank(mask=remove_penny_stocks)

    # Rank a factor using a mask to ignore the values we're  
    # filtering out by passing mask=remove_penny_stocks to rank.  
    pipe.add(sma_rank, 'sma_rank')

    longs = sma_rank.top(200, mask=remove_penny_stocks)  
    shorts = sma_rank.bottom(200, mask=remove_penny_stocks)

    pipe.add(longs, 'longs')  
    pipe.add(shorts, 'shorts')  

The rest of the code should be available in the backtest. Please let me know if you need more info!

Clone Algorithm
2
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
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import SimpleMovingAverage

def initialize(context):
    pipe = Pipeline()
    attach_pipeline(pipe, 'example')

    sma_short = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=30)
    sma_long = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=100)

    # Combined factors to create new factors
    sma_quotient = sma_short / sma_long

    # Create and apply a screen to remove penny stocks
    remove_penny_stocks = sma_short > 1.0

    sma_rank = sma_quotient.rank(mask=remove_penny_stocks)

    # Rank a factor using a mask to ignore the values we're
    # filtering out by passing mask=remove_penny_stocks to rank.
    pipe.add(sma_rank, 'sma_rank')

    longs = sma_rank.top(200, mask=remove_penny_stocks)
    shorts = sma_rank.bottom(200, mask=remove_penny_stocks)

    pipe.add(longs, 'longs')
    pipe.add(shorts, 'shorts')

    # Use multiple screens to narrow the universe
    pipe.set_screen(longs | shorts)

def before_trading_start(context, data):
    context.output = pipeline_output('example')

    context.longs = context.output[context.output.longs]
    context.shorts = context.output[context.output.shorts]

    context.security_list = context.shorts.index.union(context.longs.index)

    # Print the 5 securities with the lowest sma_rank.
    print "SHORT LIST"
    log.info("\n" + str(context.shorts.sort(['sma_rank'], ascending=True).head()))

    # Print the 5 securities with the highest sma_rank.
    print "LONG LIST"
    log.info("\n" + str(context.longs.sort(['sma_rank'], ascending=False).head()))
There was a runtime error.
6 responses

There are some video tutorials where the theory behind the strategy is explained some. I think sentdex explains this.

Hi Zachary,

Thanks for your reply! Yes, I manage a team of C# developers, and have several years of C# experience myself. Still learning python though, and quite enjoying it!

That said, I am interested in the financial reasoning behind the quotient. What does that quotient represent? At first glance a ratio of short moving average to long doesn't represent anything to me financially. Why would you rank securities based on this quotient? Could you point me to these videos?

Looking at a couple other lines of code:

longs = sma_rank.top(200, mask=remove_penny_stocks)  
shorts = sma_rank.bottom(200, mask=remove_penny_stocks)  

Here we have rankings of the top and bottom securities, based on that quotient, subtracting the penny stocks. I understand the "how?" in this situation, my question is "why?". Perhaps I'm digging too deep for the scenario, but I am curious as to the motivations behind using this factor to rank securities.

It is inspired from the Technical Analysis subject of the so called there PPO Indicator (Percentage Price Oscillator) which in plain English indicates how much (in percentage) 2 moving averages (one fast and the other slow) are different. So we have:

PPO = (sma_fast – sma_slow) / sma_slow = sma_fast / sma_slow – 1  

Because this PPO Indicator finally will be ranked then this rank will be remain unchanged if instead of

sma_fast / sma_slow – 1  

you put there just the

sma_fast / sma_slow  

without this “-1” at the end.

Also note please that this PPO indicator is a percentage version of the well-known in technical Analysis MACD indicator.

Hi Thanasis,

Thank you! That's exactly what I was after.

So it sounds like the motivation here is that the top/bottom 200 used in the code sample are the furthest from the slow mean, which implies they are more likely to mean revert in our trading window. Is this the correct conclusion?

Hi Ian,

Exactly. Or if you like to have the same algorithm not as "mean reversion" algorithm but as "momentum" algorithm simply change the lines:

longs = sma_rank.top(200, mask=remove_penny_stocks)  
shorts = sma_rank.bottom(200, mask=remove_penny_stocks)  

to the new lines:

longs = sma_rank.bottom(200, mask=remove_penny_stocks)  
shorts = sma_rank.top(200, mask=remove_penny_stocks)  

Ah! I was curious about that. I was reading about the PPO Indicator, and it is listed as a momentum indicator, so I was curious how that fit into the picture. Thanks!