<jupyter_start><jupyter_text>Optimize a portfolio * Here we will use the effecient frontier:    * Expected return and financial risk  are objective for optimization<jupyter_code>import datetime
import numpy as np
import pandas as pd
from yahoo_finance_api import YahooFinance as yf
import matplotlib.pyplot as plt
stock_symbols = ['TCS.NS', 'RELIANCE.NS', 'GAIL.NS', 'MARUTI.NS', 'BAJAJ-AUTO.NS', 
                 'ASIANPAINT.NS', 'GSKCONS.NS', 'DIAMINESQ.BO', 'SWISSGLA.BO', 'IOLCP.NS',
                 'CALCOM.BO']

numAssets = len(stock_symbols)
print("We have {} assests in the portfolio.".format(numAssets))
Weights = np.array(np.repeat(1/numAssets,numAssets))
Weights
my_stocks = pd.DataFrame()
for i in range(len(stock_symbols)):
    my_stocks[stock_symbols[i]] = yf(stock_symbols[i], result_range='5y', interval='1d', dropna='True').result['Close']
my_stocks<jupyter_output>C:\Users\<NAME>\Anaconda3\envs\tf_nptel\lib\site-packages\yahoo_finance_api-0.0.1-py3.6.egg\yahoo_finance_api\__init__.py:73: FutureWarning: The pandas.np module is deprecated and will be removed from pandas in a future version. Import numpy directly instead<jupyter_text>Function to plot individual and combined stocks<jupyter_code># plot individual graphs function
def plot_graphs(my_stocks, ylabel = 'Price in Rupees' ):    
    for i in range(len(my_stocks.columns)):
        my_stocks.iloc[:,i].plot(figsize = (12,10))
        plt.title(my_stocks.columns[i])
        plt.ylabel(ylabel)
        plt.show()

# plot combined stocks graphs function

def combined_plot_graphs(my_stocks):    
    for i in range(len(my_stocks.columns)):
        my_stocks.iloc[:,i].plot(figsize = (12,10))
    plt.title('Portfolio performance of stocks')
    plt.ylabel('closing price in Rupees')
    plt.legend(stock_symbols)
    plt.show()<jupyter_output><empty_output><jupyter_text>Combined stock performance<jupyter_code>combined_plot_graphs(my_stocks)
plot_graphs(my_stocks)<jupyter_output><empty_output><jupyter_text>Calculation of simple returns for each of the stocks* Here the period is set a 1, but if we want monthly stock returns, we can change this number to 30, hence this number can be varied, based on the requirement<jupyter_code># calculate the simple returns 
daily_simple_returns = my_stocks.pct_change(periods=1)
daily_simple_returns
# show the corvariance matrix for annualized returns
covariance_matrix = daily_simple_returns.cov() * 252
covariance_matrix<jupyter_output><empty_output><jupyter_text>* __Covariance__ is direction of relationship between two asset prices.<jupyter_code># portfolio variance

portfolio_variance = np.dot(Weights.T, np.dot(covariance_matrix, Weights))
portfolio_variance
# portfolio volatility or standard deviation
portfolio_volatility = np.sqrt(portfolio_variance)
portfolio_volatility
# Annual portfolio returns
portfolio_simple_annual_return = my_stocks.pct_change(periods=252)
print("Expected return from this portfolio for every year is : {}".format(np.sum(portfolio_simple_annual_return.mean() * Weights)))
# overall portfolio performance or metrics

variation_percentage = (round(portfolio_variance, 2)) * 100
volatility_percentage = (round(portfolio_volatility, 2)) * 100
annual_return_percentage = (round(np.sum(portfolio_simple_annual_return.mean() * Weights), 2)) * 100

print('Expected annual returns for portfolio: {}%'.format(annual_return_percentage))
print('Expected variance in portfolio: {}%'.format(variation_percentage))
print('Expected volatility in portfolio: {}%'.format(volatility_percentage))<jupyter_output>Expected annual returns for portfolio: 31.0%
Expected variance in portfolio: 4.0%
Expected volatility in portfolio: 19.0%<jupyter_text>Portfolio optimization using PyPortfolioOpt<jupyter_code>from pypfopt.efficient_frontier import EfficientFrontier
from pypfopt import risk_models
from pypfopt import expected_returns
# expected returns and annualized sample covariance matrix of asset returns

mu = expected_returns.mean_historical_return(my_stocks)
S = risk_models.sample_cov(my_stocks)<jupyter_output><empty_output><jupyter_text>Optimize for maximum sharp ratio* Sharp ratio is a way to describe the excess returns for the extra amount of volatility, it measures the performance of an investment, compared to an investment which is risk free like treasury bonds<jupyter_code>ef = EfficientFrontier(expected_returns = mu,
                       cov_matrix = S)
weights = ef.max_sharpe()
cleaned_weights = ef.clean_weights()
print(cleaned_weights)
print()
ef.portfolio_performance(verbose = True)<jupyter_output>OrderedDict([('TCS.NS', 0.06718), ('RELIANCE.NS', 0.1669), ('GAIL.NS', 0.0), ('MARUTI.NS', 0.0), ('BAJAJ-AUTO.NS', 0.0), ('ASIANPAINT.NS', 0.06712), ('GSKCONS.NS', 0.10201), ('DIAMINESQ.BO', 0.09911), ('SWISSGLA.BO', 0.18953), ('IOLCP.NS', 0.1058), ('CALCOM.BO', 0.20235)])

Expected annual return: 43.4%
Annual volatility: 22.0%
Sharpe Ratio: 1.88<jupyter_text>* The above results show, that we do not need to have to Maruthi, Bajaj and GAIL in our portfolio, in order to achieve the annual returns of 43.4%<jupyter_code># Discrete allocation of each share per stock

from pypfopt.discrete_allocation import DiscreteAllocation, get_latest_prices

latest_prices = get_latest_prices(my_stocks)
weigths = cleaned_weights
da = DiscreteAllocation(weights,
                        latest_prices,
                        total_portfolio_value = 100000)

allocation, leftover = da.lp_portfolio()
print('Discrete allocation: ', allocation)
print('Funds remainig: ', leftover)<jupyter_output>Discrete allocation:  {'TCS.NS': 3.0, 'RELIANCE.NS': 9.0, 'ASIANPAINT.NS': 4.0, 'GSKCONS.NS': 1.0, 'DIAMINESQ.BO': 33.0, 'SWISSGLA.BO': 22.0, 'IOLCP.NS': 17.0, 'CALCOM.BO': 838.0}
Funds remainig:  39.649942173215095
{'fraction_non_alphanumeric': 0.10827693909422176, 'fraction_numerical': 0.02724275550928336, 'mean_word_length': 5.781176470588235, 'pattern_counts': {'":': 0, '<': 30, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '200078', 'license': 'MIT', 'n_tokens_mistral': 2074, 'n_tokens_neox': 1906, 'n_words': 477, 'path': 'stocks_portfolio_optimization.ipynb', 'repo_name': 'arjunjanamatti/finance_and_trading', 'size': '5772'}