Stock Universe Selection on Multiple Timeframes

S

This is my take on scheduled intraday universe selection, written in Python (LEAN). The attached code is not a tradable strategy, it’s a template for others to use in building their own strategies.

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


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.
     
  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, the fine selection method 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()


About the author

quantish
By quantish

quantish

Automate everything.