Overall Statistics
Total Trades
1979
Average Win
0.21%
Average Loss
-0.20%
Compounding Annual Return
-1.795%
Drawdown
19.000%
Expectancy
-0.024
Net Profit
-5.720%
Sharpe Ratio
-0.115
Loss Rate
52%
Win Rate
48%
Profit-Loss Ratio
1.04
Alpha
0.045
Beta
-3.041
Annual Standard Deviation
0.101
Annual Variance
0.01
Information Ratio
-0.298
Tracking Error
0.101
Treynor Ratio
0.004
Total Fees
$2022.14
#This is a Template of dynamic stock selection.
#You can try your own fundamental factor and ranking method by editing the CoarseSelectionFunction and FineSelectionFunction

from QuantConnect.Data.UniverseSelection import *
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Common")

from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Indicators import *
from QuantConnect.Data.Market import TradeBar

class BasicTemplateAlgorithm(QCAlgorithm):
    
    def __init__(self):
    # set the flag for rebalance
        self.reb = 1
    # Number of stocks to pass CoarseSelection process
        self.num_coarse = 100
    # Number of stocks to long/short
        self.num_fine = 20
        self.symbols = None
        self.first_month = 0
        self.topFine = None
    

    def Initialize(self):
        self.SetCash(100000)
        self.SetStartDate(2007,1,1)
    # if not specified, the Backtesting EndDate would be today 
        self.SetEndDate(2010,4,1)
        self.Portfolio.MarginCallModel = MarginCallModel.Null;
        ############Trying to chart rolling 30 day performance################
        #self.rollingPerformanceWindow = RollingWindow[decimal](30)
        #self.rollingPerformanceWindow.Add(self.Portfolio.TotalPortfolioValue)
        #self.Plot("Rolling Performance","Rolling Strategy Performance",(self.rollingPerformanceWindow[29] -self.rollingPerformanceWindow[0])/self.rollingPerformanceWindow[29])
        
        self.spy = self.AddEquity("SPY", Resolution.Daily).Symbol
        
        self.UniverseSettings.Resolution = Resolution.Daily
        self.UniverseSettings.Leverage = 4.0
        self.AddUniverse(self.CoarseSelectionFunction,self.FineSelectionFunction)
        
    # Schedule the rebalance function to execute at the begining of each month
        self.Schedule.On(self.DateRules.MonthStart(self.spy), 
        self.TimeRules.AfterMarketOpen(self.spy,5), Action(self.rebalance))
        
    
    def CoarseSelectionFunction(self, coarse):
    # if the rebalance flag is not 1, return null list to save time.
        if self.reb != 1:
            return self.topFine if self.topFine is not None else []

            
    # make universe selection once a month
    # drop stocks which have no fundamental data or have too low prices
        selected = [x for x in coarse if (x.HasFundamentalData) 
                    and (float(x.Price) > 5)]
        
        sortedByDollarVolume = sorted(selected, key=lambda x: x.DollarVolume, reverse=True) 
        top = sortedByDollarVolume[:self.num_coarse]
        return [i.Symbol for i in top]

    def FineSelectionFunction(self, fine):
    # return null list if it's not time to rebalance
        if self.reb != 1:
            return self.topFine if self.topFine is not None else []
            
        self.reb = 0
            
    # drop stocks which don't have the information we need.
    # you can try replacing those factor with your own factors here
    
        filtered_fine = [x for x in fine if x.ValuationRatios.FCFRatio]
                                        #and x.ValuationRatios.PERatio]
                                        
        self.Log('remained to select %d'%(len(filtered_fine)))
        
        # rank stocks by three factor.
        sortedByfactor1 = sorted(filtered_fine, key=lambda x: x.ValuationRatios.FCFRatio)        
        #sortedByfactor2 = sorted(filtered_fine, key=lambda x: x.ValuationRatios.PERatio)

        #sortedByfactor1 = sorted(filtered_fine, key=lambda x: x.OperationRatios.ROE.Value,reverse=True)
        #sortedByfactor2 = sorted(filtered_fine, key=lambda x: x.ValuationRatios.PSRatio)
        #sortedByfactor3 = sorted(filtered_fine, key=lambda x: x.ValuationRatios.BookValueYield)
        #sortedByfactor3 = sorted(filtered_fine, key=lambda x: x.ValuationRatios.FCFRatio)

        stock_dict = {}
        
        # assign a score to each stock, you can also change the rule of scoring here.
        for i,ele in enumerate(sortedByfactor1):
            rank1 = i
            #rank2 = sortedByfactor2.index(ele)
            #rank3 = sortedByfactor3.index(ele)
            score = sum([rank1])#*0.5+rank2*0.5])
            stock_dict[ele] = score
        
        # sort the stocks by their scores
        self.sorted_stock = sorted(stock_dict.items(), key=lambda d:d[1],reverse=False)
        sorted_symbol = [x[0] for x in self.sorted_stock]

        # sotre the top stocks into the long_list and the bottom ones into the short_list
        self.long = [x for x in sorted_symbol[:self.num_fine]]
        self.short = [x for x in sorted_symbol[-self.num_fine:]]
        
 
        
        self.topFine = [i.Symbol for i in self.long + self.short]
        
        return self.topFine

    def OnData(self, data):
        pass
    
    def rebalance(self):
        if self.first_month == 0:
            self.first_month += 1
            return
    # if this month the stock are not going to be long/short, liquidate it.
        long_short_list = self.topFine
        for i in self.Portfolio.Values:
            if (i.Invested) and (i.Symbol not in long_short_list):
                self.Liquidate(i.Symbol)
                
    # Alternatively, you can liquidate all the stocks at the end of each month.
    # Which method to choose depends on your investment philosiphy 
    # if you prefer to realized the gain/loss each month, you can choose this method.
    
        #self.Liquidate()
        #
        #self.SetHoldings("SPY",1)
    # Assign each stock equally. Alternatively you can design your own portfolio construction method
        for i in self.long:
            self.SetHoldings(i.Symbol, 0.5/self.num_fine)
        
        for i in self.short:
            self.SetHoldings(i.Symbol, -0.5/self.num_fine)

        self.reb = 1