Overall Statistics
Total Trades
5
Average Win
24.80%
Average Loss
-0.11%
Compounding Annual Return
24.924%
Drawdown
28.300%
Expectancy
108.794
Net Profit
32.048%
Sharpe Ratio
0.839
Probabilistic Sharpe Ratio
37.746%
Loss Rate
50%
Win Rate
50%
Profit-Loss Ratio
218.59
Alpha
0.228
Beta
-0.484
Annual Standard Deviation
0.238
Annual Variance
0.057
Information Ratio
0.363
Tracking Error
0.393
Treynor Ratio
-0.413
Total Fees
$37.17
Estimated Strategy Capacity
$14000000.00
Lowest Capacity Asset
TMF UBTUG7D0B7TX
# g score investing updated
from QuantConnect.Python import PythonQuandl
import numpy as np
import pandas as pd
import scipy as sc
from datetime import timedelta
from QuantConnect.Data.UniverseSelection import * 
from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel

from AlgorithmImports import *
import statistics as stat
from collections import deque

class DynamicCalibratedGearbox(QCAlgorithm):

    def Initialize(self):        
        self.FinSci_ROA_key = 'FINSCI_ROA'
        self.Energy_ROA_key = 'ENERGY_ROA'
        self.SetStartDate(2019, 1, 1)  
        self.SetEndDate(2022, 6, 24)        
        self.SetCash(100000)        
        #self.SetBrokerageModel(AlphaStreamsBrokerageModel())
        #self.SetAlpha(ConstantAlphaModel(InsightType.Price, InsightDirection.Up, timedelta(days=31)))
        #self.SetExecution(ImmediateExecutionModel())
        #self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel(lambda time:None))        
        #self.AddUniverseSelection(FineFundamentalUniverseSelectionModel(self.CoarseFilter, self.FineFilter))
        self.UniverseSettings.Resolution = Resolution.Daily        
        self.curr_month = -1
        self.FinSci_ROA = {}  
        self.energy_ROA = {}         
        self.symbols = None           
        self.quarters = 0    
        self.SetWarmUp(756, Resolution.Daily)
        
        #KEI
        quandl_symbol = "OECD/KEI_LOLITOAA_OECDE_ST_M"
        self.kei = self.AddData(NasdaqDataLink, quandl_symbol, Resolution.Daily).Symbol
        self.init = True
        self.sma = self.SMA(self.kei, 1)
        self.mom = self.MOMP(self.kei, 2)

        self.XLFsector_symbolDataBySymbol = {}
        self.XLEsector_symbolDataBySymbol = {}
        self.XLBsector_symbolDataBySymbol = {}
        self.XLIsector_symbolDataBySymbol = {}
        self.XLYsector_symbolDataBySymbol = {}
        self.XLPsector_symbolDataBySymbol = {}
        self.XLUsector_symbolDataBySymbol = {}
        self.XLKsector_symbolDataBySymbol = {}
        self.XLVsector_symbolDataBySymbol = {}
        self.XLCsector_symbolDataBySymbol = {}

        self.XLEstocks = [x.Value for x in self.energy_ROA]
        self.XLFstocks = []
        self.XLBstocks = []
        self.XLIstocks = []
        self.XLYstocks = []
        self.XLPstocks = []
        self.XLUstocks = []
        self.XLKstocks = []
        self.XLVstocks = []
        self.XLCstocks = []

        self.trade = True
        self.stateData = { }

        self.SPY = self.AddEquity('SPY', Resolution.Daily).Symbol
        self.stock = self.AddEquity('QQQ', Resolution.Hour).Symbol
        self.bond = self.AddEquity('TMF', Resolution.Hour).Symbol
        self.vix = self.AddEquity('VIX', Resolution.Minute).Symbol

        self.XLF = self.AddEquity('XLF', Resolution.Hour).Symbol
        self.XLE = self.AddEquity('XLE', Resolution.Hour).Symbol
        self.XLB = self.AddEquity('XLB', Resolution.Hour).Symbol
        self.XLI = self.AddEquity('XLI', Resolution.Hour).Symbol
        self.XLY = self.AddEquity('XLY', Resolution.Hour).Symbol
        self.XLP = self.AddEquity('XLP', Resolution.Hour).Symbol
        self.XLU = self.AddEquity('XLU', Resolution.Hour).Symbol
        self.XLK = self.AddEquity('XLK', Resolution.Hour).Symbol
        self.XLV = self.AddEquity('XLV', Resolution.Hour).Symbol
        self.XLC = self.AddEquity('XLC', Resolution.Hour).Symbol
       
       #Shorts
        self.SQQQ = self.AddEquity('SQQQ', Resolution.Daily).Symbol
       #self.manually_selected = [self.SPY, self.stock, self.bond, self.vix, self.XLF, self.XLE, self.XLB, self.XLI, self.XLY, self.XLP, self.XLU, self.XLK, self.XLV, self.XLC]
        self.manually_selected = []
       
   # Stock Selector
        #self.UniverseSettings.Resolution = Resolution.Minute
        self.universeXLF = self.AddUniverse(self.coarse, self.XLFfine)
        self.universeXLE = self.AddUniverse(self.coarse, self.XLEfine)
    #    self.universeXLB = self.AddUniverse(self.coarse, self.XLBfine)
    #    self.universeXLI = self.AddUniverse(self.coarse, self.XLIfine)
    #    self.universeXLY = self.AddUniverse(self.coarse, self.XLYfine)
    #    self.universeXLP = self.AddUniverse(self.coarse, self.XLPfine)
    #    self.universeXLU = self.AddUniverse(self.coarse, self.XLUfine)
    #    self.universeXLK = self.AddUniverse(self.coarse, self.XLKfine)
    #    self.universeXLV = self.AddUniverse(self.coarse, self.XLVfine)
    #    self.universeXLC = self.AddUniverse(self.coarse, self.XLCfine)
        self.SetWarmup(500)
        self.symbolBySectorCode = dict()
        self.__numberOfSymbols = 2000
        self.__numberOfSymbolsFine = 3
        self.addedsymbols = [self.SPY, self.stock, self.bond, self.vix, self.XLF, self.XLE, self.XLB, self.XLI, self.XLY, self.XLP, self.XLU, self.XLK, self.XLV, self.XLC, self.SQQQ]
       
        self.Schedule.On(self.DateRules.EveryDay(self.stock), self.TimeRules.AfterMarketOpen(self.stock, 1), 
           self.Rebalance)
           
        self.Schedule.On(self.DateRules.EveryDay(self.stock), self.TimeRules.AfterMarketOpen(self.stock, 5),         
                self.Collectsymboldata)
                
                
       #set the following between 1 - 4 hours depending on buy frequency    
       
        self.Schedule.On(self.DateRules.EveryDay(self.stock),
                self.TimeRules.Every(timedelta(hours=1)),
                self.buySignals)
                
        self.Schedule.On(self.DateRules.EveryDay(self.stock), 
                self.TimeRules.Every(timedelta(hours=4)),
                self.takeShort)
                
#        self.Schedule.On(self.DateRules.EveryDay(self.stock),
#                 self.TimeRules.Every(timedelta(hours=3.25)),
#                 self.sellSignals)
                
        self.Schedule.On(self.DateRules.EveryDay("SPY"),
                self.TimeRules.AfterMarketOpen("SPY"),
                self.tradeStart)
                
        self.Schedule.On(self.DateRules.EveryDay("SPY"),
                self.TimeRules.BeforeMarketClose("SPY"),
                self.tradeEnd)

    def tradeStart(self):
       self.trade = True
    def tradeEnd(self):
       self.trade = False
       
   
   
    def Collectsymboldata(self):
       
        for symbol in self.XLFstocks:
           self.AddEquity(symbol, Resolution.Hour)
           
           ema10 = self.EMA(symbol, 10, Resolution.Hour, Field.Close)
           sma200 = self.SMA(symbol, 200, Resolution.Daily, Field.Close)
           sma7 = self.SMA(symbol, 7, Resolution.Hour, Field.Close) 
           sma20 = self.SMA(symbol, 20, Resolution.Daily, Field.Close)
           sma50 = self.SMA(symbol, 50, Resolution.Daily, Field.Close)
           ema20 = self.EMA(symbol, 20, Resolution.Hour, Field.Close)
           ema50 = self.EMA(symbol, 50, Resolution.Hour, Field.Close)
           rsi = self.RSI(symbol, 14, Resolution.Daily)
           wilr = self.WILR(symbol, 14, Resolution.Daily)
           wilr_fast = self.WILR(symbol, 10, Resolution.Daily)
           high = self.MAX(symbol, int(self.GetParameter("highHist")), Resolution.Daily, Field.High)
           midhigh = self.MAX(symbol, 3, Resolution.Daily, Field.High)
           low = self.MIN(symbol, int(self.GetParameter("lowHist")), Resolution.Daily, Field.Low)
           stoplow = self.MIN(symbol, 20, Resolution.Daily, Field.Low)
           
           symbolData = SymbolData(symbol, sma7, ema10, sma20, sma200, sma50, ema20, rsi, wilr, wilr_fast, high, midhigh, low, stoplow)
           self.XLFsector_symbolDataBySymbol[symbol] = symbolData
       
        for symbol in self.XLEstocks:
           self.AddEquity(symbol, Resolution.Hour)
           ema10 = self.EMA(symbol, 10, Resolution.Hour, Field.Close)
           sma200 = self.SMA(symbol, 200, Resolution.Daily, Field.Close)
           sma7 = self.SMA(symbol, 7, Resolution.Hour, Field.Close)
           sma20 = self.SMA(symbol, 20, Resolution.Daily, Field.Close)
           sma50 = self.SMA(symbol, 50, Resolution.Daily, Field.Close)
           ema20 = self.EMA(symbol, 20, Resolution.Hour, Field.Close)
           ema50 = self.EMA(symbol, 50, Resolution.Hour, Field.Close)
           rsi = self.RSI(symbol, 14, Resolution.Daily)
           wilr = self.WILR(symbol, 14, Resolution.Daily)
           wilr_fast = self.WILR(symbol, 10, Resolution.Daily)
           high = self.MAX(symbol, int(self.GetParameter("highHist")), Resolution.Daily, Field.High)
           midhigh = self.MAX(symbol, 3, Resolution.Daily, Field.High)
           low = self.MIN(symbol, int(self.GetParameter("lowHist")), Resolution.Daily, Field.Low)
           stoplow = self.MIN(symbol, 20, Resolution.Daily, Field.Low)
           
           symbolData = SymbolData(symbol, sma7, ema10, sma20, sma200, sma50, ema20, rsi, wilr, wilr_fast, high, midhigh, low, stoplow)
           self.XLEsector_symbolDataBySymbol[symbol] = symbolData
           
        for symbol in self.XLBstocks:
           self.AddEquity(symbol, Resolution.Hour)
           ema10 = self.EMA(symbol, 10, Resolution.Hour, Field.Close)
           sma200 = self.SMA(symbol, 200, Resolution.Daily, Field.Close)
           sma7 = self.SMA(symbol, 7, Resolution.Hour, Field.Close)
           sma20 = self.SMA(symbol, 20, Resolution.Daily, Field.Close)
           sma50 = self.SMA(symbol, 50, Resolution.Daily, Field.Close)
           ema20 = self.EMA(symbol, 20, Resolution.Hour, Field.Close)
           ema50 = self.EMA(symbol, 50, Resolution.Hour, Field.Close)
           rsi = self.RSI(symbol, 14, Resolution.Daily)
           wilr = self.WILR(symbol, 14, Resolution.Daily)
           wilr_fast = self.WILR(symbol, 10, Resolution.Daily)
           high = self.MAX(symbol, int(self.GetParameter("highHist")), Resolution.Daily, Field.High)
           midhigh = self.MAX(symbol, 3, Resolution.Daily, Field.High)
           low = self.MIN(symbol, int(self.GetParameter("lowHist")), Resolution.Daily, Field.Low)
           stoplow = self.MIN(symbol, 20, Resolution.Daily, Field.Low)
           
           symbolData = SymbolData(symbol, sma7, ema10, sma20, sma200, sma50, ema20, rsi, wilr, wilr_fast, high, midhigh, low, stoplow)
           self.XLBsector_symbolDataBySymbol[symbol] = symbolData
       
        for symbol in self.XLIstocks:
           self.AddEquity(symbol, Resolution.Hour)
           ema10 = self.EMA(symbol, 10, Resolution.Hour, Field.Close)
           sma200 = self.SMA(symbol, 200, Resolution.Daily, Field.Close)
           sma7 = self.SMA(symbol, 7, Resolution.Hour, Field.Close)
           sma20 = self.SMA(symbol, 20, Resolution.Daily, Field.Close)
           sma50 = self.SMA(symbol, 50, Resolution.Daily, Field.Close)
           ema20 = self.EMA(symbol, 20, Resolution.Hour, Field.Close)
           ema50 = self.EMA(symbol, 50, Resolution.Hour, Field.Close)
           rsi = self.RSI(symbol, 14, Resolution.Daily)
           wilr = self.WILR(symbol, 14, Resolution.Daily)
           wilr_fast = self.WILR(symbol, 10, Resolution.Daily)
           high = self.MAX(symbol, int(self.GetParameter("highHist")), Resolution.Daily, Field.High)
           midhigh = self.MAX(symbol, 3, Resolution.Daily, Field.High)
           low = self.MIN(symbol, int(self.GetParameter("lowHist")), Resolution.Daily, Field.Low)
           stoplow = self.MIN(symbol, 20, Resolution.Daily, Field.Low)
           
           symbolData = SymbolData(symbol, sma7, ema10, sma20, sma200, sma50, ema20, rsi, wilr, wilr_fast, high, midhigh, low, stoplow)
           self.XLIsector_symbolDataBySymbol[symbol] = symbolData
           
        for symbol in self.XLYstocks:
           self.AddEquity(symbol, Resolution.Hour)
           ema10 = self.EMA(symbol, 10, Resolution.Hour, Field.Close)
           sma200 = self.SMA(symbol, 200, Resolution.Daily, Field.Close)
           sma7 = self.SMA(symbol, 7, Resolution.Hour, Field.Close)
           sma20 = self.SMA(symbol, 20, Resolution.Daily, Field.Close)
           sma50 = self.SMA(symbol, 50, Resolution.Daily, Field.Close)
           ema20 = self.EMA(symbol, 20, Resolution.Hour, Field.Close)
           ema50 = self.EMA(symbol, 50, Resolution.Hour, Field.Close)
           rsi = self.RSI(symbol, 14, Resolution.Daily)
           wilr = self.WILR(symbol, 14, Resolution.Daily)
           wilr_fast = self.WILR(symbol, 10, Resolution.Daily)
           high = self.MAX(symbol, int(self.GetParameter("highHist")), Resolution.Daily, Field.High)
           midhigh = self.MAX(symbol, 3, Resolution.Daily, Field.High)
           low = self.MIN(symbol, int(self.GetParameter("lowHist")), Resolution.Daily, Field.Low)
           stoplow = self.MIN(symbol, 20, Resolution.Daily, Field.Low)
           
           symbolData = SymbolData(symbol, sma7, ema10, sma20, sma200, sma50, ema20, rsi, wilr, wilr_fast, high, midhigh, low, stoplow)
           self.XLYsector_symbolDataBySymbol[symbol] = symbolData
           
        for symbol in self.XLPstocks:
           self.AddEquity(symbol, Resolution.Hour)
           ema10 = self.EMA(symbol, 10, Resolution.Hour, Field.Close)
           sma200 = self.SMA(symbol, 200, Resolution.Daily, Field.Close)
           sma7 = self.SMA(symbol, 7, Resolution.Hour, Field.Close)
           sma20 = self.SMA(symbol, 20, Resolution.Daily, Field.Close)
           sma50 = self.SMA(symbol, 50, Resolution.Daily, Field.Close)
           ema20 = self.EMA(symbol, 20, Resolution.Hour, Field.Close)
           ema50 = self.EMA(symbol, 50, Resolution.Hour, Field.Close)
           rsi = self.RSI(symbol, 14, Resolution.Daily)
           wilr = self.WILR(symbol, 14, Resolution.Daily)
           wilr_fast = self.WILR(symbol, 10, Resolution.Daily)
           high = self.MAX(symbol, int(self.GetParameter("highHist")), Resolution.Daily, Field.High)
           midhigh = self.MAX(symbol, 3, Resolution.Daily, Field.High)
           low = self.MIN(symbol, int(self.GetParameter("lowHist")), Resolution.Daily, Field.Low)
           stoplow = self.MIN(symbol, 20, Resolution.Daily, Field.Low)
           
           symbolData = SymbolData(symbol, sma7, ema10, sma20, sma200, sma50, ema20, rsi, wilr, wilr_fast, high, midhigh, low, stoplow)
           self.XLPsector_symbolDataBySymbol[symbol] = symbolData
       
        for symbol in self.XLUstocks:
            self.AddEquity(symbol, Resolution.Hour)
            ema10 = self.EMA(symbol, 10, Resolution.Hour, Field.Close)
            sma200 = self.SMA(symbol, 200, Resolution.Daily, Field.Close)
            sma7 = self.SMA(symbol, 7, Resolution.Hour, Field.Close)
            sma20 = self.SMA(symbol, 20, Resolution.Daily, Field.Close)
            sma50 = self.SMA(symbol, 50, Resolution.Daily, Field.Close)
            ema20 = self.EMA(symbol, 20, Resolution.Hour, Field.Close)
            ema50 = self.EMA(symbol, 50, Resolution.Hour, Field.Close)
            rsi = self.RSI(symbol, 14, Resolution.Daily)
            wilr = self.WILR(symbol, 14, Resolution.Daily)
            wilr_fast = self.WILR(symbol, 10, Resolution.Daily)
            high = self.MAX(symbol, int(self.GetParameter("highHist")), Resolution.Daily, Field.High)
            midhigh = self.MAX(symbol, 3, Resolution.Daily, Field.High)
            low = self.MIN(symbol, int(self.GetParameter("lowHist")), Resolution.Daily, Field.Low)
            stoplow = self.MIN(symbol, 20, Resolution.Daily, Field.Low)
           
            symbolData = SymbolData(symbol, sma7, ema10, sma20, sma200, sma50, ema20, rsi, wilr, wilr_fast, high, midhigh, low, stoplow)
            self.XLUsector_symbolDataBySymbol[symbol] = symbolData
           
        for symbol in self.XLKstocks:
            self.AddEquity(symbol, Resolution.Hour)
            ema10 = self.EMA(symbol, 10, Resolution.Hour, Field.Close)
            sma200 = self.SMA(symbol, 200, Resolution.Daily, Field.Close)
            sma7 = self.SMA(symbol, 7, Resolution.Hour, Field.Close)
            sma20 = self.SMA(symbol, 20, Resolution.Daily, Field.Close)
            sma50 = self.SMA(symbol, 50, Resolution.Daily, Field.Close)
            ema20 = self.EMA(symbol, 20, Resolution.Hour, Field.Close)
            ema50 = self.EMA(symbol, 50, Resolution.Hour, Field.Close)
            rsi = self.RSI(symbol, 14, Resolution.Daily)
            wilr = self.WILR(symbol, 14, Resolution.Daily)
            wilr_fast = self.WILR(symbol, 10, Resolution.Daily)
            high = self.MAX(symbol, int(self.GetParameter("highHist")), Resolution.Daily, Field.High)
            midhigh = self.MAX(symbol, 3, Resolution.Daily, Field.High)
            low = self.MIN(symbol, int(self.GetParameter("lowHist")), Resolution.Daily, Field.Low)
            stoplow = self.MIN(symbol, 20, Resolution.Daily, Field.Low)
           
            symbolData = SymbolData(symbol, sma7, ema10, sma20, sma200, sma50, ema20, rsi, wilr, wilr_fast, high, midhigh, low, stoplow)
            self.XLKsector_symbolDataBySymbol[symbol] = symbolData

    def OnData(self, data):
       
       #for symbol in self.activelyTrading:
       #    if not self.Portfolio[symbol].Invested:
       #        self.SetHoldings(symbol, self.weight)
       
       # Note: in the below, x is Symbol and x.Value is string
       
       self.Debug(f"XLE universe includes: {[x.Value for x in self.energy_ROA]}")
       self.Debug(f"XLF universe includes: {[x.Value for x in self.FinSci_ROA]}")
       self.Debug(f"XLE has data on: {[x.Value for x in self.XLEsector_symbolDataBySymbol]}")
       #self.Debug(f"Actively Trading: {[x.Value for x in self.activelyTrading]}")
       self.Debug(f"XLE-2 universe includes: {[x.Value for x in self.XLEstocks]}")
#        self.Debug(f"XLI universe includes: {[x.Value for x in self.XLIstocks]}")
#        self.Debug(f"XLY universe includes: {[x.Value for x in self.XLYstocks]}")
#        self.Debug(f"XLP universe includes: {[x.Value for x in self.XLPstocks]}")
#        self.Debug(f"XLU universe includes: {[x.Value for x in self.XLUstocks]}")
       self.Debug(f"XLK universe includes: {[x.Value for x in self.XLKstocks]}")
#        self.Debug(f"XLV universe includes: {[x.Value for x in self.XLVstocks]}")
#        self.Debug(f"XLC universe includes: {[x.Value for x in self.XLCstocks]}")


    
    def coarse(self, coarse):       

        if self.curr_month == self.Time.month:
            return Universe.Unchanged
        
        self.curr_month = self.Time.month
        if self.Time.month % 3 != 1:
            return Universe.Unchanged        
        self.quarters += 1
        
        return [c.Symbol for c in coarse if c.HasFundamentalData]


    


    def XLFfine(self, fine):
       
        FinSci_securities = [f for f in fine if f.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.FinancialServices and
                                                f.OperationRatios.ROA.ThreeMonths]
        
        for security in FinSci_securities:
            symbol = security.Symbol
            if symbol not in self.FinSci_ROA:
                self.FinSci_ROA[symbol] = deque(maxlen=12)
            self.FinSci_ROA[symbol].append(security.OperationRatios.ROA.ThreeMonths)

        if self.Time.month != 4 or (self.quarters < 12 ):
            return Universe.Unchanged

        FinSci_securities = [x for x in FinSci_securities if x.OperationRatios.ROA.OneYear and
                                                        x.FinancialStatements.CashFlowStatement.OperatingCashFlow.TwelveMonths and
                                                        x.FinancialStatements.BalanceSheet.TotalAssets.TwelveMonths and
                                                        x.FinancialStatements.IncomeStatement.ResearchAndDevelopment.TwelveMonths and
                                                        x.FinancialStatements.CashFlowStatement.CapExReported.TwelveMonths and
                                                        x.FinancialStatements.IncomeStatement.SellingGeneralAndAdministration.TwelveMonths and
                                                        x.MarketCap]

        FinSci_VARROA = {symbol:stat.variance(ROA) for symbol, ROA in self.FinSci_ROA.items() if len(ROA) == ROA.maxlen}
        
        if len(FinSci_VARROA) < 2:
            return Universe.Unchanged
        
        FinSci_VARROA_median = stat.median(FinSci_VARROA.values())
        FinSci_ROA1Y = {x.Symbol:x.OperationRatios.ROA.OneYear for x in FinSci_securities}
        FinSci_ROA1Y_median = stat.median(FinSci_ROA1Y.values())
        FinSci_CFROA = {x.Symbol: (
            x.FinancialStatements.CashFlowStatement.OperatingCashFlow.TwelveMonths 
            / x.FinancialStatements.BalanceSheet.TotalAssets.TwelveMonths
            ) for x in FinSci_securities}
        FinSci_CFROA_median = stat.median(FinSci_CFROA.values())

        FinSci_RD2MktCap = {x.Symbol: (
            x.FinancialStatements.IncomeStatement.ResearchAndDevelopment.TwelveMonths / x.MarketCap
            ) for x in FinSci_securities}
        FinSci_RD2MktCap_median = stat.median(FinSci_RD2MktCap.values()) 

        FinSci_CaPex2MktCap = {x.Symbol: (
            x.FinancialStatements.CashFlowStatement.CapExReported.TwelveMonths / x.MarketCap
            ) for x in FinSci_securities}
        FinSci_CaPex2MktCap_median = stat.median(FinSci_CaPex2MktCap.values())  

        FinSci_Ad2MktCap = {x.Symbol: (
            x.FinancialStatements.IncomeStatement.SellingGeneralAndAdministration.TwelveMonths / x.MarketCap
            ) for x in FinSci_securities}
        FinSci_Ad2MktCap_median = stat.median(FinSci_Ad2MktCap.values())

        has_book = [f for f in fine if f.FinancialStatements.BalanceSheet.NetTangibleAssets.TwelveMonths and f.MarketCap]
        sorted_by_BM = sorted(has_book, key=lambda x: x.FinancialStatements.BalanceSheet.NetTangibleAssets.TwelveMonths / x.MarketCap)[:len(has_book)//4]
        FinSci_symbols = [f.Symbol for f in sorted_by_BM if f in FinSci_securities]
        
        ratioDicts_medians = [(FinSci_ROA1Y, FinSci_ROA1Y_median), 
                                (FinSci_CFROA, FinSci_CFROA_median), (FinSci_RD2MktCap, FinSci_RD2MktCap_median),
                                (FinSci_CaPex2MktCap, FinSci_CaPex2MktCap_median), (FinSci_Ad2MktCap, FinSci_Ad2MktCap_median)]

    def XLEfine(self, fine):
       
        energy_securities = [f for f in fine if f.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.Energy and
                                                f.OperationRatios.ROA.ThreeMonths]
        
        for security in energy_securities:
            symbol = security.Symbol
            if symbol not in self.energy_ROA:
                self.energy_ROA[symbol] = deque(maxlen=12)
            self.energy_ROA[symbol].append(security.OperationRatios.ROA.ThreeMonths)

        if self.Time.month != 4 or (self.quarters < 12 ):
            return Universe.Unchanged

        energy_securities = [x for x in energy_securities if x.OperationRatios.ROA.OneYear and
                                                        x.FinancialStatements.CashFlowStatement.OperatingCashFlow.TwelveMonths and
                                                        x.FinancialStatements.BalanceSheet.TotalAssets.TwelveMonths and
                                                        x.FinancialStatements.IncomeStatement.ResearchAndDevelopment.TwelveMonths and
                                                        x.FinancialStatements.CashFlowStatement.CapExReported.TwelveMonths and
                                                        x.FinancialStatements.IncomeStatement.SellingGeneralAndAdministration.TwelveMonths and
                                                        x.MarketCap]

        energy_VARROA = {symbol:stat.variance(ROA) for symbol, ROA in self.energy_ROA.items() if len(ROA) == ROA.maxlen}
        
        if len(energy_VARROA) < 2:
            return Universe.Unchanged
        
        energy_VARROA_median = stat.median(energy_VARROA.values())
        energy_ROA1Y = {x.Symbol:x.OperationRatios.ROA.OneYear for x in energy_securities}
        energy_ROA1Y_median = stat.median(energy_ROA1Y.values())
        energy_CFROA = {x.Symbol: (
            x.FinancialStatements.CashFlowStatement.OperatingCashFlow.TwelveMonths 
            / x.FinancialStatements.BalanceSheet.TotalAssets.TwelveMonths
            ) for x in energy_securities}
        energy_CFROA_median = stat.median(energy_CFROA.values())

        energy_RD2MktCap = {x.Symbol: (
            x.FinancialStatements.IncomeStatement.ResearchAndDevelopment.TwelveMonths / x.MarketCap
            ) for x in energy_securities}
        energy_RD2MktCap_median = stat.median(energy_RD2MktCap.values()) 

        energy_CaPex2MktCap = {x.Symbol: (
            x.FinancialStatements.CashFlowStatement.CapExReported.TwelveMonths / x.MarketCap
            ) for x in energy_securities}
        energy_CaPex2MktCap_median = stat.median(energy_CaPex2MktCap.values())  

        energy_Ad2MktCap = {x.Symbol: (
            x.FinancialStatements.IncomeStatement.SellingGeneralAndAdministration.TwelveMonths / x.MarketCap
            ) for x in energy_securities}
        energy_Ad2MktCap_median = stat.median(energy_Ad2MktCap.values())

        has_book = [f for f in fine if f.FinancialStatements.BalanceSheet.NetTangibleAssets.TwelveMonths and f.MarketCap]
        sorted_by_BM = sorted(has_book, key=lambda x: x.FinancialStatements.BalanceSheet.NetTangibleAssets.TwelveMonths / x.MarketCap)[:len(has_book)//4]
        energy_symbols = [f.Symbol for f in sorted_by_BM if f in energy_securities]
        
        ratioDicts_medians = [(energy_ROA1Y, energy_ROA1Y_median),   
                                (energy_CFROA, energy_CFROA_median), (energy_RD2MktCap, energy_RD2MktCap_median),
                                (energy_CaPex2MktCap, energy_CaPex2MktCap_median), (energy_Ad2MktCap, energy_Ad2MktCap_median)]
        
    def compute_g_score_finance(symbol):
        g_score = 0
        if FinSci_CFROA[symbol] > FinSci_ROA1Y[symbol]:
                g_score += 1
        if symbol in FinSci_VARROA and FinSci_VARROA[symbol] < FinSci_VARROA_median:
                g_score += 1
        for ratio_dict, median in ratioDicts_medians:
            if symbol in ratio_dict and ratio_dict[symbol] > median:
                g_score += 1
        return g_score
 
        g_scores = {symbol:compute_g_score(symbol) for symbol in FinSci_symbols}
        
        return [symbol for symbol, g_score in g_scores.items() if g_score >= 5]

    def compute_g_score_energy(symbol):
        g_score = 0
        if energy_CFROA[symbol] > energy_ROA1Y[symbol]:
                g_score += 1
        if symbol in energy_VARROA and energy_VARROA[symbol] < energy_VARROA_median:
                g_score += 1
        for ratio_dict, median in ratioDicts_medians:
            if symbol in ratio_dict and ratio_dict[symbol] > median:
                g_score += 1
        return g_score
 
        g_scores = {symbol:compute_g_score(symbol) for symbol in energy_symbols}
        
        return [symbol for symbol, g_score in g_scores.items() if g_score >= 5]


    def Rebalance(self):
       if not self.mom.IsReady or not self.sma.IsReady: return
       initial_asset = self.stock if self.mom.Current.Value > 0 else self.bond
       
       if self.init:
           self.SetHoldings(initial_asset, .01)
           self.init = False
           
       keihist = self.History([self.kei], (int(self.GetParameter("keihist"))))
       #keihist = keihist['Value'].unstack(level=0).dropna()
       keihistlowt = np.nanpercentile(keihist, 15)
       keihistmidt = np.nanpercentile(keihist, 50)
       keihisthight = np.nanpercentile(keihist, 90)
       kei = self.sma.Current.Value
       keimom = self.mom.Current.Value
           
       if (keimom < 0 and kei < keihistmidt and  kei > keihistlowt) and not (self.Securities[self.bond].Invested)  :
           # DECLINE
           self.Liquidate()
           self.SetHoldings(self.XLP, .01)
           
           for symbol, symbolData in self.XLPsector_symbolDataBySymbol.items():
               if not self.Portfolio[symbol].Invested : #and (self.Securities[symbol].Close > symbolData.sma50.Current.Value):
                   self.SetHoldings(symbol, .1, False, "Buy Signal")
                   
          #Stop Loss
#            for symbol, symbolData in self.XLPsector_symbolDataBySymbol.items():
#                if not (self.Securities[symbol].Close < symbolData.low.Current.Value) and (self.Securities[self.XLB].Invested):
#                    self.Liquidate()
#                    self.SetHoldings(self.XLP, .01)
           
           self.SetHoldings(self.bond, .4)
           self.Debug("STAPLES {0} >> {1}".format(self.XLP, self.Time))
       
       elif (keimom > 0 and kei < keihistlowt) and not (self.Securities[self.XLB].Invested)  :
           # RECOVERY
           self.Liquidate()
           self.SetHoldings(self.XLB, .01)
           
           for symbol, symbolData in self.XLEsector_symbolDataBySymbol.items():
               if not self.Portfolio[symbol].Invested : #and (self.Securities[symbol].Close > symbolData.sma50.Current.Value):
                   self.SetHoldings(symbol, .1, False, "Buy Signal")
           
           #XLB
           for symbol, symbolData in self.XLBsector_symbolDataBySymbol.items():
               if not self.Portfolio[symbol].Invested : #and (self.Securities[symbol].Close > symbolData.sma50.Current.Value):
                   self.SetHoldings(symbol, .1, False, "Buy Signal")
           #XLY
           for symbol, symbolData in self.XLYsector_symbolDataBySymbol.items():
               if not self.Portfolio[symbol].Invested : #and (self.Securities[symbol].Close > symbolData.sma50.Current.Value):
                   self.SetHoldings(symbol, .1, False, "Buy Signal")
          
           #Stop Loss
#            for symbol, symbolData in self.XLBsector_symbolDataBySymbol.items():
#                if not (self.Securities[symbol].Close < symbolData.low.Current.Value) and (self.Securities[self.XLB].Invested):
#                    self.Liquidate()
#                    self.SetHoldings(self.XLB, .01)
          
          
           self.Debug("MATERIALS {0} >> {1}".format(self.XLB, self.Time))
           
           
       elif (keimom > 0 and kei > keihistlowt and kei < keihistmidt) and not (self.Securities[self.XLE].Invested)  :
           # EARLY
           self.Liquidate()
           self.SetHoldings(self.XLE, .01)
           #XLF
           for symbol, symbolData in self.XLFsector_symbolDataBySymbol.items():
               if not self.Portfolio[symbol].Invested : #and (self.Securities[symbol].Close > symbolData.sma50.Current.Value):
                   self.SetHoldings(symbol, .1, False, "Buy Signal")
           
           #XLI
           for symbol, symbolData in self.XLIsector_symbolDataBySymbol.items():
               if not self.Portfolio[symbol].Invested : #and (self.Securities[symbol].Close > symbolData.sma50.Current.Value):
                   self.SetHoldings(symbol, .1, False, "Buy Signal")
           
           #XLE 
           for symbol, symbolData in self.XLEsector_symbolDataBySymbol.items():
               if not self.Portfolio[symbol].Invested : #and (self.Securities[symbol].Close > symbolData.sma50.Current.Value):
                   self.SetHoldings(symbol, .1, False, "Buy Signal")
                   
           #Stop Loss
#            for symbol, symbolData in self.XLEstocks.items():
#                if not (self.Securities[symbol].Close < symbolData.low.Current.Value) and (self.Securities[self.XLE].Invested):
#                    self.Liquidate()
#                    self.SetHoldings(self.XLE, .01)
          
           
           self.Debug("ENERGY {0} >> {1}".format(self.XLE, self.Time))
           
       elif (keimom > 0 and kei > keihistmidt and kei < keihisthight) and not (self.Securities[self.XLU].Invested)  :
           # REBOUND
           self.Liquidate()
           #self.SetHoldings(self.XLK, .5)
           self.SetHoldings(self.XLU, .01)
           
           #XLU
           for symbol, symbolData in self.XLUsector_symbolDataBySymbol.items():
               if not self.Portfolio[symbol].Invested : #and (self.Securities[symbol].Close > symbolData.sma50.Current.Value):
                   self.SetHoldings(symbol, .2, False, "Buy Signal")
           
           #Stop Loss
#           for symbol, symbolData in self.XLUsector_symbolDataBySymbol.items():
#               if not (self.Securities[symbol].Close < symbolData.low.Current.Value) and (self.Securities[self.XLU].Invested):
#                   self.Liquidate()
#                   self.SetHoldings(self.XLU, .01)
           
           
           
           self.Debug("UTILITIES {0} >> {1}".format(self.XLU, self.Time))
       
       elif (keimom < 0 and kei < keihisthight and kei > keihistmidt) and not (self.Securities[self.XLK].Invested)  :
           # LATE
           self.Liquidate()
           self.SetHoldings(self.XLK, .01)
           
           for symbol, symbolData in self.XLKsector_symbolDataBySymbol.items():
               if not self.Portfolio[symbol].Invested and (self.Securities[symbol].Close > symbolData.sma200.Current.Value) :
                   self.SetHoldings(symbol, .1, False, "Buy Signal")
          
          
           self.Debug("INFO TECH {0} >> {1}".format(self.XLK, self.Time))
           
           #Stop Loss
 #          for symbol, symbolData in self.XLKsector_symbolDataBySymbol.items():
#               if not (self.Securities[symbol].Close < symbolData.low.Current.Value) and (self.Securities[self.XLK].Invested):
#                   self.Liquidate()
#                   self.SetHoldings(self.XLK, .01)
       
       elif (keimom < 0 and kei < 100 and not self.Securities[self.bond].Invested):
           self.Liquidate()
           self.SetHoldings(self.bond, .5)
       
       self.Plot("LeadInd", "SMA(LeadInd)", self.sma.Current.Value)
       self.Plot("LeadInd", "THRESHOLD", 100)
       self.Plot("MOMP", "MOMP(LeadInd)", self.mom.Current.Value)
       self.Plot("MOMP", "THRESHOLD", 0)
       
    def buySignals(self):
        if self.trade == False:
           return
## EARLY - XLE
        for symbol, symbolData in self.XLEsector_symbolDataBySymbol.items():
           if self.Portfolio[self.XLE].Invested and (self.Securities[symbol].Close > symbolData.sma200.Current.Value):
               self.SetHoldings(symbol, .15, False, "Buy Signal")
       
        for symbol, symbolData in self.XLFsector_symbolDataBySymbol.items():
           if self.Portfolio[self.XLE].Invested and (self.Securities[symbol].Close > symbolData.sma200.Current.Value):
               self.SetHoldings(symbol, .15, False, "Buy Signal")
               
        for symbol, symbolData in self.XLIsector_symbolDataBySymbol.items():
           if self.Portfolio[self.XLE].Invested and (self.Securities[symbol].Close > symbolData.sma200.Current.Value):
               self.SetHoldings(symbol, .15, False, "Buy Signal")
               
##  Recovery - XLB
        for symbol, symbolData in self.XLEsector_symbolDataBySymbol.items():
           if self.Portfolio[self.XLB].Invested and (self.Securities[symbol].Close > symbolData.sma200.Current.Value):
               self.SetHoldings(symbol, .2, False, "Buy Signal")
       
        for symbol, symbolData in self.XLBsector_symbolDataBySymbol.items():
           if self.Portfolio[self.XLB].Invested and (self.Securities[symbol].Close > symbolData.sma200.Current.Value):
               self.SetHoldings(symbol, .2, False, "Buy Signal")
               
        for symbol, symbolData in self.XLYsector_symbolDataBySymbol.items():
           if self.Portfolio[self.XLB].Invested and (self.Securities[symbol].Close > symbolData.sma200.Current.Value):
               self.SetHoldings(symbol, .2, False, "Buy Signal")
               
## Rebound - XLU
        for symbol, symbolData in self.XLUsector_symbolDataBySymbol.items():
           if self.Portfolio[self.XLU].Invested and (self.Securities[symbol].Close > symbolData.sma200.Current.Value):
               self.SetHoldings(symbol, .2, False, "Buy Signal")
               
## Decline - XLP 
        for symbol, symbolData in self.XLPsector_symbolDataBySymbol.items():
           if self.Portfolio[self.XLP].Invested and (self.Securities[symbol].Close > symbolData.sma200.Current.Value):
               self.SetHoldings(symbol, .2, False, "Buy Signal")
               
## Late - XLK               
        for symbol, symbolData in self.XLKsector_symbolDataBySymbol.items():
           if self.Portfolio[self.XLK].Invested and (self.Securities[symbol].Close > symbolData.sma200.Current.Value):
               self.SetHoldings(symbol, .2, False, "Buy Signal")
               
        for symbol, symbolData in self.XLVsector_symbolDataBySymbol.items():
           if self.Portfolio[self.XLK].Invested and (self.Securities[symbol].Close > symbolData.sma200.Current.Value):
               self.SetHoldings(symbol, .2, False, "Buy Signal")
    
    def takeShort(self):               
        if self.trade == False:
           return
## SHORT - XLK
        for symbol, symbolData in self.XLKsector_symbolDataBySymbol.items():
           if self.Portfolio[self.XLK].Invested: # and (self.Securities[symbol].Close < symbolData.sma50.Current.Value):
               self.Liquidate()
               self.SetHoldings(self.SQQQ, .5, "Short Position Signal")

class SelectionData(object):
   def __init__(self, symbol, period):
       self.symbol = symbol
       self.ema = ExponentialMovingAverage(period)
       self.is_above_ema = False
       self.volume = 0
   def update(self, time, price, volume):
       self.volume = volume
       if self.ema.Update(time, price):
           self.is_above_ema = price > ema   

class SymbolData:
   def __init__(self, symbol, sma7, ema10, sma20, sma50, sma200,  ema20, rsi, wilr, wilr_fast, high, midhigh, low, stoplow):
       self.Symbol = symbol
       self.sma7 = sma7
       self.ema10 = ema10
       self.sma20 = sma20
       self.sma50 = sma50
       self.sma200 = sma200
       self.ema20 = ema20
       self.rsi = rsi
       self.wilr = wilr
       self.wilr_fast = wilr_fast
       self.high = high
       self.midhigh = midhigh
       self.low = low
       self.stoplow = stoplow
       
   
       
# Quandl often doesn't use close columns so need to tell LEAN which is the "value" column.
class QuandlCustomColumns(PythonQuandl):
   def __init__(self):
       # Define ValueColumnName: cannot be None, Empty or non-existant column name
       self.ValueColumnName = "Value"