Back to Community
How to rebalance every month based on a 10 months simple moving average rule ?

Hi, I'm just getting started on quantopian.
I would like to test a simple strategy based on a monthly timeframe :

At the beginning of each month :
• If the SPY is >= to it's 10 months simple moving average we buy it.

• Else we exit all of our positions

I don't manage to get the monthly SMA(10) to test it...
How can I manage this ?

Thank you

4 responses

Here is a sample algorithm which does something close to what you are asking. See if it makes sense.

Good luck!

Clone Algorithm
26
Loading...
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
'''
Simple algorithm to trade a fixed set of stocks based upon certain rules.
The data is defined in the pipeline definition.
The selection logic is performed in the code.
'''

# The following imports need to included when using Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline

# Import all the built in Quantopian filters and factors (just in case)
import quantopian.pipeline.filters as Filters
import quantopian.pipeline.factors as Factors

# Import Pandas and Numpy (just in case we want to use their functionality)
import pandas as pd
import numpy as np

# Import any specialiazed packages here (eg scipy.optimize or scipy.stats)
pass

# Import any needed datasets
from quantopian.pipeline.data.builtin import USEquityPricing


# Set any 'constants' you will be using
# A list of securities and equally weight each one
MY_STOCKS = symbols('SPY')
WEIGHT = 1.0 / len(MY_STOCKS)

def initialize(context):
    """
    Called once at the start of the algorithm.
    """   
    
    # Set commission model or omit and the default Q models will be used
    # set_commission(commission.PerShare(cost=0.0, min_trade_cost=0.0))
    # set_slippage(slippage.FixedSlippage(spread=0))
    
    # Attach the pipeline defined in my_pipe so we have data to use
    attach_pipeline(pipe_definition(context), name='my_data')
  
    # Schedule when to trade.Here it's the beginning of each month.
    schedule_function(trade, date_rules.month_start(), time_rules.market_open())

    # Schedule when to record any tracking data
    schedule_function(record_vars, date_rules.every_day(), time_rules.market_close())

         
def pipe_definition(context):
    '''
    Here is where the pipline definition is set.
    Specifically it defines which collumns appear in the resulting dataframe.
    Think of its defining a big spreadsheet (really a dataframe) of data.
    Don't think of the pipeline as doing any logic. That's later in the algo.
    '''
    
    # Create a universe filter which defines our baseline set of securities
    # If no filter is used then ALL assets in the Q database will potentially be returned
    # This is not what one typically wants because 
    #    1) it includes a mix of ETFs and stocks
    #    2) it includes very low liquid and 'penny' stocks
    #
    # This filter can also be used as a mask in factors to potentially speed up some calcs
    # Just want a single stock though so use the StaticAssets filter
    universe = Filters.StaticAssets(MY_STOCKS)
    
    # Create any basic data factors that your logic will use.
    # This is done by simply using the 'latest' method on a datacolumn object.
    # Just ensure the dataset is imported first.
    close_price = USEquityPricing.close.latest

    # Create any built in factors you want to use (in this case Returns). 
    # Hre we want the SMA over 10 months. Thi sis about 10 x 20 days/mo = 200 days.
    sma_200 = Factors.SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=200, mask=universe)   
    
    # Create any built in filters you want to use.
    pass

    # Create any filters based upon factors defined above.
    # These are easily made with the built in methods such as '.top' etc applied to a factor
    pass

    # Define the columns and any screen which we want our pipeline to return
    # This becomes the data that our algorithm will use to make trading decisions
    return Pipeline(
            columns = {
            'close_price' : close_price,
            'sma_200' : sma_200,
            },
            screen = universe,
            )
    
 
def before_trading_start(context, data):
    '''
    Run pipeline_output to get the latest data for each security.
    The data is returned in a 2D pandas dataframe. Rows are the security objects.
    Columns are what was defined in the pipeline definition.
    '''
    
    # Get a dataframe of our pipe data. Placed in the context object so it's available
    # to other functions and methods (quasi global)
    context.output = pipeline_output('my_data')
       
   
def trade(context, data):
    '''
    This is a scheduled function to execute all buys and sells
    '''
    # Note that no logic was done in the pipeline. Just fetched the data.
    # Here is where you can filter, sort, and do whatever you want with that data.
    # Anything that could have been done in pipeline can be done with the
    # dataframe that it returns. Use the pandas methods on context.output.
    
    open_these = context.output.query('close_price >= sma_200').index.tolist()
    for stock in open_these:
        if data.can_trade(stock):
            order_target_percent(stock, WEIGHT)
    
    close_these = context.output.query('close_price < sma_200').index.tolist()
    for stock in close_these:
        if data.can_trade(stock):
            order_target_percent(stock, 0)

                  

def record_vars(context, data):
    """
    Plot variables at the end of each day.
    """
    
    # Record the number of positions held each day
    record(leverage=context.account.leverage,
           positions=len(context.portfolio.positions))
There was a runtime error.

Thank you very much Dan.
So we must use a daily timeframe ?
We cannot change the timeframe to another basis like weekly or monthly ?

olivier,

You may get any time frame from Quantopian data.history() using .resample()
Hope this simple code will help you.

def initialize(context):  
    schedule_function(trade, date_rules.month_start(), time_rules.market_open(minutes = 65))  

def trade(context, data):  
    #---------------------------------------------  
    stock, TimeFrame, ma = symbol('SPY'), '1M', 10  
    #---------------------------------------------  
    bars = ma*21  
    if get_open_orders(): return 

    curr_price = data.current(stock, 'price')  
    daily_prices = data.history(stock, 'price',  bars, '1d')  
    monthly_prices = daily_prices.resample(TimeFrame).last()  
    print monthly_prices  
    mavg = monthly_prices.mean() 

    if data.can_trade(stock):  
        if curr_price >= mavg:  
            order_target_percent(stock, 1.0)  
        else:  
            order_target_percent(stock, 0)

    record(price = curr_price, mavg = mavg)  

Thank you very much Vladimir.