title: “vestibulum vitghgae dictum aliqua phasellus magnis at” date: 2018-05-30 tags: [“aliquam incididunt”, “notes”, “velit”] categories: [“aliquam auctor”, “do”] description: “vulputate sem sapien felis ullamcorper risus mi eu metus integer posuere fermentum” draft: false
import pandas as pd
import os
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
# Constants
data_folder='data_2020_09_25'
variable='Adj Close'
start_date = '2010-09-25'
end_date = '2020-09-25'
n_stocks=len(os.listdir(data_folder))
def get_stocks_data_from_folder(data_folder, variable, start_date, end_date):
files_list=os.listdir(data_folder)
df=pd.DataFrame()
for filename in files_list:
file_path=os.path.join(data_folder,filename)
col_name=filename.replace('.NS.csv','')
df[col_name]=read_stock_variable_from_CSV(file_path,variable,start_date, end_date)[variable]
return df
def read_stock_variable_from_CSV(file_path,variable,start_date, end_date):
data=pd.read_csv(file_path)
data['Date'] = data['Date'].apply(pd.to_datetime)
data.set_index('Date',inplace=True)
mask = (data.index >= start_date) & (data.index <= end_date)
return data.loc[mask][['Adj Close']]
Adjusted closing is closing price but it includes stock splitting, dividends, etc.
data_adj_close=get_stocks_data_from_folder(data_folder, 'Adj Close', start_date, end_date)
missing_values_count = data_adj_close.isnull().sum()
print(missing_values_count)
data_adj_close.dropna(inplace=True)
AXISBANK 8
DABUR 8
DRREDDY 8
ICICIBANK 8
INFY 8
RELIANCE 8
SBIN 8
SUNPHARMA 8
TCS 8
dtype: int64
data_adj_close.plot(figsize=(16,8))
<matplotlib.axes._subplots.AxesSubplot at 0x1219cbdf708>
daily_returns= data_adj_close.pct_change(1)
daily_returns.dropna(inplace=True)
daily_logreturns=np.log(1+daily_returns)
daily_logreturns['AXISBANK'].plot(figsize=(16,8))
<matplotlib.axes._subplots.AxesSubplot at 0x1219d46c048>
daily_logreturns['DABUR'].plot(figsize=(16,8))
<matplotlib.axes._subplots.AxesSubplot at 0x1219d4fcbc8>
daily_logreturns.plot(figsize=(16,8))
<matplotlib.axes._subplots.AxesSubplot at 0x1bc3ef49a08>
fig = plt.figure(figsize = (15,10))
ax = fig.gca()
daily_logreturns.hist(ax = ax,bins=100)
C:\Users\bharath\Anaconda3\lib\site-packages\ipykernel_launcher.py:3: UserWarning: To output multiple subplots, the figure containing the passed axes is being cleared
This is separate from the ipykernel package so we can avoid doing imports until
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x000001BC3D1DBA88>,
<matplotlib.axes._subplots.AxesSubplot object at 0x000001BC3D39A888>,
<matplotlib.axes._subplots.AxesSubplot object at 0x000001BC3D3D4308>],
[<matplotlib.axes._subplots.AxesSubplot object at 0x000001BC3D5BA0C8>,
<matplotlib.axes._subplots.AxesSubplot object at 0x000001BC3D5EEF08>,
<matplotlib.axes._subplots.AxesSubplot object at 0x000001BC3D623888>],
[<matplotlib.axes._subplots.AxesSubplot object at 0x000001BC3D65E6C8>,
<matplotlib.axes._subplots.AxesSubplot object at 0x000001BC3D695548>,
<matplotlib.axes._subplots.AxesSubplot object at 0x000001BC3D6A0C88>]],
dtype=object)
daily_logreturns.mean()*252 # per year
AXISBANK 0.059558
DABUR 0.168364
DRREDDY 0.133080
ICICIBANK 0.107442
INFY 0.184585
RELIANCE 0.164989
SBIN 0.014902
SUNPHARMA 0.100159
TCS 0.193752
dtype: float64
daily_logreturns.cov()*252 # per year
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
def get_portfolio_return(weights, daily_logreturns):
return np.sum(daily_logreturns.mean()*weights)*252 # per year - 252 trading days
def get_portfolio_variance(weights, daily_logreturns):
return np.sqrt(np.dot(weights.T, np.dot(daily_logreturns.cov()*252,weights)))
def generate_porfolios_stats_randomly(daily_logreturns, n_portfolios):
n_stocks=len(daily_logreturns.columns)
pf_returns=[]
pf_variances=[]
for i in range(n_portfolios):
weights=np.random.random(n_stocks)
weights /= np.sum(weights)
pf_returns.append(get_portfolio_return(weights, daily_logreturns))
pf_variances.append(get_portfolio_variance(weights, daily_logreturns))
pf_returns=np.array(pf_returns)
pf_variances=np.array(pf_variances)
return pf_returns, pf_variances
returns, variances = generate_porfolios_stats_randomly(daily_logreturns, 10000)
def plot_portfolios(pfreturns,pfvariances):
plt.figure(figsize = (15,8))
plt.scatter(pfvariances, pfreturns,c=pfreturns/pfvariances, marker='o' , edgecolor='black')
plt.grid(True)
plt.xlabel('Expected Variance')
plt.ylabel('Expected Return')
plt.colorbar(label= 'Sharp Ratio')
plt.show()
plot_portfolios(returns,variances)
def get_portfolio_stats(weights, daily_logreturns):
pf_return=get_portfolio_return(weights, daily_logreturns)
pf_variance=get_portfolio_variance(weights, daily_logreturns)
return np.array([pf_return, pf_variance, pf_return/pf_variance])
def get_portfolio_sharp_ration(weights, daily_logreturns):
return -get_portfolio_stats(weights, daily_logreturns)[2]
from scipy.optimize import minimize
def optimize_portfolio(daily_logreturns):
n_stocks=len(daily_logreturns.columns)
bounds = tuple((0,1) for x in range(n_stocks))
con=({'type':'eq','fun': lambda x: np.sum(x)-1})
weights=np.random.random(n_stocks)
weights /= np.sum(weights)
optimum_pf=minimize(fun=get_portfolio_sharp_ration, x0=weights, args=daily_logreturns, bounds=bounds, method='SLSQP', constraints=con)
return optimum_pf
opt_pf=optimize_portfolio(daily_logreturns)
print('Optimal weights:',opt_pf['x'].round(3))
Optimal weights: [0. 0.299 0.152 0. 0.131 0.129 0. 0. 0.29 ]
AXISBANK DABUR DRREDDY ICICIBANK INFY RELIANCE SBIN SUNPHARMA TCS
# optimum portfolio statistics
opt_pf_stats=get_portfolio_stats(opt_pf['x'],daily_logreturns)
print('Expected return, Volatility and Sharp ratio:',opt_pf_stats)
Expected return, Volatility and Sharp ratio: [0.17205126 0.16731228 1.02832414]
def plot_optimum_portfolios(pfreturns,pfvariances):
plt.figure(figsize = (15,8))
plt.scatter(pfvariances, pfreturns,c=pfreturns/pfvariances, marker='o' , edgecolor='black')
plt.plot(opt_pf_stats[1],opt_pf_stats[0],'g*', markersize=20)
plt.grid(True)
plt.xlabel('Expected Variance')
plt.ylabel('Expected Return')
plt.colorbar(label= 'Sharp Ratio')
plt.show()
plot_optimum_portfolios(returns,variances)