Overall Statistics
Total Trades
188
Average Win
0.57%
Average Loss
-0.27%
Compounding Annual Return
3.038%
Drawdown
12.700%
Expectancy
1.184
Net Profit
34.914%
Sharpe Ratio
0.351
Probabilistic Sharpe Ratio
0.039%
Loss Rate
29%
Win Rate
71%
Profit-Loss Ratio
2.06
Alpha
0.028
Beta
0.003
Annual Standard Deviation
0.079
Annual Variance
0.006
Information Ratio
-0.589
Tracking Error
0.155
Treynor Ratio
10.681
Total Fees
$1341.85
from QuantConnect.Data.UniverseSelection import *
import math
import numpy as np
import pandas as pd
import scipy as sp

class PriceEarningsAnamoly(QCAlgorithm):

    def Initialize(self):

        self.SetStartDate(2010, 1, 1)   
        self.SetEndDate(2020, 1, 1)         
        self.SetCash(100000)
        self.SetBenchmark("SPY")
        
        self.UniverseSettings.Resolution = Resolution.Daily
        self.symbols = []
        
        self.spy = self.AddEquity("SPY", Resolution.Daily).Symbol
        
        self.AddEquity("SPY", Resolution.Daily)
        self.SpyMomentum = self.MOMP("SPY", 3, Resolution.Daily)
        self.SetWarmUp(3) 
        
        # record the year that have passed since the algorithm starts
        self.year = -1
        self._NumCoarseStocks = 200
        self._NumStocksInPortfolio = 10
        
        self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)
        
        
    def CoarseSelectionFunction(self, coarse):
        
        if self.Time.year == self.year:
            return self.symbols
        
        # drop stocks which have no fundamental data or have low price
        CoarseWithFundamental = [x for x in coarse if x.HasFundamentalData and x.Price > 5]
        sortedByDollarVolume = sorted(CoarseWithFundamental, key=lambda x: x.DollarVolume, reverse=False) 
        
        return [i.Symbol for i in sortedByDollarVolume[:self._NumCoarseStocks]]

    def FineSelectionFunction(self, fine):
        
        if self.Time.year == self.year:
            return self.symbols
       
        self.year = self.Time.year
    
        fine = [x for x in fine if x.ValuationRatios.PERatio> 0 and x.OperationRatios.RevenueGrowth.Value > 0]

        sortedPERatio = sorted(fine, key=lambda x: x.ValuationRatios.PERatio/x.OperationRatios.RevenueGrowth.Value)
        #sortedPEGRatio = sorted(PEGRatio)

        self.symbols = [i.Symbol for i in sortedPERatio[:self._NumStocksInPortfolio]]
        
        return self.symbols
    
    def OnSecuritiesChanged(self, change):
        
        # liquidate securities that removed from the universe
        for security in change.RemovedSecurities:
            if self.Portfolio[security.Symbol].Invested:
                self.Liquidate(security.Symbol)

        count = len(change.AddedSecurities)

        # evenly invest on securities that newly added to the universe
        for security in change.AddedSecurities:
            self.SetHoldings(security.Symbol, 1.0/count)
        
    def OnData(self, data):
        if self.SpyMomentum is None or not self.SpyMomentum.IsReady:
            return
        
        if self.Portfolio.Invested:
            if self.SpyMomentum.Current.Value < -0.1:
                self.Liquidate()