Spaces:
Sleeping
Sleeping
| # app.py | |
| import gradio as gr | |
| import numpy as np | |
| import pandas as pd | |
| import yfinance as yf | |
| import plotly.express as px | |
| # Default stock options | |
| default_stocks = ["RELIANCE.NS", "TCS.NS", "HDFCBANK.NS", "INFY.NS", "ITC.NS"] | |
| def run_analysis(tickers, risk_free, n_portfolios): | |
| if len(tickers) < 2: | |
| raise gr.Error("Please select at least 2 stocks") | |
| # Download data | |
| data = yf.download(tickers, period="3y")['Close'] | |
| # Calculate returns | |
| returns = data.pct_change().dropna() | |
| annual_returns = returns.mean() * 252 | |
| cov_matrix = returns.cov() * 252 | |
| # Generate portfolios | |
| results = [] | |
| for _ in range(n_portfolios): | |
| weights = np.random.random(len(tickers)) | |
| weights /= np.sum(weights) | |
| ret = np.dot(weights, annual_returns) | |
| risk = np.sqrt(weights.T @ cov_matrix @ weights) | |
| sharpe = (ret - risk_free/100) / risk | |
| results.append([ret, risk, sharpe, weights]) | |
| results_df = pd.DataFrame(results, columns=['Return', 'Risk', 'Sharpe', 'Weights']) | |
| # Visualization | |
| fig = px.scatter( | |
| results_df, | |
| x='Risk', | |
| y='Return', | |
| color='Sharpe', | |
| title=f"Risk-Return Profile of {n_portfolios} Random Portfolios", | |
| hover_data={'Weights': False} | |
| ) | |
| # Highlight optimal portfolios | |
| max_sharpe = results_df.iloc[results_df['Sharpe'].idxmax()] | |
| min_risk = results_df.iloc[results_df['Risk'].idxmin()] | |
| fig.add_scatter( | |
| x=[max_sharpe['Risk']], | |
| y=[max_sharpe['Return']], | |
| mode='markers', | |
| marker=dict(size=15, symbol='star', color='gold'), | |
| name='Max Sharpe' | |
| ) | |
| fig.add_scatter( | |
| x=[min_risk['Risk']], | |
| y=[min_risk['Return']], | |
| mode='markers', | |
| marker=dict(size=15, symbol='x', color='red'), | |
| name='Min Risk' | |
| ) | |
| # Prepare allocation tables | |
| max_sharpe_df = pd.DataFrame({ | |
| 'Stock': tickers, | |
| 'Weight': max_sharpe['Weights'] | |
| }).set_index('Stock') | |
| min_risk_df = pd.DataFrame({ | |
| 'Stock': tickers, | |
| 'Weight': min_risk['Weights'] | |
| }).set_index('Stock') | |
| return ( | |
| fig, | |
| f"Max Sharpe Portfolio - Return: {max_sharpe['Return']:.2%}, Risk: {max_sharpe['Risk']:.2%}, Sharpe: {max_sharpe['Sharpe']:.2f}", | |
| max_sharpe_df.style.format({'Weight': '{:.2%}'}).to_html(), | |
| f"Min Risk Portfolio - Return: {min_risk['Return']:.2%}, Risk: {min_risk['Risk']:.2%}, Sharpe: {min_risk['Sharpe']:.2f}", | |
| min_risk_df.style.format({'Weight': '{:.2%}'}).to_html() | |
| ) | |
| # Define Gradio interface | |
| with gr.Blocks(title="Indian Stock Portfolio Optimizer") as demo: | |
| gr.Markdown("# ๐ Indian Stock Portfolio Optimizer") | |
| with gr.Row(): | |
| with gr.Column(): | |
| tickers = gr.CheckboxGroup( | |
| label="Select Indian Stocks (NSE)", | |
| choices=default_stocks, | |
| value=default_stocks[:2] | |
| ) | |
| risk_free = gr.Slider( | |
| label="Risk-Free Rate (%)", | |
| minimum=0.0, | |
| maximum=10.0, | |
| value=6.0, | |
| step=0.1 | |
| ) | |
| n_portfolios = gr.Slider( | |
| label="Number of Portfolios", | |
| minimum=100, | |
| maximum=1000, | |
| value=500, | |
| step=100 | |
| ) | |
| submit_btn = gr.Button("Run Analysis") | |
| with gr.Column(): | |
| plot = gr.Plot(label="Efficient Frontier") | |
| max_sharpe_title = gr.Markdown() | |
| max_sharpe_table = gr.HTML() | |
| min_risk_title = gr.Markdown() | |
| min_risk_table = gr.HTML() | |
| submit_btn.click( | |
| fn=run_analysis, | |
| inputs=[tickers, risk_free, n_portfolios], | |
| outputs=[plot, max_sharpe_title, max_sharpe_table, min_risk_title, min_risk_table] | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() |