Overall Statistics
Total Trades
68
Average Win
4.01%
Average Loss
-3.01%
Compounding Annual Return
10.485%
Drawdown
24.800%
Expectancy
0.368
Net Profit
41.780%
Sharpe Ratio
0.529
Loss Rate
41%
Win Rate
59%
Profit-Loss Ratio
1.33
Alpha
0.222
Beta
-4.826
Annual Standard Deviation
0.238
Annual Variance
0.057
Information Ratio
0.446
Tracking Error
0.238
Treynor Ratio
-0.026
Total Fees
$483.50
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(2016, 1, 1)   
        self.SetEndDate(2019, 7, 1)         
        self.SetCash(100000)            
        self.UniverseSettings.Resolution = Resolution.Daily
        self.filtered_fine = None
        self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)
        self._NumCoarseStocks = 200
        self._NumStocksInPortfolio = 10
        self.SetBenchmark("SPY")
        # record the year that have passed since the algorithm starts
        self.year = -1
    
    def CoarseSelectionFunction(self, coarse):
        if self.Time.year == self.year: return []
        
        # 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) 
        top = sortedByDollarVolume[:self._NumCoarseStocks]
        return [i.Symbol for i in top]

    def FineSelectionFunction(self, fine):
        if self.Time.year == self.year:
            self.filtered_fine = []
        else:
            fine = [x for x in fine if (x.ValuationRatios.PERatio > 0)]
            for i in fine:
                i.PERatio = float(i.ValuationRatios.PERatio)
            sortedPERatio = sorted(fine, key=lambda x: x.PERatio)
            
            self.filtered_fine = [i.Symbol for i in sortedPERatio[:self._NumStocksInPortfolio]]
            
        return self.filtered_fine
    
    def OnSecuritiesChanged(self, change):
        if self.year == self.Time.year: return
        
        # liquidate securities that removed from the universe
        for security in change.RemovedSecurities:
            self.Liquidate(security.Symbol)
        # evenly invest on securities that newly added to the universe
        for security in change.AddedSecurities:
            self.SetHoldings(security.Symbol, 1/len(change.AddedSecurities))
        
        self.year = self.Time.year