Overall Statistics |
Total Trades 70 Average Win 1.25% Average Loss -1.17% Compounding Annual Return 0.816% Drawdown 9.800% Expectancy -0.029 Net Profit 0.816% Sharpe Ratio 0.106 Probabilistic Sharpe Ratio 14.113% Loss Rate 53% Win Rate 47% Profit-Loss Ratio 1.07 Alpha -0.07 Beta 0.409 Annual Standard Deviation 0.104 Annual Variance 0.011 Information Ratio -1.647 Tracking Error 0.114 Treynor Ratio 0.027 Total Fees $72.92 Estimated Strategy Capacity $8700000.00 Lowest Capacity Asset ROL R735QTJ8XC9X |
from AlgorithmImports import * from datetime import timedelta, datetime from QuantConnect.Data.UniverseSelection import * from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel from Execution.ImmediateExecutionModel import ImmediateExecutionModel from Portfolio.EqualWeightingPortfolioConstructionModel import EqualWeightingPortfolioConstructionModel class Third_Attempt(QCAlgorithm): def Initialize(self): self.SetStartDate(2021, 1, 1) # Set Start Date self.SetEndDate(2022, 1, 1) # Set Start Date self.SetCash(100000) # Set Strategy Cash self.AddUniverseSelection(Highperformance()) self.UniverseSettings.Resolution = Resolution.Daily self.AddAlpha(BuyPerformance()) self.SetPortfolioConstruction(PortfolioBuilder()) #self.AddRiskManagement(Trailing_SL_TP()) self.SetExecution(ImmediateExecutionModel()) class Highperformance (FundamentalUniverseSelectionModel): def __init__(self): super().__init__( True, None) self.lastMonth = -1 #creating the SPY symbol (for the index) self.spy = Symbol.Create('SPY', SecurityType.Equity, Market.USA) def SelectCoarse(self, algorithm, coarse): #run the algorithm once a month, return Universe.Unchanged in case we are looking at exactly the same month if algorithm.Time.month == self.lastMonth or not algorithm.TradingCalendar.GetTradingDay().BusinessDay: return Universe.Unchanged self.lastMonth = algorithm.Time.month sortedByVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True) filteredByFundamentals = [x.Symbol for x in sortedByVolume if x.HasFundamentalData] return filteredByFundamentals + [self.spy] def SelectFine(self, algorithm, fine): sorted_high = sorted([x for x in fine if x.MarketCap > 2e9 and 0.5 > x.OperationRatios.AVG5YrsROIC.FiveYears > 0.20 and 50 > x.ValuationRatios.PERatio > 20 and x.AssetClassification.MorningstarSectorCode != MorningstarSectorCode.FinancialServices and x.AssetClassification.MorningstarSectorCode != MorningstarSectorCode.Healthcare], key = lambda x: x.ValuationRatios.PERatio, reverse=True) #fundamental_universe = [x.Symbol for x in sorted_high[:5]] + [self.spy] return [x.Symbol for x in sorted_high[:5]] + [self.spy] class BuyPerformance(AlphaModel): def __init__(self): self.lastMonth = -1 self.newAdds = [] self.spy = Symbol.Create('SPY', SecurityType.Equity, Market.USA) def Update(self, algorithm, data): if algorithm.Time.month == self.lastMonth: return [] self.lastMonth = algorithm.Time.month insights = [] #printing the time (for troubleshooting purposes) algorithm.Debug(str(algorithm.Time)) # Generate Pos (+) insight if the symbol has been added to 'newAdds', has data to trade and has not been invested before for added in self.newAdds: if not algorithm.Securities[added].Invested and algorithm.Securities[added].HasData and algorithm.Securities[added].IsTradable: algorithm.Debug('Positive Insight : ' + str(added)) if added not in data.Bars: continue insights.append(Insight(added, timedelta(30), InsightType.Price, InsightDirection.Up)) # Generate Flat insight if the symbol is already in the Portfolio, has been invested and it's not in newadds for x in algorithm.Portfolio: holding = x.Value symbol = holding.Symbol if holding.Invested and (symbol not in self.newAdds): if symbol not in data.Bars: continue insights.append(Insight(symbol, timedelta(30), InsightType.Price, InsightDirection.Flat)) return insights def OnSecuritiesChanged(self, algorithm, changes): # When assets are added to the universe, they will trigger OnSecuritiesChanged() event. #From there, you can initialize any state or history required for the Alpha Model algorithm.Debug('\n -----ALPHA MODEL ----: ' + str(algorithm.Time)) # Securities added into the universe will be added to self.newAdds for security in changes.AddedSecurities: symbol = security.Symbol if (symbol not in self.newAdds) and (symbol != self.spy): algorithm.Debug('added symbol : ' + str(symbol)) self.newAdds.append(symbol) # Securities removed from the universe will be removed from self.newAdds for security in changes.RemovedSecurities: symbol = security.Symbol if symbol in self.newAdds and (symbol != self.spy): algorithm.Debug('removed symbol symbol : ' + str(symbol)) self.newAdds.remove(symbol) #Until now we keep excluding the index SPY. We will execute the trade in the portfolio builder class PortfolioBuilder(PortfolioConstructionModel): def __init__(self): self.lastMonth = -1 self.spy = Symbol.Create('SPY', SecurityType.Equity, Market.USA) def CreateTargets (self, algorithm, insights): if not algorithm.Time.month == self.lastMonth: total_equity = algorithm.Portfolio.TotalPortfolioValue else: return [] self.lastMonth = algorithm.Time.month algorithm.Debug('\n -----PORTFOLIO CONSTRUCTION ----: ' + str(algorithm.Time)) # Create a list of PortfolioTarget objects from Insights (just for symbols, excluding SPY) target_array = [] target = None new = [] #I am creating a vector of new symbols added to the algorithm # i will use this vector 'new' to find the lentgh and allocate the right % of the portfolio for insight in insights: if not algorithm.Securities[insight.Symbol].Invested: new.append(insight.Symbol) for insight in insights: if insight.Direction == InsightDirection.Flat: target = PortfolioTarget(insight.Symbol, 0) #Generate the sell order on the flat insight if insight.Direction == InsightDirection.Up: #Calculate shares using the half Portfolio value divided in equal amount with the number of symbols recently added. target = PortfolioTarget.Percent(algorithm, insight.Symbol, 1/(2*len(new))) if target is not None: target_array.append(target) #Now i will create the target for the index 'SPY' who's shorting the other half of the portfolio value for x in algorithm.ActiveSecurities: holding = x.Value symbol = holding.Symbol if not holding.Invested and symbol == self.spy: target = PortfolioTarget.Percent(algorithm, symbol, -0.5) target_array.append(target) return target_array ''' class Trailing_SL_TP(RiskManagementModel): def __init__(self): pass def ManageRisk(self, algorithm, targets): pass '''