| 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()