Dead Kernel with redistribute_weights(data, weight_limit=0.10) in HRP

Hi, I have tweaked the code you provided in the course, and it seemd to work until the "redistribute_weights" function is used to set a weight limit to my problem. Then my kernel dies when I run the formula.



This is the tweaked code used for the formula:

 

def redistribute_weights(data, weight_limit=0.10):
    """
    Code to redistribute weights between funds.
    """

    """Check if weight redistribution is possible"""
    # Get the total number of funds available
    num_funds = len(data.index)

    # Calculate the minimum number of funds needed for the given weight_limit
    num_funds_needed = int(1 / weight_limit)

    # Proceed if sufficient funds are available
    if (num_funds >= num_funds_needed):

        # Sort the dataframe to get the fund with maximum weight
        data = data.sort_values(by=data.columns.to_list(), ascending=False)

        # Base case
        # If fund with maximum weights is less than or equal to the 
        # weight_limit, return data
        if data.iloc[0][0] <= weight_limit:
            data.rename(columns={"Original": "New"}, inplace=True)
            return data

        # If fund with maximum weights is greater than the weight_limit, 
        # reassign weights
        if data.iloc[0][0] > weight_limit:
            # Calculate excess weight
            excess_weight = data.iloc[0][0] - weight_limit

            # Assign weight_limit to fund with excess weight
            data.iloc[0][0] = weight_limit

            # Calculate ratio of distribution of excess weight
            ratio = (data.iloc[1:] / data.iloc[1:].sum())

            # Distribute excess weight
            excess_weight_distribution = data.iloc[1:] + (ratio * excess_weight)

            # Update the weights
            data.iloc[1:, :] = excess_weight_distribution

        return redistribute_weights(data)

    else:
        print(
            f"Weight redistribution is not possible. Add {num_funds_needed - num_funds} more funds or reduce the weight limit to {round(1 / num_funds, 2)}.")
        return data

 





And this is the code that causes the kernel to die:

 

# Calculating the new weights after redistribution
new_weights = redistribute_weights(weights, weight_limit=0.10)

Can you help me please?

Thanks!

Luca

Hello Luca, 



I ran the 'redistribute_weights' function you have shared in my local system and it gave me new weights without any kernel issues. 

Can you share your 'weights' CSV file? I will try running the 'redistribute_weights' function on the 'weights' CSV file in my local system  and check if the issue exists.



Thanks

Hello Varun,



I have tried to re-run the same function with a new weight limit equal to 0.15 on a portfolio of 7 assets, and I am experiencing the same issue again. The weights used are stored in a DataFrame and are: 



weights_hrp =



CDF: 0.07

MTR: 0.09

NAF: 0.04

SEB: 0.12

ADT: 0.06

AEA: 0.03

BSF: 0.6



These are "re-tickerized" funds, not stocks tickers.



And this is the function code snippet:

 

def redistribute_weights(data, weight_limit=0.15):
    """
    Code to redistribute weights between stocks.
    """

    """Check if weight redistribution is possible"""
    # Get the total number of stocks available
    num_stocks = len(data.index)

    # Calculate the minimum number of stocks needed for the given weight_limit
    num_stocks_needed = int(1 / weight_limit)

    # Proceed if sufficient stocks are available
    if (num_stocks >= num_stocks_needed):

        # Sort the dataframe to get the stock with maximum weight
        data = data.sort_values(by=data.columns.to_list(), ascending=False)

        # Base case
        # If stock with maximum weights is less than or equal to the 
        # weight_limit, return data
        if data.iloc[0][0] <= weight_limit:
            data.rename(columns={"Original": "New"}, inplace=True)
            return data

        # If stock with maximum weights is greater than the weight_limit, 
        # reassign weights
        if data.iloc[0][0] > weight_limit:
            # Calculate excess weight
            excess_weight = data.iloc[0][0] - weight_limit

            # Assign weight_limit to stock with excess weight
            data.iloc[0][0] = weight_limit

            # Calculate ratio of distribution of excess weight
            ratio = (data.iloc[1:] / data.iloc[1:].sum())

            # Distribute excess weight
            excess_weight_distribution = data.iloc[1:] + (ratio * excess_weight)

            # Update the weights
            data.iloc[1:, :] = excess_weight_distribution

        return redistribute_weights(data)

    else:
        print(
            f"Weight redistribution is not possible. Add {num_stocks_needed - num_stocks} more stocks or reduce the weight limit to {round(1 / num_stocks, 2)}.")
        return data

Then, when I run the following line of code I got the error killing my kernel:
 
# Calculating the new weights after redistribution
new_weights = redistribute_weights(weights_hrp, weight_limit=0.15)

It tells me: "The kernel appears to have died. It will restart automatically."

Can you please help me? 

Luca 

Hello Luca, 

The code has been updated in the course and with the updated code, you will be able to generate new weights for your HRP portfolio. You can find the code here.



Here is the output for your data with re-assigned weights. 





Here is an observation of the result.

As you can see, the first six contracts have maximum weightage allowed and the rest was allocated to 'AEA'. This is (almost) equal weightage allocation. So, this negates the purpose of using HRP for weight allocation. 

Hence, in your case, if you want to retain the HRP weights and maintain an optimum portfolio, you can't have the weights limitation of 15%.

Hope this helps!