A recurring help topic in the forums is scheduling intraday universe selection, so I thought to share a template for how I've done this in the past, in the attached backtest, 

This is not a tradable strategy, it simply shows one approach to intraday stock universe selection. 

____________________________________

General Architecture
There are three universe selection phases: Coarse, Fine and Intraday (scheduled). In the Fine and Intraday selection, a SymbolData object holds each stock's indicators, which are seeded with historical data at the appropriate time. Once an asset meets criteria for all three phases, we open a position, and close it position once exit criteria is met. 

The Code
I’ve tried to modularize and comment the code so it's easy to follow, repurpose and replace the screening criteria with your own.

  1. Coarse Universe Selection
    Using LEAN’s standard ‘AddUniverse’ approach for coarse selection, select up to ‘X’ top liquid stocks that meet specified coarse criteria. For example: price > $50. 
     
  2. Fine universe Selection w/Indicators
    Using LEAN’s standard ‘AddUniverse’ approach for fine selection, select up to ‘Y’ stocks that meet specified criteria for Daily Screening: For example: Stock price is above 10 day EMA.

    Note: When the Fine universe selection routine is called, data isn't available for the symbols, so we call self.History() for each of the stocks (that passed coarse selection). The stocks that meet fine criteria will be stored for later use in the scheduled intraday routine. Alternatively, if we were not performing any further intraday filtering we could return these assets in a list at the end of the function, instead returning the blank list as we do now.
     
  3. Scheduled Intraday Universe Selection w/indicators
    At a scheduled time during the day, select stocks that meet intraday criteria. For example: positive 4 hour momentum. Select the top ‘Z’ stocks, ranked by momentum.
     
  4. Subscribe to Data for Screened Stocks
    When a stock passes all screening, we ‘add’ the security to the algorithm after the intraday screening. This subscribes to the data feed for the symbol, which we will need to calculate indicator values for our exit. 

    Note: In a scenario where we don’t need intraday filtering, then our fine selection function will invoke the adding of securities, by returning a list of symbols (instead of a blank list) to the LEAN framework.
     
  5. Open Positions for Screened Stocks
    Adding the security invokes the onSecuritiesChanged handler, where we queue buy orders in a ‘queuedPositions’ list. This queue is processed (ie: positions are opened) in the next call to OnData, when data is available.
     
  6. Close positions for stocks when exit condition is met
    Exit when stock price is below the EMA. Or, optionally, exit at End of day , if the useEoDExit flag is set.
     

Customization
To change entry  logic for your own needs, modify these methods:

## In main.py:
GetDailyScreenedStocks(stocksToScreen)
GetIntraDayScreenedStocks(stocksToScreen)

## In SymbolData.py:
DailyScreeningCriteriaMet()
IntradayScreeningCriteriaMet()

 

Known Issue
For some reason the first set of positions take place 30 minutes later than expected. I haven't had the time to investigate it.

____________________________________
 

Feel free to re-use this, customize it, make it better and re-share.

 

 

Author