Overall Statistics |
Total Trades 534 Average Win 0.30% Average Loss -0.27% Compounding Annual Return -7.435% Drawdown 5.700% Expectancy -0.041 Net Profit -3.207% Sharpe Ratio -0.635 Loss Rate 55% Win Rate 45% Profit-Loss Ratio 1.12 Alpha 0.147 Beta -11.908 Annual Standard Deviation 0.1 Annual Variance 0.01 Information Ratio -0.812 Tracking Error 0.1 Treynor Ratio 0.005 Total Fees $534.00 |
from clr import AddReference AddReference("System") AddReference("QuantConnect.Common") AddReference("QuantConnect.Indicators") AddReference("QuantConnect.Algorithm.Framework") from QuantConnect.Data.UniverseSelection import * from QuantConnect.Indicators import ExponentialMovingAverage from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel import decimal as d class UniverseSelectionModel(FundamentalUniverseSelectionModel): def __init__(self, universeCount = 20, filterFineData = True, universeSettings = None, securityInitializer = None): super().__init__(filterFineData, universeSettings, securityInitializer) self.universeCount = universeCount self.resolution = Resolution.Daily # Holds our coarse fundamental indicators by symbol self.calculations = {} def SelectCoarse(self, algorithm, coarse): '''Performs coarse selection based on price and volume''' # We are going to use a dictionary to refer the object that will keep the calculations for cf in coarse: if cf.Symbol not in self.calculations: self.calculations[cf.Symbol] = SymbolData(algorithm, cf.Symbol, self.resolution) #self.calculations[cf.Symbol].RegisterIndicators(algorithm, self.resolution) self.calculations[cf.Symbol].update(cf.EndTime, cf.Price, cf.Volume, cf.DollarVolume, cf.HasFundamentalData) # Updates the SymbolData object with price, volume, dollar volume, etc #avg = self.calculations[cf.Symbol] #avg.RegisterIndicators(algorithm) #avg.update(cf.EndTime, cf.Price, cf.Volume, cf.DollarVolume, cf.HasFundamentalData) # Filter the values of the dict based on chosen criteria. filtered_coarse = list(filter(lambda x: (x.is_uptrend and x.fundamentaldata), self.calculations.values())) # Sort the values of the dict: we want those with greater DollarVolume sorted_coarse = sorted(filtered_coarse, key = lambda x: x.dollarvolume, reverse = True) #for x in sorted_values[:self.universeCount]: # algorithm.Log(str(algorithm.Time) + 'symbol: ' + str(x.symbol.Value) # + ' close price: ' + str(x.price) # + ' volume: ' + str(x.volume) # + ' dollar volume: ' + str(x.dollarvolume) # + ' mean price: ' + str(x.priceSMA.Current.Value) # + ' mean vol: ' + str(x.volSMA.Current.Value)) # Select Top Stocks (based on universeCount) return [ x.Symbol for x in sorted_coarse[:self.universeCount] ] def SelectFine(self, algorithm, fine): '''Performs fine selection: The company's headquarter must in the U.S. The stock must be traded on either the NYSE or NASDAQ At least half a year since its initial public offering The stock's market cap must be greater than 500 million''' filtered_fine = list(filter(lambda x: (x.CompanyReference.CountryId == "USA" and (x.CompanyReference.PrimaryExchangeID == "NYS" or x.CompanyReference.PrimaryExchangeID == "NAS") and (algorithm.Time - x.SecurityReference.IPODate).days > 180 and x.EarningReports.BasicEPS.TwelveMonths > 0 and x.ValuationRatios.PERatio > 0 and x.EarningReports.BasicAverageShares.ThreeMonths > 0), fine)) #and x.EarningReports.BasicAverageShares.ThreeMonths * (x.EarningReports.BasicEPS.TwelveMonths * x.ValuationRatios.PERatio) > 5e8), fine)) # Sort the values of the dict by market cap sorted_fine = sorted(filtered_fine, key = lambda x: x.EarningReports.BasicAverageShares.ThreeMonths * (x.EarningReports.BasicEPS.TwelveMonths * x.ValuationRatios.PERatio), reverse = True) # Select Top Stocks (up to UniverseCount) return [ x.Symbol for x in filtered_fine[:20] ] # class used to improve readability of the coarse selection function class SymbolData: def __init__(self, algorithm, symbol, resolution): self.Symbol = symbol #self.Consolidator = None self.priceWin = RollingWindow[float](10) self.priceSMA10 = SimpleMovingAverage(10) self.priceSMA50 = SimpleMovingAverage(50) self.priceSMA200 = SimpleMovingAverage(200) self.volSMA = SimpleMovingAverage(50) self.is_uptrend = False #self.Consolidator = algorithm.ResolveConsolidator(self.Symbol, resolution) #algorithm.RegisterIndicator(self.Symbol, self.priceSMA10, self.Consolidator) #smaName = algorithm.CreateIndicatorName(self.Symbol, "SimpleMovingAverage{}".format(10), resolution) #self.SMA = SimpleMovingAverage(smaName, 10) #algorithm.RegisterIndicator(self.Symbol, self.SMA, self.Consolidator) #def RegisterIndicators(self, algorithm, resolution): #self.Consolidator = algorithm.ResolveConsolidator(self.Symbol, resolution) #algorithm.RegisterIndicator(self.Symbol, self.priceSMA10, self.Consolidator) #algorithm.RegisterIndicator(self.symbol, self.priceSMA50, self.Consolidator) #algorithm.RegisterIndicator(self.symbol, self.priceSMA200, self.Consolidator) #algorithm.RegisterIndicator(self.symbol, self.volSMA, self.Consolidator) def update(self, time, price, volume, dollarvolume, fundamentaldata): self.price = price self.volume = volume self.dollarvolume = dollarvolume self.fundamentaldata = fundamentaldata self.priceWin.Add(price) self.priceSMA10.Update(time, price) self.priceSMA50.Update(time, price) self.priceSMA200.Update(time, price) self.volSMA.Update(time, volume) # self.priceSMA200.IsReady if self.priceSMA10.IsReady and self.priceSMA50.IsReady and self.volSMA.IsReady and self.priceWin.IsReady: SMA10price = self.priceSMA10.Current.Value SMA50price = self.priceSMA50.Current.Value SMA200price = self.priceSMA200.Current.Value SMAvol = self.volSMA.Current.Value # Here we can add the criteria for our universe # > SMA200price self.is_uptrend = (SMA10price > SMA50price and price > 20 and price > SMA10price and price > max(self.priceWin) and price > (self.priceWin[1] + float(1)) and SMAvol > 500 and volume > (d.Decimal(1.5) * SMAvol))
from UniverseSelection import UniverseSelectionModel from AlphaCreation import ConstantAlphaModel from Portfolio.EqualWeightingPortfolioConstructionModel import EqualWeightingPortfolioConstructionModel from Execution.ImmediateExecutionModel import ImmediateExecutionModel from Risk.NullRiskManagementModel import NullRiskManagementModel from RiskManagement import PnLManagementModel class BasicTemplateFrameworkAlgorithm(QCAlgorithmFramework): def Initialize(self): # Set requested data resolution self.UniverseSettings.Resolution = Resolution.Minute self.SetStartDate(2018, 5, 1) # Set Start Date self.SetEndDate(2018, 10, 1) # Set End Date self.SetCash(10000) # Set Strategy Cash # Adding SPY Market to use in Schedule Function #self.AddEquity("SPY") # Scheduled Function to liquidate all positions 15 minutes before market close #self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.BeforeMarketClose("SPY", 15), self.rebalance) self.SetUniverseSelection(UniverseSelectionModel(universeCount = 5, filterFineData = False)) self.SetAlpha(ConstantAlphaModel()) self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel()) self.SetExecution(ImmediateExecutionModel()) #self.SetRiskManagement(NullRiskManagementModel()) self.SetRiskManagement(PnLManagementModel(maximumDrawdownPercent = 0.03, TakeProfitPercent = 0.1)) #def rebalance(self): #algorithm.Log(str(algorithm.Time) + 'Liquidating End Of Day: ' + str(security)) #self.Liquidate()
from clr import AddReference AddReference("System") AddReference("QuantConnect.Common") AddReference("QuantConnect.Algorithm") AddReference("QuantConnect.Algorithm.Framework") from QuantConnect import * from QuantConnect.Algorithm import * from QuantConnect.Algorithm.Framework import * from QuantConnect.Algorithm.Framework.Portfolio import PortfolioTarget from QuantConnect.Algorithm.Framework.Risk import RiskManagementModel class PnLManagementModel(RiskManagementModel): '''Provides an implementation of IRiskManagementModel that limits the drawdown per holding to the specified percentage''' def __init__(self, maximumDrawdownPercent = 0.05, TakeProfitPercent = 0.05): '''Initializes a new instance of the MaximumDrawdownPercentPerSecurity class Args: maximumDrawdownPercent: The maximum percentage drawdown allowed for any single security holding TakeProfitPercent: The take profit percentage for any single security holding''' self.maximumDrawdownPercent = -abs(maximumDrawdownPercent) self.TakeProfitPercent = abs(TakeProfitPercent) def ManageRisk(self, algorithm, targets): '''Manages the algorithm's risk at each time step Args: algorithm: The algorithm instance''' targets = [] for kvp in algorithm.Securities: security = kvp.Value if not security.Invested: continue pnl = security.Holdings.UnrealizedProfitPercent if pnl <= self.maximumDrawdownPercent: # Liquidate algorithm.Log(str(algorithm.Time) + 'Liquidating Due To MaxDrawdown: ' + str(security)) targets.append(PortfolioTarget(security.Symbol, 0)) elif pnl >= self.TakeProfitPercent: # Liquidate algorithm.Log(str(algorithm.Time) + 'Taking Profit: ' + str(security)) targets.append(PortfolioTarget(security.Symbol, 0)) return targets
from clr import AddReference AddReference("QuantConnect.Common") AddReference("QuantConnect.Algorithm") AddReference("QuantConnect.Algorithm.Framework") from QuantConnect import * from QuantConnect.Algorithm import * from QuantConnect.Algorithm.Framework import * from datetime import timedelta from QuantConnect.Algorithm.Framework.Alphas import AlphaModel, Insight, InsightType, InsightDirection class ConstantAlphaModel(AlphaModel): def __init__(self): self.period = timedelta(hours=5,minutes=30) self.securities = [] self.insightsTimeBySymbol = {} self.ShouldEmitInsight = True self.Name = 'ConstantAlphaModel' def Update(self, algorithm, data): insights = [] if self.ShouldEmitInsight: for security in self.securities: if security.Symbol.Value != "SPY": insights.append(Insight.Price(security.Symbol, self.period, InsightDirection.Up)) self.ShouldEmitInsight = False return insights def OnSecuritiesChanged(self, algorithm, changes): self.removedSecurities = [] for added in changes.AddedSecurities: self.securities.append(added) self.ShouldEmitInsight = True # this will allow the insight to be re-sent when the security re-joins the universe for removed in changes.RemovedSecurities: self.removedSecurities.append(removed) self.ShouldEmitInsight = True if removed in self.securities: self.securities.remove(removed) if removed.Symbol in self.insightsTimeBySymbol: self.insightsTimeBySymbol.pop(removed.Symbol)