Overall Statistics
import numpy as np
import pandas as pd


class MyAlgo(QCAlgorithm):
    
    def __init__(self):
    
    # Number of stocks to pass filtering process
        self.num_filter = 2
        
    
    def Initialize(self):

        self.SetCash(1000000)
        # Start and end dates for the backtest.
        self.SetStartDate(2015,1,1)
        self.SetEndDate(2015,5,1)
        
        
        
        self.spy = self.AddEquity("SPY")

        self.security_list = ["JPM", "BRK.B","BAC", "WFC", "C", "GS", "USB",
        "MS", "PNC", "AXP", "BLK","SCHW", "CB", "BK","CME","AIG","MET","SPGI","COF"]

        for i in range(len(self.security_list)):
            self.AddEquity(self.security_list[i],Resolution.Minute)
        
        # Schedule the rebalance function to execute at the begining of each month
        self.Schedule.On(self.DateRules.EveryDay("SPY"), 
        self.TimeRules.AfterMarketOpen("SPY",30), 
        Action(self.rebalance))
    
    
    
    def OnData(self, data):
        pass


    def rebalance(self):

        # ---------------------------------------------------------------
        # Stocks History               ----------------------------------
        # ---------------------------------------------------------------
        
        history = self.History(self.security_list, 6, Resolution.Daily)
        price_history = history['close'].unstack(level=0)
        
        # ---------------------------------------------------------------
        # Pct Change    -------------------------------------------------
        # ---------------------------------------------------------------
        # Raw DF 
        d1 = price_history.values
        d2 = price_history.columns
        df1 = pd.DataFrame(d1, columns = d2)
        df1 = df1.dropna()
        
        pct_change_df1 = df1.pct_change(periods=5).iloc[-1]
        
        # Sorting
        rank_df1 = pct_change_df1.rank(ascending = False)
        sort_df1 = rank_df1.sort_values(ascending = True)
        sort_bottom_df1 = rank_df1.sort_values(ascending = False)
        #self.Log('\n' + 'Sorted :' + '\n' + str(sort_df1) + '\n'+str(sort_bottom_df1)+'\n')
        
        # lists
        top_list = sort_df1[:self.num_filter].index.tolist()
        bottom_list = sort_bottom_df1[:self.num_filter].index.tolist()
        total_list = top_list + bottom_list
        
        weight = 0.9/self.num_filter
        
        
        # Mean-Reversion   --------------------------------------------
        for i in self.security_list:
            if i not in total_list:
                self.Liquidate(i)
            
            if i in top_list:
                self.SetHoldings(i, -weight)
                
            if i in bottom_list:
                self.SetHoldings(i, weight) 
        
        
        invested = [ x.Symbol.Value for x in self.Portfolio.Values if x.Invested ]
        self.Log("invested: " + str(invested))