Back to Community
Having trouble getting started

Im brand new to the world of Quantopian and im still getting my feet wet with programming my first algo. Im trying to create an algo that is long only and buys US stocks which have a current price above its 50day simple moving average and have an ROE/PE ratio greater than 1.5. If the current price moves below the 50 then the stock gets sold. I would like to start with something simple like this and then continue to add other technicals such as Williams %R. I tried looking through some of the documentation in learn but couldn't figure out to call things like ROE/PE or W%. Thanks a bunch for any help!

9 responses

How far have you gotten?

I figured out how to get the ROE and PE ratio using custom factors. As for the moving average, I am not sure how to do this. If you figure it out please let me know. I've attached the algorithm below, which adds a column to the pipeline for the ROE and PE.

Clone Algorithm
3
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 import CustomFactor
from quantopian.pipeline.data import morningstar

class PE(CustomFactor):
    inputs = (USEquityPricing.close, morningstar.valuation.shares_outstanding, morningstar.income_statement.total_revenue)
    window_length = 1
    
    def compute(self, today, asset, out, close, shares, revenue):
        earnings_per_share = revenue[-1] / shares[-1]
        pe = close[-1] / earnings_per_share
        out[:] = pe
        
class ROE(CustomFactor):
    inputs = (morningstar.income_statement.net_income, morningstar.balance_sheet.stockholders_equity)
    window_length = 1
    
    def compute(self, today, asset, out, ni, se):
        roe = ni / se * 100
        out[:] = roe
 
def initialize(context):
    """
    Called once at the start of the algorithm.
    """   
    # Rebalance every day, 1 hour after market open.
    schedule_function(rebalance, date_rules.every_day(), time_rules.market_open(hours=1))
     
    # Create our dynamic stock selector.
    attach_pipeline(pipeline(context), 'pipeline')
         
def pipeline(context):
    
    # Create our pipeline
    pipe = Pipeline()
    
    # Add PE to pipeline
    price_earnings = PE()
    pipe.add(price_earnings, 'PE')
    
    # Add ROE to pipeline
    return_on_equity = ROE()
    pipe.add(return_on_equity, 'ROE')
    
    # Adding filters to get rid of NaN and only get positive ROE
    pe_filter = (price_earnings > 0)
    roe_filter = (return_on_equity > 0)
    
    pipe.set_screen(pe_filter & roe_filter)
    
    return pipe
 
def before_trading_start(context, data):
    """
    Called every day before market open.
    """
    context.output = pipeline_output('pipeline')
    
    # Print out our pipeline
    log.info(context.output)
    
 
def rebalance(context,data):
    """
    Execute orders according to our schedule_function() timing. 
    """
    
    # Make your ordering of securities here.
    
    pass
There was a runtime error.

SimpleMovingAverage is one of the built-in factors. The documentation covers how to use it pretty thoroughly.

Ahhhh sorry for the delay in responding here! I just finished moving. What a painful process...

So I did a bit of work on this, still have ways to go but heres what I got so far. Jeep, I will include the moving average in my next algo post. Now I don't know how to get the log to print out all the stocks that qualify for the criteria I have set. Currently if you run it, the logs will only display like the top 20 or something similar. I can tell there are more results because the log has ... at the end but just can't figure our how to display full results. As I continue developing this I will post back. Thanks for any help on this.

Heres the latest I have... Im totally new at this (python and quantopian) so progress has been slow but steady.

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.data import morningstar

def initialize(context):  
    attach_pipeline(my_pipeline(context), 'my_pipeline')  
def my_pipeline(context):  
    return Pipeline(  
        columns={  
            'close': USEquityPricing.close.latest,
            'roe'  : morningstar.operation_ratios.roe.latest,
            'pe' : morningstar.valuation_ratios.pe_ratio.latest,
            'mkt_cap' : morningstar.valuation.market_cap.latest,
            'roe_pe' : morningstar.operation_ratios.roe.latest / morningstar.valuation_ratios.pe_ratio.latest,
             
        },  
        screen=(morningstar.earnings_ratios.diluted_eps_growth.latest > 7 and USEquityPricing.close.latest > 5)  
    )  

def before_trading_start(context, data):  
    context.data = pipeline_output('my_pipeline')  
    log.info(context.data)  
There was a runtime error.

There's a limit for printed information using log but it does contain a lot more. Are there any specific reason for printing it all? The context.data does contain all the securities that passes the screen.

I need to see the whole list to compare with what I am doing manually. I actually run a strategy manually using Bloomberg so I need to compare the results that I get from quantopian with what I am getting from the Bloomberg terminal. Any idea on how to get this accomplished?

I don't think that is possible since there's a limit of messages using the print or log.info commands.

Adding the piece of code below will loop through every security you've got and print it, but since the limit is exceeded it will only show you a few. Maybe you could do a ranking of the securities and then print out the 10 best ranked or something.

for stock in context.data.index:  
        log.info(stock)  

Thanks Jeppe. I was thinking, what would happen if I told it to buy all the stock that populate in context.data after my filters are applied and then opened the backtest in research to view all my transactions? Do you think that it would print out all the data or just the stock symbols that it bought? I haven't used that research feature yet. As I continue to build out the algo, the end result should give me a portfolio of a maximum of 20 stocks which I hope is under the log limit. I also added the 50 day moving average.

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.data import morningstar
from quantopian.pipeline.factors import SimpleMovingAverage


def initialize(context):  
    attach_pipeline(my_pipeline(context), 'my_pipeline')  
def my_pipeline(context):  
    return Pipeline(  
        columns={  
            'close': USEquityPricing.close.latest,
            'roe'  : morningstar.operation_ratios.roe.latest,
            'pe' : morningstar.valuation_ratios.pe_ratio.latest,
            'mkt_cap' : morningstar.valuation.market_cap.latest,
            'roe_pe' : morningstar.operation_ratios.roe.latest / morningstar.valuation_ratios.pe_ratio.latest,
            '50d' : SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=50),  
        },  
        screen=(morningstar.earnings_ratios.diluted_eps_growth.latest > 7 and USEquityPricing.close.latest > 5 and USEquityPricing.close.latest > SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=50))  
    )  

def before_trading_start(context, data):  
    context.data = pipeline_output('my_pipeline')  
    log.info(context.data)  
    
    
#062816 need to implement filter to remove N/As
There was a runtime error.

My next steps are to figure out a way for my filter to select only those stock that closed above their 50d moving average. I should be posting that here soon as I don't think it will be complicated. The complicated part is now I need to incorporate Williams%R and a few other technical indicators. I will start exploring that part of the algo today. Oh yea and as you can see in the code, I also need to weed out those that display N/A for data.