Advertisement
cjc5013

Relative Momentum Strategy

Oct 7th, 2019
416
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.81 KB | None | 0 0
  1. '''
  2. Relative Momentum Strategy Rules:
  3.  
  4. 1) We use the "Q500US" universe here - 500 most liquid US stocks.  
  5.   Description of the Q500US universe from the docs:
  6.   "Constituents are chosen at the start of each calendar month by selecting the top 500 "tradeable" stocks by         200-day average dollar volume, capped at 30% of equities allocated to any single sector"
  7.  
  8. 2) Every month, we buy the top 20 stocks with the best momentum.  This is measure by the stocks
  9.   with the strongest 5 month (105 trading day) total return.
  10.  
  11. 3) We employ a trend following regime filter, only taking new entries if the ETF SPY's current price
  12.   Is greater than its 200 day moving average
  13.  
  14. 4) This algo rebalances once a month, selling any stocks we own that are no longer top 20 based on momentum
  15.   and replacing those stocks with the current top 20 based on momentum (if our TF regime filter is passed)
  16.  
  17. 5) We use equal weights here - with 20 positions that menas 5% in each stock
  18.  
  19. '''
  20.  
  21.  
  22.  
  23. import quantopian.algorithm as algo
  24. from quantopian.pipeline import Pipeline
  25. from quantopian.pipeline.data.builtin import USEquityPricing
  26. from quantopian.pipeline.filters import Q500US
  27.  
  28.  
  29. def initialize(context):
  30.     #Schedule our rebalance function to run once a month
  31.     schedule_function(rebalance , date_rules.month_end(), time_rules.market_close(minutes=10))
  32.    
  33.     #This code simply "attaches" our pipeline to this algo. This code never changes
  34.     algo.attach_pipeline(make_pipeline(), 'pipeline')    
  35.    
  36.     #Grab SPY for the Trend Following Filter
  37.     context.spy = sid(8554)
  38.    
  39. def make_pipeline():
  40.  
  41.     # Base universe set to the Q500US
  42.     universe = Q500US()
  43.  
  44.     # This is pipeline code
  45.     # All we are doing is making an object, 'pipe' containing the current 500 most liquid US stocks
  46.     pipe = Pipeline(screen=universe)
  47.     return pipe
  48.  
  49. def before_trading_start(context, data):
  50.    
  51.     # Called every day before market open, this grabs the output from our function "make_pipeline"    
  52.     context.output = algo.pipeline_output('pipeline')
  53.    
  54.     # Here we grab in "index" of our pipeline
  55.     # This makes a list of securities "context.security_list" containing 500 stocks
  56.     context.security_list = context.output.index
  57.        
  58. def rebalance(context, data):
  59.     #This code is for our Trend Following Regime Filter:
  60.     #We get the history for SPY, current price for SPY and calculates the moving average
  61.     spy_history = data.history(context.spy,"close", 200, "1d")
  62.     spy_MA = spy_history.mean()    
  63.     spy_current = data.current(context.spy,'price')
  64.    
  65.     #This code grabs the pricing history for all 500 stocks in our universe
  66.     #This DataFrame, "history", contains 253 rows (days) and 500 columns (one for each stock)
  67.     history = data.history(context.security_list,"close", 253, "1d")
  68.    
  69.     #This grabs the current momentum for each stock
  70.     #Default is 105 days (5 months) lookback
  71.     #We use .iloc[-1] to get the last value (most recent momentum measure)
  72.     current_momentum = history.pct_change(105).iloc[-1]  
  73.    
  74.     #Here we use "nlargest" to grab the 20 stocks with the best momentum
  75.     top_n_stock = current_momentum.nlargest(20)
  76.    
  77.     #Loop through all stocks in our portfolio, selling any that arent still in the top 20 based on momentum
  78.     for security in context.portfolio.positions:
  79.         if security not in top_n_stock:
  80.             order_target_percent(security, 0.0)
  81.    
  82.     #Here we buy new stocks
  83.     #We first check if the current price of SPY is abve its 200 day MA
  84.     #We then loop through our "top_n_stock" list (20 with best momentum) and buy each we 5% of our portfolio
  85.     if spy_current > spy_MA:
  86.         for x in top_n_stock.index:
  87.             if x not in context.portfolio.positions:
  88.                 order_target_percent(x , 0.05)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement