robertmartin8 / PyPortfolioOpt

Financial portfolio optimisation in python, including classical efficient frontier, Black-Litterman, Hierarchical Risk Parity
https://pyportfolioopt.readthedocs.io/
MIT License
4.28k stars 930 forks source link

How to use PyPortfolioOpt with regular rebalancing of portfolio? #446

Closed Jelknw closed 2 years ago

Jelknw commented 2 years ago

For research for my master's program, I am currently running several portfolio optimizations. The idea is to rebalance the portfolio every month by means of a for loop that rebalances the portfolio if it is the first day of the month. So I loop over the rows of the data frame and when the indicator for the first day of the month is equal to 1 I want to run an optimization. At the rebalancing point, I create a subset of the total data frame to run the optimization with. In the end I want to save the retrieved weights in a data frame. However, the first rebalancing worked as intended but afterwards I receive the following error:

image image

I think it has something to do with the fact that I have to instantiate a new object for each loop, but I don't exactly know how to overcome this problem. I hope someone can help me with this problem. I also added a snippet of the base dataframe.

`# Loop over the rows of the base dataframe and rebalance if month_day count == 1 for index, row in df.iterrows():

Define the rebalancing point

if row['month_day_count'] == 1.0:

    # set the lookback period based on the index
    end_period = index
    start_period = index - 253

    # define the subset for the optimization, drop month day count and set index
    subset = df.loc[start_period:end_period]
    subset = subset.set_index('date')
    subset= subset.dropna(axis=1) # drop all stocks with no obs in the lookback period
    subset = subset.drop('month_day_count', axis =1) #drop the month counter

    if len(subset) < 253:
        pass
    else:

        # Start the optimization by maximizing the sharpe ratio
        # Estimate mean historical return and covariance matrix
        ret_test = mean_historical_return(subset, returns_data = True)

        # Sometimes the covariance matrix is non positive semidefinite, therefore solving this
        cov = risk_matrix(subset, method='sample_cov',returns_data=True )
        cov_good = fix_nonpositive_semidefinite(cov, fix_method = 'diag')

        # after having retrieved the covariance and mu it is now possible to start the optimization
        ef = EfficientFrontier(ret_test, cov_good, solver = 'SCS')
        weights = ef.max_sharpe()
        cleaned_weights = ef.clean_weights()     
else:
    #print('no rebalance')
    pass
`

df.csv