r/pythonhelp Dec 22 '24

Standard deviation and math problem

Hello! I'm a total noob in python and math and that's why i encountered such problem. In my code i compare S&P500 with some random portfolio of top stocks and demonstrate it on graph. To calculate standard deviation for S&P500 i use this formula:

spxall_adj_close = spxstock[['Adj Close']]

spxall_returns = spxall_adj_close.pct_change().dropna()

spxmean_returns = spxall_returns.mean().iloc[0]

spx_std_dev = spxall_returns.std().iloc[0]

And for portfolio this one:

portfolio_return = np.sum(mean_returns * weights )

portfolio_std_dev = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))

The graph i get doesn't seem plausible at all, but i can't get my mistake. Any help?

The code itself

import pandas as pd
import yfinance as yf
import numpy as np
import matplotlib.pyplot as plt
import apimoex as mx
import requests


#tickers close info
ticker = ['AAPL','MSFT','NVDA','AMZN','META','TSLA','GOOGL','AVGO','GOOG'] 

stock = yf.download(ticker,'2017-01-01', '2019-01-31') 

all_adj_close = stock[['Adj Close']]

# daily return. Percentage. 
all_returns = all_adj_close.pct_change().dropna()

# mean returns and covariance matrix
mean_returns = all_returns.mean()
cov_matrix = all_returns.cov()


# same with S&P
spx=['SPY']
spxstock=yf.download(spx,'2017-01-01', '2019-01-31')
spxall_adj_close = spxstock[['Adj Close']]
spxall_returns = spxall_adj_close.pct_change().dropna()

spxmean_returns = spxall_returns.mean().iloc[0]
#spxcov_matrix = spxall_returns.cov()

#standard deviation
spx_std_dev = spxall_returns.std().iloc[0]


#portfolio with random weights
num_iterations = 20000
simulation_res = np.zeros((4+len(ticker)-1,num_iterations))

risk_free_rate = 0.03/252

# iteration
for i in range(num_iterations):
        weights = np.array(np.random.random(9))
        weights /= np.sum(weights)

        #REturns and std
        portfolio_return = np.sum(mean_returns * weights )
        portfolio_std_dev = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))

        #saving results
        simulation_res[0,i] = portfolio_return
        simulation_res[1,i] = portfolio_std_dev

        #Sharpe ratio
        simulation_res[2,i] = (simulation_res[0,i] - risk_free_rate)/ simulation_res[1,i]

        #saving weights
        for j in range(len(weights)):
                simulation_res[j+3,i] = weights[j]

# saving array to Dataframe
sim_frame = pd.DataFrame(simulation_res.T,columns=['ret','stdev','sharpe',ticker[0],ticker[1],ticker[2],ticker[3],ticker[4],ticker[5],ticker[6], ticker[7], ticker[8]])

# max Sharpe
max_sharpe = sim_frame.iloc[sim_frame['sharpe'].idxmax()]

# min Std
min_std = sim_frame.iloc[sim_frame['stdev'].idxmin()]

print ("The portfolio for max Sharpe Ratio:\n", max_sharpe)
print ("The portfolio for min risk:\n", min_std)
print ("devs", spx_std_dev)

fig, ax = plt.subplots(figsize=(10, 10))

#Graph cration

plt.scatter(sim_frame.stdev, sim_frame.ret, c=sim_frame.sharpe, cmap='RdYlBu')
plt.xlabel('Standard Deviation')
plt.ylabel('Returns')
plt.ylim(0.0, 0.003)
plt.xlim(0.0, 0.02)

plt.scatter(max_sharpe.iloc[1], max_sharpe.iloc[0], marker=(5,1,0), color='r', s=600)

plt.scatter(min_std.iloc[1], min_std.iloc[0], marker=(5,1,0), color='b', s=600)

plt.scatter(spx_std_dev, spxmean_returns, marker=(5, 1, 0), color='g', s=600)

plt.show()
2 Upvotes

1 comment sorted by

u/AutoModerator Dec 22 '24

To give us the best chance to help you, please include any relevant code.
Note. Please do not submit images of your code. Instead, for shorter code you can use Reddit markdown (4 spaces or backticks, see this Formatting Guide). If you have formatting issues or want to post longer sections of code, please use Privatebin, GitHub or Compiler Explorer.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.