Overall Statistics |
Total Trades 32 Average Win 56.33% Average Loss -22.20% Compounding Annual Return 5.452% Drawdown 85.600% Expectancy 1.211 Net Profit 254.755% Sharpe Ratio 0.202 Sortino Ratio 0.223 Probabilistic Sharpe Ratio 0.001% Loss Rate 38% Win Rate 62% Profit-Loss Ratio 2.54 Alpha 0.008 Beta 0.88 Annual Standard Deviation 0.262 Annual Variance 0.068 Information Ratio 0.011 Tracking Error 0.172 Treynor Ratio 0.06 Total Fees $244.56 Estimated Strategy Capacity $130000000.00 Lowest Capacity Asset AAPL R735QTJ8XC9X Portfolio Turnover 0.35% |
from AlgorithmImports import * import pandas as pd from io import StringIO class MorningStarDataAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2000, 1, 1) # Cambiar fechas en las que quieres que corra self.SetEndDate(2023, 11, 1) self.SetCash(100000) self.UniverseSettings.Resolution = Resolution.Hour self.SetBenchmark("QQQ") self.num_symbols = 3 # Número de acciones en el portafolio self.AddUniverse(self.FundamentalSelection) self.Settings.FreePortfolioValuePercentage = 0.05 self.Settings.MinimumOrderMarginPortfolioPercentage = 0 self.Schedule.On(self.DateRules.On(self.EndDate), self.TimeRules.At(15, 55), self.Liquidate) self.changes = None #i = int(self.GetParameter('i')) self.percentages = self.get_text() self.x1 = self.percentages.loc[65,'Number1'] self.x2 = self.percentages.loc[65,'Number2'] self.x3 = self.percentages.loc[65,'Number3'] self.Debug('1st stock percentage '+str(self.x1)) self.Debug('2nd stock percentage '+str(self.x2)) self.Debug('3rd stock percentage '+str(self.x3)) self.e1 = None self.e2 = None self.e3 = None self.sorted_added_securities = [] self.active_securities = [] def FundamentalSelection(self, fundamental): selected = [c for c in fundamental if c.HasFundamentalData and c.SecurityReference.ExchangeId == "NAS"] self.sorted_by_mc = sorted(selected, key=lambda f: f.MarketCap, reverse=True) self.sorted_by_mc = self.sorted_by_mc[:self.num_symbols] self.Log(f"Symbols: {[x.Symbol.Value for x in self.sorted_by_mc]}") return [ f.Symbol for f in self.sorted_by_mc ] def OnData(self, data): # if we have no changes, do nothing if self.changes is None and self.previous_sorted_by_mc == self.sorted_by_mc: return try: # liquidate removed securities for security in self.changes.RemovedSecurities: self.Liquidate(security.Symbol) if security.Symbol.Value == self.e1: self.Debug("Liquidated Stock 1: " + str(security.Symbol.Value)) self.e1 = None if security.Symbol.Value == self.e2: self.Debug("Liquidated Stock 2: " + str(security.Symbol.Value)) self.e2 = None if security.Symbol.Value == self.e3: self.Debug("Liquidated Stock 3: " + str(security.Symbol.Value)) self.e3 = None except: pass if len(self.active_securities)==3: self.Rebalance_weights() self.previous_sorted_by_mc = self.sorted_by_mc.copy() self.changes = None sorted_added_securities = [] def OnSecuritiesChanged(self, changes): self.changes = changes for security in self.changes.RemovedSecurities: self.Debug('Removed '+ str(security.Symbol)) if security in self.active_securities: self.active_securities.remove(security) for security in self.changes.AddedSecurities: self.active_securities.append(security) self.Debug('Added stock '+str(security.Symbol)) def Rebalance_weights(self): # Sort active securities by Market Cap self.active_securities = sorted(self.active_securities, key=lambda x: x.Fundamentals.MarketCap, reverse=True) self.Log(f"Inside Rebalance_weights: {[x.Symbol.Value for x in self.active_securities]}") # Set portfolio weights accordingly # Check if the security is already invested with that percentage if self.active_securities[0].Invested: self.Debug('is invested') percentage_invested_1 = self.Portfolio[self.active_securities[0].Symbol].Quantity * self.Securities[self.active_securities[0].Symbol].Price / self.Portfolio.TotalPortfolioValue if not percentage_invested_1 >= (self.x1-0.09): self.Debug('Port per 1 '+str(percentage_invested_1)) self.SetHoldings(self.active_securities[0].Symbol, self.x1) self.Debug("Bought Stock 1: " + str(self.active_securities[0].Symbol)) self.e1 = self.active_securities[0].Symbol.Value elif not self.active_securities[0].Invested: self.Debug('not invested') self.SetHoldings(self.active_securities[0].Symbol, self.x1) self.Debug("Bought Stock 1: " + str(self.active_securities[0].Symbol)) self.e1 = self.active_securities[0].Symbol.Value if self.active_securities[1].Invested: percentage_invested_2 = self.Portfolio[self.active_securities[1].Symbol].Quantity * self.Securities[self.active_securities[1].Symbol].Price / self.Portfolio.TotalPortfolioValue if percentage_invested_2 >= (self.x2-0.09): self.Debug('Port per 2 '+str(percentage_invested_2)) self.SetHoldings(self.active_securities[1].Symbol, self.x2) self.Debug("Bought Stock 2: " + str(self.active_securities[1].Symbol)) self.e2 = self.active_securities[1].Symbol.Value elif not self.active_securities[1].Invested: self.SetHoldings(self.active_securities[1].Symbol, self.x2) self.Debug("Bought Stock 2: " + str(self.active_securities[1].Symbol)) self.e2 = self.active_securities[1].Symbol.Value if self.active_securities[2].Invested: percentage_invested_3 = self.Portfolio[self.active_securities[2].Symbol].Quantity * self.Securities[self.active_securities[2].Symbol].Price / self.Portfolio.TotalPortfolioValue if percentage_invested_3 >= (self.x3-0.09): self.Debug('Port per 3 '+str(percentage_invested_3)) self.SetHoldings(self.active_securities[2].Symbol, self.x3) self.Debug("Bought Stock 3: " + str(self.active_securities[2].Symbol)) self.e3 = self.active_securities[2].Symbol.Value elif not self.active_securities[2].Invested: self.SetHoldings(self.active_securities[2].Symbol, self.x3) self.Debug("Bought Stock 3: " + str(self.active_securities[2].Symbol)) self.e3 = self.active_securities[2].Symbol.Value #def Liquidate(self): # self.Liquidate() def get_text(self): url = 'https://www.dropbox.com/scl/fi/cgcdnn328vi7mqwjsgoi6/portfolio_weights_1.csv?rlkey=1dam9mp6430gj4xt32qlpwjx6&dl=1' csv_data = self.Download(url) # Use pd.read_csv to directly read the CSV data into a DataFrame df = pd.read_csv(StringIO(csv_data), index_col=0) return df