Portfolio-Optimization / PortfolioHelperFuncs.py
arif97's picture
updated
8443aa0
Raw History Blame Contribute Delete
8.4 kB
import streamlit as st
from streamlit_option_menu import option_menu
import pandas as pd
import yfinance as yf
import plotly.express as px
import datetime
from datetime import date
import numpy as np
from dataclasses import dataclass
import warnings
warnings.filterwarnings('ignore')
np.set_printoptions(suppress=True)
# Define the commodities and their Yahoo Finance tickers
commodities = {
'Gold': 'GC=F',
'Silver': 'SI=F',
'Crude Oil': 'CL=F',
'Natural Gas': 'NG=F',
'Copper': 'HG=F',
'Platinum': 'PL=F',
'Paladium': 'PA=F',
'RBOB Gasoline': 'RB=F',
'Brent Crude Oil': 'BZ=F',
'Corn Futures': 'ZC=F',
'Oat Futures': 'ZO=F',
'KC HRW Wheat Futures': 'KE=F',
'Soybean Oil Futures': 'ZL=F',
'Soybean Futures': 'ZS=F',
'Live Cattle Futures': 'LE=F',
'Cocoa': 'CC=F',
'Coffee': 'KC=F',
'Cotton': 'CT=F',
'Sugar': 'SB=F'
}
# Define the Class Structure
@dataclass
class Data:
collectedData: pd.DataFrame
commTickers: dict
years: int
upperBoundLimit: float
import plotly.express as px
import pandas as pd
import streamlit as st
def plot_optimal_weights(weights: pd.DataFrame, title: str = "Weights Allocation Bar Chart"):
"""
Plot optimal weights using Plotly and display it on Streamlit.
Parameters:
- weights: pd.DataFrame containing asset names and their corresponding weights.
- title: Title of the plot.
"""
# Ensure the DataFrame has the correct format
if weights.shape[1] != 2:
raise ValueError("DataFrame should have two columns: 'Tickers' and 'Weights'.")
# Fill NaN weights with 0
weights['Weights'] = weights['Weights'].fillna(0)
fig = px.bar(weights,
x='Tickers',
y='Weights',
title=title,
labels={"Tickers": "Assets", "Weights": "Weights"},
template='plotly_dark')
fig.update_layout(
width=1000,
height=475,
xaxis_title="Assets",
yaxis_title="Weights",
title_font=dict(size=24, color='white'),
legend=dict(
title_font=dict(size=36, color='white'),
font=dict(size=28, color='white')
),
plot_bgcolor='black',
paper_bgcolor='black'
)
fig.update_traces(marker=dict(color='blue', line=dict(color='white', width=1.5)))
return fig
# Function to retrieve ticker data or Stock Prices from Yahoo Finance
def retrieve_tickers():
global dt
if len(st.session_state.dtVariable.commTickers) <= 0:
return
startDate = date.today() - datetime.timedelta(days=st.session_state.dtVariable.years * 365)
endDate = date.today()
for com, tick in st.session_state.dtVariable.commTickers.items():
# st.write("Hello",st.session_state.dtVariable.collectedData.columns)
if com not in st.session_state.dtVariable.collectedData.columns:
st.session_state.dtVariable.collectedData[com] = yf.download(tickers=tick, start=startDate, end=endDate)['Adj Close']
st.session_state.dtVariable.collectedData.dropna(inplace=True)
# Function to Visualize Ticker Data
def visualize(data: pd.DataFrame,
title: str, hoverLabel: dict,
xTitle: str,
yTitle: str,
legendTitle: str,
width: int = 1000 # Default width set to 1000, you can adjust as needed
):
# Create interactive plots
fig = px.line(data,
title=title,
labels=hoverLabel)
fig.update_layout(
width=width, # Set the width of the plot
xaxis_title=xTitle,
yaxis_title=yTitle,
legend_title_text=legendTitle,
template='plotly_dark',
hovermode='x unified',
plot_bgcolor='black', # Set plot background color to black
paper_bgcolor='black', # Set paper background color to black
title_font=dict(color='white'),
legend=dict(
title_font=dict(color='white'), # Set legend title color to white
font=dict(color='white') # Set legend items color to white
) # Set title color to white
)
return fig
# Function to Calculate Key metrics
class KeyMetrics:
def __init__(self, data, logNormal=False):
self.data = data
self.initialWeights = np.array([1/len(self.data.columns) for _ in range(len(self.data.columns))])
self.logNormal = logNormal
self.dailyReturns = None
self.covarianceMatrix = None
self.variance = None
self.standardDeviation = None
self.expectedReturns = None
self.sharpeRatio = None
self.negSharpeRatio = None
def calculate_daily_returns(self):
self.dailyReturns = np.log(self.data / self.data.shift(1)).dropna() if self.logNormal else self.data.pct_change().dropna()
def calculate_covariance(self):
if self.dailyReturns is None:
return "Please Calculate Daily Returns First"
self.covarianceMatrix = self.dailyReturns.cov() * 252
def calculate_standard_deviation(self):
if self.covarianceMatrix is None:
return "Please Calculate Covariance Matrix First"
self.variance = self.initialWeights.T @ self.covarianceMatrix @ self.initialWeights
self.standardDeviation = np.sqrt(self.variance)
def calculate_expected_return(self):
if self.standardDeviation is None:
return "Please Calculate Standard Deviation First"
self.expectedReturns = np.sum(self.dailyReturns.mean() * self.initialWeights) * 252
def calculate_sharpe_ratio(self, riskFreeRate):
if self.expectedReturns is None:
return "Please Calculate Expected Returns First"
self.sharpeRatio = (self.expectedReturns - riskFreeRate) / self.standardDeviation
def negative_sharpe_ratio(self):
if self.sharpeRatio is None:
return "Please Calculate Sharpe Ratio First"
self.negSharpeRatio = - self.sharpeRatio
# Navigation Bar
def navigationBar():
# Use the following link to get whichever icon you'd like:
# https://getbootstrap.com/
options = [
{"label": "Sharpe Ratio Technique", "icon": "bezier"}
]
selected = option_menu(
menu_title= None, #"Ask Me Anything", # Menu title
options=[option["label"] for option in options],
icons=[option["icon"] for option in options],
menu_icon="lightbulb-fill",
default_index=0,
orientation="horizontal",
styles={
"container": {
"display": "flex",
"flex-direction": "column",
"justify-content": "center",
"padding": "20px 40px 20px 40px", # Increased top and bottom padding
"background-color": "#00E0FF", # Dark background color
"border-radius": "20px",
"width":"100%",
"box-shadow": "0px 2px 10px rgba(0, 0, 0, 0.2)", # Shadow effect
"margin": "auto", # Center align the navigation bar
"overflow-x": "auto", # Allow horizontal scrolling for small screens
},
"menu-title": {
"font-size": "36px",
"font-weight": "bold",
"background-color": "#292",
"color": "#FFFFFF", # White text color
"margin-bottom": "20px", # Spacing below the menu title
},
"menu-icon": {
"color": "#FFD700", # Golden yellow icon color
"font-size": "36px",
"margin-right": "10px",
},
"icon": {
"color": "#FFD700", # Golden yellow icon color
"font-size": "36px",
"margin-right": "10px",
},
"nav-link": {
"font-size": "20px",
"text-align": "center",
"color": "#FFFFFF", # White text color
"padding": "10px 20px",
"border-radius": "15px",
"transition": "background-color 0.3s ease",
},
"nav-link-selected": {
"background-color": "#07A2F4", # Tomato red when selected
"color": "#FFFFFF", # White text color when selected
}
},
)
return selected