You are on page 1of 6

05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook 05/09/2021 Portfolio Construction &

gine - Jupyter Notebook 05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook

In [3]: 1 # ticker list


2 s_ticker_list = ["ADANIPORTS","ASIANPAINT","AXISBANK","BAJAJ-AUTO","BAJAJFINSV","BAJFINANCE","BHARTIARTL",
Portfolio Construction & Optimization { Python } 3
4
"BPCL","BRITANNIA","CIPLA","COALINDIA","DIVISLAB","DRREDDY","EICHERMOT","GRASIM","HCLTECH"
"HDFC","HDFCBANK","HDFCLIFE","HEROMOTOCO","HINDALCO","HINDUNILVR","ICICIBANK","INDUSINDBK"
5 "INFY","IOC","ITC","JSWSTEEL","KOTAKBANK","LT","M&M","MARUTI","NESTLEIND","NTPC","ONGC",
In [ ]: 1 ​ 6 "POWERGRID","RELIANCE","SBILIFE","SBIN","SHREECEM","SUNPHARMA","TATACONSUM","TATAMOTORS",
7 "TATASTEEL","TCS","TECHM","TITAN","ULTRACEMCO","UPL","WIPRO"]
8 b_ticker = "NIFTY"
In [ ]: 1 ​
9 ​
10 # other inputs
In [ ]: 1 ​ 11 rf = 0.06
12 time = 252
13 simulations = 1000
Importing Libraries 14 investment = 1000000
15 ​
16 # cob dates
In [1]: 1 import pandas as pd
17 start_date = date(2017,1,1)
2 import numpy as np
18 end_date = date(2019,12,31)
3 from nsepy import get_history
4 from datetime import date, timedelta
5 import matplotlib.pyplot as plt
Extract Data
In [2]: 1 %matplotlib inline
In [4]: 1 #creating an empty dataframe & dictionary
2 s_ticker_spot_hist_dc = pd.DataFrame()
Feeder Pack 3 s_ticker_spot_hist_dc = {}
4 b_ticker_spot_hist_df = pd.DataFrame()
5 ​
6 for item in s_ticker_list:
7 s_ticker_spot_hist_dc[item] = get_history(symbol=item, start=start_date, end=end_date)
8 s_ticker_spot_hist_dc[item]['%Change'] = s_ticker_spot_hist_dc[item]['Close'].pct_change().fillna(0)
9 ​
10 b_ticker_spot_hist_df = get_history(symbol=b_ticker, start=start_date, end=end_date, index=True)
11 b_ticker_spot_hist_df['%Change'] = b_ticker_spot_hist_df['Close'].pct_change().fillna(0)

localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 1/23 localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 2/23

05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook 05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook

In [5]: 1 s_ticker_spot_hist_dc['HDFCLIFE'] In [6]: 1 b_ticker_spot_hist_df

Out[5]: Out[6]:
Prev Deliverable Open High Low Close Volume Turnover %Change
Symbol Series Open High Low Last Close VWAP Volume Turnover Trades %Deliverble %Chang
Close Volume
Date
Date
2017-01-02 8210.10 8212.00 8133.80 8179.50 122016111 5.255490e+10 0.000000
2017-
HDFCLIFE EQ 290.00 310.0 369.00 307.00 343.90 344.60 327.26 168836552 5.525288e+15 1177530 82044782 0.4859 0.00000 2017-01-03 8196.05 8219.10 8148.60 8192.25 131186021 6.053670e+10 0.001559
11-17

2017- 2017-01-04 8202.65 8218.50 8180.90 8190.50 136476345 6.543130e+10 -0.000214


HDFCLIFE EQ 344.60 344.7 358.90 344.00 355.00 355.35 353.18 14650240 5.174106e+14 166263 6761287 0.4615 0.03119
11-20
2017-01-05 8226.65 8282.65 8223.70 8273.80 163957452 8.180680e+10 0.010170
2017-
HDFCLIFE EQ 355.35 356.4 418.90 352.50 386.90 385.30 389.24 43078194 1.676786e+15 450090 11584111 0.2689 0.08428 2017-01-06 8281.85 8306.85 8233.25 8243.80 143689850 7.298740e+10 -0.003626
11-21
... ... ... ... ... ... ... ...
2017-
HDFCLIFE EQ 385.30 388.0 408.00 386.90 394.00 395.20 397.38 15227642 6.051231e+14 166870 3475999 0.2283 0.02569
11-22 12269.25 12283.70 12202.10 12214.55 470290298 1.386456e+11 -0.003931
2019-12-24
2017- 12211.85 12221.55 12118.85 12126.55 520326632 1.636231e+11 -0.007205
HDFCLIFE EQ 395.20 390.0 392.00 371.10 375.50 374.85 379.99 12300150 4.673873e+14 124472 6200309 0.5041 -0.05149 2019-12-26
11-23
2019-12-27 12172.90 12258.45 12157.90 12245.80 383788556 1.367620e+11 0.009834
... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2019-12-30 12274.90 12286.45 12213.80 12255.85 411084614 1.455673e+11 0.000821
2019-
HDFCLIFE EQ 616.15 618.1 627.60 613.40 624.50 625.30 621.48 2938173 1.826018e+14 63620 1429838 0.4866 0.01485
12-24 2019-12-31 12247.10 12247.10 12151.80 12168.45 426931711 1.481289e+11 -0.007131

2019-
HDFCLIFE EQ 625.30 627.9 639.00 623.10 636.60 635.60 631.25 3006668 1.897949e+14 58982 1433743 0.4769 0.01647
12-26 739 rows × 7 columns
2019-
HDFCLIFE EQ 635.60 639.0 639.00 628.55 630.05 631.40 631.79 2494965 1.576282e+14 72563 1514619 0.6071 -0.00660
12-27

2019- Risk (Standard Deviation) & Return (Mean) - Stocks | Benchmark


HDFCLIFE EQ 631.40 632.7 638.75 629.00 636.95 636.15 632.89 1799682 1.139002e+14 37683 1176305 0.6536 0.00752
12-30

2019- In [7]: 1 print("Benchmark Mean Return :", b_ticker_spot_hist_df['%Change'].mean()*time)


HDFCLIFE EQ 636.15 637.9 646.00 620.75 622.50 626.05 634.34 2217822 1.406856e+14 44539 960791 0.4332 -0.01587
12-31 2 print("Benchmark SD. :", b_ticker_spot_hist_df['%Change'].std()*np.sqrt(time))

521 rows × 15 columns Benchmark Mean Return : 0.14273263200168973


Benchmark SD. : 0.12061193399492835

localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 3/23 localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 4/23
05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook 05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook

In [8]: 1 s_ticker_ret_hist_df = pd.DataFrame() In [9]: 1 b_ret = b_ticker_spot_hist_df['%Change'][1:].mean()*time


2 s_ticker_rr_profile_df = pd.DataFrame() 2 b_sd = b_ticker_spot_hist_df['%Change'][1:].std()*np.sqrt(time)
3 ​ 3 b_sr = (b_ret - rf) / b_sd
4 for item in s_ticker_list: 4 b_portf_ret = b_ret * investment
5 s_ticker_ret_hist_df[item] = s_ticker_spot_hist_dc[item]["%Change"] 5 b_portf_sd = b_sd * investment
6 temp = pd.DataFrame({ 6 ​
7 "Mean": s_ticker_ret_hist_df[item].mean()*time, 7 print("Investment :", investment)
8 "SD": s_ticker_ret_hist_df[item].std()*np.sqrt(time) 8 print("Benchmark Return:", b_portf_ret)
9 },index=[item]) 9 print("Benchmark SD :", b_portf_sd)
10 s_ticker_rr_profile_df = s_ticker_rr_profile_df.append(temp)
11 s_ticker_ret_hist_df = s_ticker_ret_hist_df.fillna(0) Investment : 1000000
12 s_ticker_rr_profile_df Benchmark Return: 142926.03665209853
Benchmark SD : 120693.27749207916
Out[8]:
Mean SD

ADANIPORTS 0.146732 0.308613 In [10]: 1 weights = 1 / len(s_ticker_list)


2 weights = [weights] * len(s_ticker_list)
ASIANPAINT 0.254572 0.214106

AXISBANK 0.216748 0.279921 In [11]: 1 sp_ticker_ret_hist_df = pd.DataFrame()


2 sp_ticker_ret_hist_df["Portfolio"] = s_ticker_ret_hist_df.dot(weights)
BAJAJ-AUTO 0.093869 0.221231
3 ret = sp_ticker_ret_hist_df['Portfolio'].mean()*time
BAJAJFINSV 0.438334 0.294133 4 sd = sp_ticker_ret_hist_df['Portfolio'].std()*np.sqrt(time)
5 sr = (ret - rf) / sd
BAJFINANCE 0.593202 0.327144 6 portf_ret = ret * investment
0.186642 0.337235
7 portf_sd = sd * investment
BHARTIARTL
8 ​
BPCL 0.001328 0.412570 9 print("Investment :", investment)
10 print("Portfolio Return:", portf_ret)
BRITANNIA 0.103488 0.362333
11 print("Portfolio SD :", portf_sd)
CIPLA -0.028010 0.243157
Investment : 1000000
COALINDIA -0.086463 0.257124 Portfolio Return: 110739.97790607161
Portfolio SD : 129223.8925618024

Equally Weighted Portfolio vs. Benchmark | Risk-Return Profile | Sharpe Ratio


Comparison between Equally Weighted Portfolio vs. Benchmark

localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 5/23 localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 6/23

05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook 05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook

In [12]: 1 print("Investment :", investment) In [15]: 1 weights = np.random.random(len(s_ticker_list))


2 print("Portfolio Return:", b_portf_ret) 2 weights = weights / np.sum(weights)
3 print("Portfolio SD :", b_portf_sd) 3 weights
4 print("")
5 print("Investment :", investment) Out[15]: array([3.43202393e-02, 3.73588420e-02, 3.09804141e-02, 1.09797596e-02,
6 print("Portfolio Return:", portf_ret) 2.22771701e-02, 3.11769227e-02, 1.78243143e-02, 1.41896092e-02,
7 print("Portfolio SD :", portf_sd) 2.71338399e-02, 1.64737074e-03, 4.08975040e-03, 3.25742865e-02,
7.29800734e-03, 4.11945397e-02, 2.43061026e-02, 2.78889413e-02,
Investment : 1000000 3.45622359e-02, 1.60238492e-02, 2.00893618e-02, 9.18965145e-03,
Portfolio Return: 142926.03665209853 1.14254789e-02, 5.20727947e-03, 4.32708394e-03, 3.31171544e-02,
Portfolio SD : 120693.27749207916 8.43938446e-03, 3.11453830e-03, 4.13547152e-02, 3.51798196e-02,
2.77113950e-02, 1.18171337e-02, 2.99802996e-02, 4.06307783e-02,
Investment : 1000000 4.10726210e-04, 2.35103147e-03, 1.31846250e-02, 1.30824116e-02,
Portfolio Return: 110739.97790607161 2.37179901e-03, 2.17028977e-02, 3.14014757e-02, 8.19419247e-03,
Portfolio SD : 129223.8925618024 1.59742558e-02, 1.68434989e-02, 3.71841494e-02, 3.29669418e-02,
1.82567358e-02, 2.12414987e-02, 1.26945701e-02, 1.27666588e-02,
6.19054216e-05, 4.19003572e-02])
In [13]: 1 print("Benchmark SR:", b_sr)
2 print("Portfolio SR:", sr)
In [16]: 1 weights = np.random.random(len(s_ticker_list))
Benchmark SR: 0.6870808248416386 2 weights = weights / np.sum(weights)
Portfolio SR: 0.39265167532238515 3 sp_ticker_ret_hist_df = pd.DataFrame()
4 sp_ticker_ret_hist_df["Portfolio"] = s_ticker_ret_hist_df.dot(weights)
5 ret = sp_ticker_ret_hist_df['Portfolio'].mean()*time
Random Weighted Portfolio vs. Benchmark | Risk-Return Profile | Sharpe Ratio 6 sd = sp_ticker_ret_hist_df['Portfolio'].std()*np.sqrt(time)
7 sr = (ret - rf) / sd
In [14]: 1 b_ret = b_ticker_spot_hist_df['%Change'][1:].mean()*time 8 portf_ret = ret * investment
2 b_sd = b_ticker_spot_hist_df['%Change'][1:].std()*np.sqrt(time) 9 portf_sd = sd * investment
3 b_sr = (b_ret - rf) / b_sd 10 ​
4 b_portf_ret = b_ret * investment 11 print("Investment :", investment)
5 b_portf_sd = b_sd * investment 12 print("Portfolio Return:", portf_ret)
6 ​ 13 print("Portfolio SD :", portf_sd)
7 print("Investment :", investment)
Investment : 1000000
8 print("Benchmark Return:", b_portf_ret) Portfolio Return: 116988.15937315492
9 print("Benchmark SD :", b_portf_sd)
Portfolio SD : 127452.39709462825
Investment : 1000000
Benchmark Return: 142926.03665209853
Benchmark SD : 120693.27749207916 Comparison between Random Weighted Portfolio vs. Benchmark

localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 7/23 localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 8/23
05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook 05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook

In [17]: 1 print("Investment :", investment) In [39]: 1 sp_ticker_ret_simu_df = pd.DataFrame()


2 print("Portfolio Return:", b_portf_ret) 2 portf_optimum = pd.DataFrame()
3 print("Portfolio SD :", b_portf_sd) 3 ​
4 print("") 4 for i in range(simulations):
5 print("Investment :", investment) 5 weights = np.random.random(len(s_ticker_list))
6 print("Portfolio Return:", portf_ret) 6 weights = weights / np.sum(weights)
7 print("Portfolio SD :", portf_sd) 7
8 portf_ret_simu_df = pd.DataFrame()
Investment : 1000000 9 portf_ret_simu_df = s_ticker_ret_hist_df.dot(weights)
Portfolio Return: 142926.03665209853 10
Portfolio SD : 120693.27749207916 11 ret = portf_ret_simu_df.mean()
12 sd = portf_ret_simu_df.std()
Investment : 1000000 13 sr = (ret - (rf/252)) / sd
Portfolio Return: 116988.15937315492 14
Portfolio SD : 127452.39709462825 15 temp1 = pd.DataFrame({
16 'Portfolio Return': ret,
17 'Portfolio SD': sd,
18 'Portfolio SR': sr,
In [18]: 1 print("Benchmark SR:", b_sr)
19 }, index=[0])
2 print("Portfolio SR:", sr)
20 sp_ticker_ret_simu_df = sp_ticker_ret_simu_df.append(temp1)
Benchmark SR: 0.6870808248416386 21 ​
Portfolio SR: 0.4471328956711855 22 portf_optimum = sp_ticker_ret_simu_df.sort_values(by="Portfolio SR", ascending=False)
23 portf_ret_p = portf_optimum.iloc[0,0]
24 portf_sd_p = portf_optimum.iloc[0,1]
25 portf_sr_p = portf_optimum.iloc[0,2]
Simulator: Optimized Portfolio vs. Benchmark | Risk-Return Profile | Sharpe Ratio 26 ​
27 portf_ret = portf_ret_p * time * investment
In [19]: 1 b_ret = b_ticker_spot_hist_df['%Change'][1:].mean()*time 28 portf_sd = portf_sd_p * np.sqrt(time) * investment
2 b_sd = b_ticker_spot_hist_df['%Change'][1:].std()*np.sqrt(time) 29 portf_sr = ((portf_ret_p * time) - rf) / (portf_sd_p * np.sqrt(time))
3 b_sr = (b_ret - rf) / b_sd 30 ​
4 b_portf_ret = b_ret * investment 31 print("Investment :", investment)
5 b_portf_sd = b_sd * investment 32 print("Portfolio Return:", portf_ret)
6 ​ 33 print("Portfolio SD :", portf_sd)
7 print("Investment :", investment)
8 print("Benchmark Return:", b_portf_ret) Investment : 1000000
9 print("Benchmark SD :", b_portf_sd) Portfolio Return: 157623.43471432617
Portfolio SD : 126338.35300157545
Investment : 1000000
Benchmark Return: 142926.03665209853
Benchmark SD : 120693.27749207916
Kickoff
localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 9/23 localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 10/23

05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook 05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook

In [ ]: 1 portf_optimum['Portfolio Return'] = portf_optimum['Portfolio Return'] * time In [42]: 1 plt.figure(figsize=(20,10))


2 portf_optimum['Portfolio SD'] = portf_optimum['Portfolio SD'] * np.sqrt(time) 2 plt.scatter(sp_ticker_ret_simu_df["Portfolio SD"]*np.sqrt(time), sp_ticker_ret_simu_df["Portfolio Return"]*t
3 portf_optimum 3 ​
4 plt.scatter(portf_optimum.iloc[0,1]*np.sqrt(time), portf_optimum.iloc[0,0]*time, color='b', s=250)
5 plt.annotate("---Portfolio", (portf_optimum.iloc[0,1]*np.sqrt(time), portf_optimum.iloc[0,0]*time), fontsize
Comparison between Simulated Portfolio vs. Benchmark 6 ​
7 plt.scatter(b_sd, b_ret, color='r', s=250)
8 plt.annotate("---Benchmark", (b_sd, b_ret), fontsize=12, color='black')
In [40]: 1 print("Investment :", investment) 9 ​
2 print("Portfolio Return:", b_portf_ret) 10 plt.suptitle('Simulation: Portfolio vs. Benchmark | Risk-Return Profile', fontsize=12)
3 print("Portfolio SD :", b_portf_sd) 11 plt.xlabel("Standard Deviation")
4 print("") 12 plt.ylabel("Mean Return")
5 print("Investment :", investment) 13 plt.show()
6 print("Portfolio Return:", portf_ret)
7 print("Portfolio SD :", portf_sd)

Investment : 1000000
Portfolio Return: 142926.03665209853
Portfolio SD : 120693.27749207916

Investment : 1000000
Portfolio Return: 157623.43471432617
Portfolio SD : 126338.35300157545

In [41]: 1 print("Benchmark SR:", b_sr)


2 print("Portfolio SR:", portf_sr)

Benchmark SR: 0.6870808248416386


Portfolio SR: 0.7727141631576343

Project: Portfolio Construction & Optimization

Identify the weights under simulated portfolio approach.

localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 11/23 localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 12/23
05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook 05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook

In [43]: 1 rr_profile = pd.DataFrame({


2 "Mean": [portf_ret_p*time, b_ret],
3 "SD": [portf_sd_p*np.sqrt(time), b_sd]
4 }, index=["Simulated Portfolio", "Benchmark Portfolio"])
5 rr_profile

Out[43]:
Mean SD

Simulated Portfolio 0.157623 0.126338

Benchmark Portfolio 0.142926 0.120693

In [44]: 1 df = rr_profile.append(s_ticker_rr_profile_df)
2 df['SR'] = (df['Mean'] - rf) / df["SD"]
3 df

Out[44]:
Mean SD SR

Simulated Portfolio 0.157623 0.126338 0.772714

Benchmark Portfolio 0.142926 0.120693 0.687081

ADANIPORTS 0.146732 0.308613 0.281038

ASIANPAINT 0.254572 0.214106 0.908763

AXISBANK 0.216748 0.279921 0.559973

BAJAJ-AUTO 0.093869 0.221231 0.153092

BAJAJFINSV 0.438334 0.294133 1.286268

BAJFINANCE 0.593202 0.327144 1.629869


Risk-Return Profile - Stocks | Portfolio | Benchmark
BHARTIARTL 0.186642 0.337235 0.375531

BPCL 0.001328 0.412570 -0.142211

BRITANNIA 0.103488 0.362333 0.120023

localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 13/23 localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 14/23

05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook 05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook

In [45]: 1 plt.figure(figsize=(20,10))
2 plt.scatter(df["SD"], df["Mean"])
3 ​
4 plt.scatter(df.loc["Simulated Portfolio", "SD"], df.loc["Simulated Portfolio", "Mean"], color='b', s=250)
5 plt.annotate("---Portfolio", (df.loc["Simulated Portfolio", "SD"], df.loc["Simulated Portfolio", "Mean"]), f
6 ​
7 plt.scatter(df.loc["Benchmark Portfolio", "SD"], df.loc["Benchmark Portfolio", "Mean"], color='r', s=250)
8 plt.annotate("---Benchmark", (b_sd, b_ret), fontsize=12, color='black')
9 ​
10 plt.suptitle('Risk-Return Profile - Stocks | Portfolio | Benchamrk', fontsize=12)
11 plt.xlabel("Standard Deviation")
12 plt.ylabel("Mean Return")
13 plt.show()

Analytics

localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 15/23 localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 16/23
05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook 05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook

In [46]: 1 df_higher_mean = df[df['Mean'] >= df.loc["Simulated Portfolio", "Mean"]].sort_values(by=['Mean'], ascending= In [47]: 1 1 - (df.loc["Simulated Portfolio", "SD"] / df.loc["ICICIBANK", "SD"])
2 df_lower_sd = df[df['SD'] <= df.loc["Simulated Portfolio", "SD"]].sort_values(by=['SD'], ascending=False)
3 print(df_higher_mean) Out[47]: 0.575618753706364
4 print(df_lower_sd)
In [48]: 1 df['DRatio'] = df.loc["Simulated Portfolio", "SD"] / df['SD']
Mean SD SR
2 df
BAJFINANCE 0.593202 0.327144 1.629869
TITAN 0.485473 0.327154 1.300530 Out[48]:
BAJAJFINSV 0.438334 0.294133 1.286268 Mean SD SR DRatio
TATACONSUM 0.379408 0.327609 0.974965
DIVISLAB 0.347802 0.350771 0.820483 Simulated Portfolio 0.157623 0.126338 0.772714 1.000000
NESTLEIND 0.332469 0.216543 1.258269 Benchmark Portfolio 0.142926 0.120693 0.687081 1.046772
HDFCLIFE 0.331218 0.291921 0.929080
KOTAKBANK 0.316419 0.219698 1.167144 ADANIPORTS 0.146732 0.308613 0.281038 0.409375
HINDUNILVR 0.307279 0.194055 1.274275
ASIANPAINT 0.254572 0.214106 0.908763 0.590073
ICICIBANK 0.302969 0.297700 0.816153
HDFC 0.258261 0.223339 0.887712 AXISBANK 0.216748 0.279921 0.559973 0.451336
ASIANPAINT 0.254572 0.214106 0.908763
AXISBANK 0.216748 0.279921 0.559973 BAJAJ-AUTO 0.093869 0.221231 0.153092 0.571070
RELIANCE 0.214392 0.393515 0.392340 BAJAJFINSV 0.438334 0.294133 1.286268 0.429528
TECHM 0.188675 0.270197 0.476226
BHARTIARTL 0.186642 0.337235 0.375531 BAJFINANCE 0.593202 0.327144 1.629869 0.386185
SBILIFE 0.177249 0.274036 0.427860
BHARTIARTL 0.186642 0.337235 0.375531 0.374631
SBIN 0.163963 0.343142 0.302973
HINDALCO 0.158421 0.327037 0.300949 BPCL 0.001328 0.412570 -0.142211 0.306223
Simulated Portfolio 0.157623 0.126338 0.772714
BRITANNIA 0.103488 0.362333 0.120023 0.348681
Mean SD SR
Simulated Portfolio 0.157623 0.126338 0.772714
Benchmark Portfolio 0.142926 0.120693 0.687081
Variance-Covariance & Correlation

Diversification Ratio

Diversification Ratio = Portfolio SD / Stock SD


(lower the better)

localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 17/23 localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 18/23

05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook 05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook

In [57]: 1 s_ticker_cov_hist_df = s_ticker_ret_hist_df.cov()*time In [50]: 1 s_ticker_corr_hist_df = s_ticker_ret_hist_df.corr()


2 s_ticker_cov_hist_df.round(6) 2 s_ticker_corr_hist_df.round(4)

Out[57]: Out[50]:
BAJAJ- BAJAJ-
ADANIPORTS ASIANPAINT AXISBANK BAJAJFINSV BAJFINANCE BHARTIARTL BPCL BRITANNIA CIPLA ... SUN ADANIPORTS ASIANPAINT AXISBANK BAJAJFINSV BAJFINANCE BHARTIARTL BPCL BRITANNIA CIPLA ... SUNPHAR
AUTO AUTO

ADANIPORTS 0.095242 0.016780 0.023662 0.017421 0.029928 0.035363 0.018885 0.030657 0.015196 0.016857 ... ADANIPORTS 1.0000 0.2539 0.2739 0.2552 0.3297 0.3503 0.1815 0.2408 0.1359 0.2246 ... 0.1

ASIANPAINT 0.016780 0.045842 0.017222 0.013581 0.022076 0.020405 0.014065 0.023600 0.010962 0.004859 ... ASIANPAINT 0.2539 1.0000 0.2873 0.2867 0.3506 0.2913 0.1948 0.2672 0.1413 0.0933 ... 0.0

AXISBANK 0.023662 0.017222 0.078356 0.014836 0.027235 0.029090 0.017151 0.023607 0.013149 0.013001 ... AXISBANK 0.2739 0.2873 1.0000 0.2396 0.3308 0.3177 0.1817 0.2044 0.1296 0.1910 ... 0.1

BAJAJ-AUTO 0.017421 0.013581 0.014836 0.048943 0.019691 0.019647 0.012686 0.020663 0.003877 0.010520 ... BAJAJ-AUTO 0.2552 0.2867 0.2396 1.0000 0.3026 0.2715 0.1700 0.2264 0.0484 0.1956 ... 0.1

BAJAJFINSV 0.029928 0.022076 0.027235 0.019691 0.086514 0.067627 0.020797 0.031098 0.017283 0.012088 ... BAJAJFINSV 0.3297 0.3506 0.3308 0.3026 1.0000 0.7028 0.2097 0.2563 0.1622 0.1690 ... 0.1

BAJFINANCE 0.035363 0.020405 0.029090 0.019647 0.067627 0.107023 0.020166 0.034381 0.015309 0.014264 ... BAJFINANCE 0.3503 0.2913 0.3177 0.2715 0.7028 1.0000 0.1828 0.2547 0.1292 0.1793 ... 0.1

BHARTIARTL 0.018885 0.014065 0.017151 0.012686 0.020797 0.020166 0.113727 0.017786 0.005648 0.012786 ... BHARTIARTL 0.1815 0.1948 0.1817 0.1700 0.2097 0.1828 1.0000 0.1278 0.0462 0.1559 ... 0.0

BPCL 0.030657 0.023600 0.023607 0.020663 0.031098 0.034381 0.017786 0.170214 0.004947 0.008205 ... BPCL 0.2408 0.2672 0.2044 0.2264 0.2563 0.2547 0.1278 1.0000 0.0331 0.0818 ... 0.0

BRITANNIA 0.015196 0.010962 0.013149 0.003877 0.017283 0.015309 0.005648 0.004947 0.131285 0.005811 ... BRITANNIA 0.1359 0.1413 0.1296 0.0484 0.1622 0.1292 0.0462 0.0331 1.0000 0.0660 ... 0.0

CIPLA 0.016857 0.004859 0.013001 0.010520 0.012088 0.014264 0.012786 0.008205 0.005811 0.059125 ... CIPLA 0.2246 0.0933 0.1910 0.1956 0.1690 0.1793 0.1559 0.0818 0.0660 1.0000 ... 0.3

Data Cleaning

In [ ]: 1 s_ticker_ret_hist_df.transpose()

In [ ]: 1 s_ticker_ret_hist_df.isnull().sum()

In [ ]: 1 s_ticker_ret_hist_df.fillna(0).transpose()

Engine: Optimized Portfolio vs. Benchmark | Risk-Return Profile | Sharpe Ratio

In [65]: 1 from pypfopt import risk_models, expected_returns


2 from pypfopt.efficient_frontier import EfficientFrontier
3 from pypfopt.discrete_allocation import DiscreteAllocation, get_latest_prices

localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 19/23 localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 20/23
05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook 05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook

In [52]: 1 s_ticker_close_hist_df = pd.DataFrame() In [67]: 1 s_ticker_ret_hist_df = expected_returns.mean_historical_return(s_ticker_close_hist_df)


2 for item in s_ticker_list: 2 s_ticker_cov_hist_df = risk_models.sample_cov(s_ticker_close_hist_df)
3 s_ticker_close_hist_df[item] = s_ticker_spot_hist_dc[item]['Close'] 3 s_ticker_cov_hist_df

Out[67]:
In [53]: 1 s_ticker_close_hist_df BAJAJ-
ADANIPORTS ASIANPAINT AXISBANK BAJAJFINSV BAJFINANCE BHARTIARTL BPCL BRITANNIA CIPLA ... SUN
AUTO
Out[53]:
BAJAJ- ADANIPORTS 0.095371 0.016802 0.023694 0.017445 0.029968 0.035411 0.018911 0.030699 0.015216 0.016879 ...
ADANIPORTS ASIANPAINT AXISBANK BAJAJFINSV BAJFINANCE BHARTIARTL BPCL BRITANNIA CIPLA ... SUNPHARMA TATA
AUTO
ASIANPAINT 0.016802 0.045903 0.017245 0.013600 0.022106 0.020431 0.014084 0.023632 0.010977 0.004866 ...
Date
AXISBANK 0.023694 0.017245 0.078462 0.014856 0.027271 0.029129 0.017174 0.023639 0.013167 0.013018 ...
2017-
273.80 904.65 447.75 2598.50 2949.65 870.05 311.00 640.50 2886.45 566.00 ... 634.05 BAJAJ-AUTO 0.017445 0.013600 0.014856 0.049009 0.019718 0.019674 0.012703 0.020691 0.003883 0.010535 ...
01-02

2017- BAJAJFINSV 0.029968 0.022106 0.027271 0.019718 0.086631 0.067718 0.020825 0.031140 0.017306 0.012104 ...
273.95 896.60 455.25 2619.20 3016.65 884.00 304.45 650.55 2872.25 573.65 ... 636.10
01-03
BAJFINANCE 0.035411 0.020431 0.029129 0.019674 0.067718 0.107167 0.020193 0.034428 0.015330 0.014284 ...
2017-
274.90 906.60 453.10 2684.10 2960.85 871.90 313.90 655.45 2852.40 568.25 ... 637.35 BHARTIARTL 0.018911 0.014084 0.017174 0.012703 0.020825 0.020193 0.113881 0.017810 0.005655 0.012804 ...
01-04
BPCL 0.030699 0.023632 0.023639 0.020691 0.031140 0.034428 0.017810 0.170445 0.004954 0.008216 ...
2017-
287.50 916.50 458.05 2723.35 3018.45 899.75 321.10 672.70 2865.80 579.85 ... 643.45
01-05 BRITANNIA 0.015216 0.010977 0.013167 0.003883 0.017306 0.015330 0.005655 0.004954 0.131463 0.005819 ...
2017- CIPLA 0.016879 0.004866 0.013018 0.010535 0.012104 0.014284 0.012804 0.008216 0.005819 0.059205 ...
286.05 929.50 455.20 2707.35 2978.55 878.45 319.75 664.85 2894.95 582.85 ... 640.75
01-06

... ... ... ... ... ... ... ... ... ... ... ... ...

2019- In [68]: 1 efficient_frontier = EfficientFrontier(s_ticker_ret_hist_df, s_ticker_cov_hist_df)


368.60 1803.45 740.65 3226.75 9294.85 4139.50 457.15 477.80 3091.05 478.70 ... 429.80 2 raw_weights = efficient_frontier.max_sharpe()
12-24
3 optimum_weights = efficient_frontier.clean_weights()
2019- 4 print(optimum_weights)
363.65 1809.60 736.50 3230.05 9350.10 4187.10 447.55 477.20 3062.30 474.15 ... 422.15
12-26
OrderedDict([('ADANIPORTS', 0.0), ('ASIANPAINT', 0.0), ('AXISBANK', 0.0), ('BAJAJ-AUTO', 0.0), ('BAJAJFINSV',
2019-
363.70 1812.25 760.15 3241.95 9443.15 4252.65 455.10 490.95 3042.10 481.10 ... 426.00 0.0), ('BAJFINANCE', 0.23729), ('BHARTIARTL', 0.0), ('BPCL', 0.0), ('BRITANNIA', 0.0), ('CIPLA', 0.0), ('COAL
12-27
INDIA', 0.0), ('DIVISLAB', 0.04192), ('DRREDDY', 0.0), ('EICHERMOT', 0.0), ('GRASIM', 0.0), ('HCLTECH', 0.0),
2019- ('HDFC', 0.0), ('HDFCBANK', 0.0), ('HDFCLIFE', 0.06254), ('HEROMOTOCO', 0.0), ('HINDALCO', 0.0), ('HINDUNILV
365.95 1802.30 754.10 3251.95 9439.20 4243.30 460.50 493.05 3047.35 479.95 ... 430.15
12-30 R', 0.1767), ('ICICIBANK', 0.00272), ('INDUSINDBK', 0.0), ('INFY', 0.0), ('IOC', 0.0), ('ITC', 0.0), ('JSWSTE
2019-
EL', 0.0), ('KOTAKBANK', 0.1108), ('LT', 0.0), ('M&M', 0.0), ('MARUTI', 0.0), ('NESTLEIND', 0.18655), ('NTP
366.00 1784.95 754.10 3185.00 9393.35 4234.75 455.80 491.55 3027.80 478.20 ... 432.55 C', 0.0), ('ONGC', 0.0), ('POWERGRID', 0.0), ('RELIANCE', 0.0), ('SBILIFE', 0.0), ('SBIN', 0.0), ('SHREECEM',
12-31
0.0), ('SUNPHARMA', 0.0), ('TATACONSUM', 0.01521), ('TATAMOTORS', 0.0), ('TATASTEEL', 0.0), ('TCS', 0.0), ('T
ECHM', 0.0262), ('TITAN', 0.14007), ('ULTRACEMCO', 0.0), ('UPL', 0.0), ('WIPRO', 0.0)])
739 rows × 50 columns

localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 21/23 localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 22/23

05/09/2021 Portfolio Construction & Optimization { Python } | Simulator | Analytics | Engine - Jupyter Notebook

In [70]: 1 efficient_frontier.portfolio_performance(verbose=True)

Expected annual return: 45.6%


Annual volatility: 15.9%
Sharpe Ratio: 2.75

Out[70]: (0.4563880020607941, 0.15855281059794166, 2.752319561003476)

localhost:8888/notebooks/Desktop/Projects/Programming/Python/Portfolio Construction %26 Optimization %7B Python %7D %7C Simulator %7C Analytics %7C Engine.ipynb 23/23

You might also like