<jupyter_start><jupyter_text><jupyter_code>#Description: This program optimizes a stock portfolio
#Import libraries
import pandas as pd 
import numpy as np
import requests
import time
import pandas_datareader as web
import matplotlib.pyplot as plt

import bs4 as bs
import datetime as dt
import os
import pickle
SP500 = []

def save_sp500_tickers():
    resp = requests.get('http://en.wikipedia.org/wiki/List_of_S%26P_500_companies')
    soup = bs.BeautifulSoup(resp.text, 'lxml')
    table = soup.find('table', {'class': 'wikitable sortable'})
    tickers = []
    for row in table.findAll('tr')[1:]:
        ticker = row.findAll('td')[0].text.replace('.', '-')
        ticker = ticker[:-1]
        tickers.append(ticker)
    with open("sp500tickers.pickle", "wb") as f:
        pickle.dump(tickers, f)
    return tickers

SP500 = save_sp500_tickers()
df = pd.DataFrame()
# = ['GOOG', 'AAPL', 'FB', 'BABA', 'AMZN', 'GE', 'AMD', 'WMT', 'BAC', 'GM','T', 'UAA', 'SHLD', 'XOM', 'RRC', 'BBY', 'MA', 'PFE', 'JPM', 'SBUX']

for symbol in SP500:
  df[symbol] = web.DataReader(symbol, data_source = "yahoo", start = "2000-01-01", end = "2021-03-01")['Adj Close']
  time.sleep(0.1)
assets = df.columns
assets
pip install PyPortfolioOpt
#Optimize the portfolio
from pypfopt.efficient_frontier import EfficientFrontier
from pypfopt import risk_models
from pypfopt import expected_returns
df = df.drop(['CARR'], axis=1)
df
#Calculate the expected returns and covariance
mu = expected_returns.mean_historical_return(df)
s = risk_models.sample_cov(df)
print(mu)
print(s)

max = mu.max()
min = mu.min()

print(max)
print(min)
#Optimize sharpe ratio
#ef = EfficientFrontier(mu,s,weight_bounds=(-1,1))
ef = EfficientFrontier(mu,s)
weights = ef.max_sharpe()

cleaned_weights = ef.clean_weights()
print(cleaned_weights)
ef.portfolio_performance(verbose=True)
pip install pulp
#Get the discrete allocation 
from pypfopt.discrete_allocation import  DiscreteAllocation, get_latest_prices

portfolio_val = 100000
latest_prices = get_latest_prices(df)
weights = cleaned_weights
da = DiscreteAllocation(weights, latest_prices, total_portfolio_value = portfolio_val)
allocation, leftover = da.lp_portfolio()
print('Discrete allocation:', allocation)
print('Funds Remaining: $', leftover)
#Create a function to get the companies name
def get_company_name(symbol):
  url = 'http://d.yimg.com/autoc.finance.yahoo.com/autoc?query='+symbol+'&region=1&lang=en'
  result = requests.get(url).json()
  for r in result['ResultSet']['Result']:
    if r['symbol'] == symbol:
      return r['name']

#Store the company name into a list
company_name = []
for symbol in allocation:
  company_name.append(get_company_name(symbol))
#Get the discrete allocation values
discrete_allocation_list = []
for symbol in allocation:
  discrete_allocation_list.append(allocation.get(symbol))
#Creare a data for the portfolio
portfolio_df = pd.DataFrame(columns=['Company_name','Company_Ticker', 'Discrete_val_'+str(portfolio_val)]) 

portfolio_df['Company_name'] =  company_name
portfolio_df['Company_Ticker'] =  allocation
portfolio_df['Discrete_val_'+str(portfolio_val)] =  discrete_allocation_list

portfolio_df
from pypfopt import plotting
# Efficient Frontier
ef = EfficientFrontier(mu, s)
#ef.add_constraint(lambda w: w[0] >= 0.2)
#ef.add_constraint(lambda w: w[2] == 0.15)
#ef.add_constraint(lambda w: w[3] + w[4] <= 0.10)

fig, ax = plt.subplots()
plotting.plot_efficient_frontier(ef, ax=ax, show_assets=True)
plt.show()
cov = plotting.plot_covariance(s, plot_correlation=False, show_tickers=True)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13484087102177555, 'fraction_numerical': 0.01870463428252373, 'mean_word_length': 5.916988416988417, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 1}, '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': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '548682', 'license': 'MIT', 'n_tokens_mistral': 1333, 'n_tokens_neox': 1266, 'n_words': 294, 'path': 'Portfolio_SP500.ipynb', 'repo_name': 'sergiocabrales/python', 'size': '3582'}