import gradio as gr import yfinance as yf from pypfopt.discrete_allocation import DiscreteAllocation, get_latest_prices from pypfopt import EfficientFrontier from pypfopt import risk_models from pypfopt import expected_returns from pypfopt import plotting import copy import numpy as np import pandas as pd import plotly.express as px import matplotlib.pyplot as plt from datetime import datetime import datetime def plot_cum_returns(data, title): daily_cum_returns = 1 + data.dropna().pct_change() daily_cum_returns = daily_cum_returns.cumprod()*100 fig = px.line(daily_cum_returns, title=title) return fig def output_results(start_date, end_date, tickers_string, investment_amount): tickers = tickers_string.split(',') # Get Stock Prices stocks_df = yf.download(tickers, start=start_date, end=end_date)['Adj Close'] company_names = stocks_df['Adj Close'].columns.tolist() # Plot Individual Stock Prices fig_indiv_prices = px.line(stocks_df, title='Price of Individual Stocks') # Plot Individual Cumulative Returns fig_cum_returns = plot_cum_returns(stocks_df, 'Cumulative Returns of Individual Stocks Starting with ₹100') # Calculate and Plot Correlation Matrix between Stocks # corr_df = stocks_df.corr().round(2) # fig_corr = px.imshow(corr_df, text_auto=True, title = 'Correlation between Stocks') # Calculate expected returns and sample covariance matrix for portfolio optimization later mu = expected_returns.mean_historical_return(stocks_df) S = risk_models.sample_cov(stocks_df) # Plot efficient frontier curve #fig_efficient_frontier = plot_efficient_frontier_and_max_sharpe(mu, S) # Get optimized weights ef = EfficientFrontier(mu, S) ef.max_sharpe(risk_free_rate=0.04) weights = ef.clean_weights() expected_annual_return, annual_volatility, sharpe_ratio = ef.portfolio_performance() expected_annual_return, annual_volatility, sharpe_ratio = '{}%'.format((expected_annual_return*100).round(2)), \ '{}%'.format((annual_volatility*100).round(2)), \ '{}%'.format((sharpe_ratio*100).round(2)) weights_df = pd.DataFrame.from_dict(weights, orient='index').reset_index() weights_df.columns = ['Tickers', 'Weights'] # Get the latest prices latest_prices = get_latest_prices(stocks_df) # Allocate the stocks based on the given budget da = DiscreteAllocation(weights, latest_prices, total_portfolio_value=investment_amount) allocation, leftover = da.lp_portfolio() allocation_df = pd.DataFrame(list(allocation.items()), columns=['Ticker', 'Shares']) # Calculate returns of portfolio with optimized weights stocks_df['Optimized Portfolio'] = 0 for ticker, weight in weights.items(): stocks_df['Optimized Portfolio'] += stocks_df[ticker]*weight # Plot Cumulative Returns of Optimized Portfolio fig_cum_returns_optimized = plot_cum_returns(stocks_df['Optimized Portfolio'], 'Cumulative Returns of Optimized Portfolio Starting with ₹100') return fig_cum_returns_optimized, allocation_df, \ expected_annual_return, leftover.round(), fig_indiv_prices, fig_cum_returns with gr.Blocks() as app: with gr.Row(): gr.HTML("