Hi,

I have this code where I invest in the top 3 companies of NASDAQ by Market Cap. I want to try different portfolio distributions, so I import a csv with three columns, each has the corresponding portfolio percentage for each stock i.e 0.9, 0.1, 0.1 or 0.5, 0.2, 0.3. 

The problem is that when I compared the same algo with 1 stock (investing in the stock with greatest market cap in nasdaq) and the portfolio distribution (1, 0, 0) I don't get the same results…

I'm using SetHoldings to set the percentages. Here are both codes with results. Any help is appreciated.

First code with parameters symbols = 1 and count = 0

from AlgorithmImports import *
class MorningStarDataAlgorithm(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2009, 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 = int(self.GetParameter('symbols')) # Número de acciones en el portafolio
        self.AddUniverse(self.FundamentalSelection)
        self.Settings.FreePortfolioValuePercentage = 0.05

        self.Schedule.On(self.DateRules.On(self.EndDate), 
                 self.TimeRules.At(15, 55), 
                 self.Liquidate)

        self.changes = None
        self.i = int(self.GetParameter('count'))

    def FundamentalSelection(self, fundamental):
        selected = [c for c in fundamental if c.HasFundamentalData and c.SecurityReference.ExchangeId == "NAS"]
        sorted_by_mc = sorted(selected, key=lambda f: f.MarketCap, reverse=True)
        sorted_by_mc = sorted_by_mc[self.i:self.num_symbols+self.i]
        return [ f.Symbol for f in sorted_by_mc ]

    def OnData(self, data):
        # if we have no changes, do nothing
        if self.changes is None: return

        # liquidate removed securities
        for security in self.changes.RemovedSecurities:
            if security.Invested:
                self.Liquidate(security.Symbol)
                #self.Debug("Liquidated Stock: " + str(security.Symbol.Value))

        # we want 50% allocation in each security in our universe
        for security in self.changes.AddedSecurities:
            self.SetHoldings(security.Symbol, 1/self.num_symbols)
            #self.Debug("Bought Stock: " + str(security.Symbol.Value))

        self.changes = None
    
    def OnSecuritiesChanged(self, changes):
        self.changes = changes
        for security in self.changes.RemovedSecurities:
            self.Debug('Removed '+ str(security.Symbol))
        x = 1
        for security in self.changes.AddedSecurities:
            self.Debug('Added ' +str(x)+' '+ str(security.Symbol))
            x +=1
        

    #def Liquidate(self):
    #    self.Liquidate()

 

And the results

171657_1705619411.jpg

Second code i = 65

from AlgorithmImports import *
import pandas as pd
from io import StringIO
class MorningStarDataAlgorithm(QCAlgorithm):


    def Initialize(self):
        self.SetStartDate(2009, 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[i,'Number1']
        self.x2 = self.percentages.loc[i,'Number2']
        self.x3 = self.percentages.loc[i,'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"]
        sorted_by_mc = sorted(selected, key=lambda f: f.MarketCap, reverse=True)
        sorted_by_mc = sorted_by_mc[:self.num_symbols]
        return [ f.Symbol for f in sorted_by_mc ]


    def OnData(self, data):
        # if we have no changes, do nothing
        if self.changes is None: return
       
        # 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


        if len(self.active_securities)==3:
            self.Rebalance_weights()


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

And results

171657_1705619585.jpg

It doesnt even change at the same dates, I find it wierd.

 

Thaaanks