| import gradio as gr |
| import yfinance as yf |
| import pandas as pd |
| import numpy as np |
| import plotly.express as px |
|
|
| class ottimizzazioneLagrange: |
| def __init__(self, tickers_string, period): |
| |
| self.tickers = [t.strip().upper() for t in tickers_string.split(',')] |
| self.period = period |
| self.dati_prezzi = None |
| self.matrice_covarianza = None |
| self.pesi_ottimali = None |
| |
| def run_optimization(self): |
| |
| dati = yf.download(self.tickers, period=self.period, progress=False) |
| if dati.empty: |
| return "Error: No data found / Errore: Dati non trovati.", None |
| |
| if isinstance(dati.columns, pd.MultiIndex): |
| self.dati_prezzi = dati['Close'] |
| else: |
| self.dati_prezzi = pd.DataFrame(dati['Close']) |
| self.dati_prezzi.columns = self.tickers |
| |
| |
| rendimenti = self.dati_prezzi.pct_change().dropna() |
| self.matrice_covarianza = rendimenti.cov() * 252 |
| |
| |
| n_asset = len(self.tickers) |
| vettore1 = np.ones(n_asset) |
| cov_inversa = np.linalg.inv(self.matrice_covarianza.values) |
| |
| num = cov_inversa @ vettore1 |
| den = vettore1.T @ num |
| self.pesi_ottimali = num / den |
| |
| |
| res = "GLOBAL MINIMUM VARIANCE PORTFOLIO\n" + "-"*35 + "\n" |
| for i, ticker in enumerate(self.tickers): |
| res += f"Asset: {ticker} | Weight: {self.pesi_ottimali[i]*100:.2f}%\n" |
| |
| |
| df_plot = pd.DataFrame({ |
| 'Asset': self.tickers, |
| 'Weight': self.pesi_ottimali * 100 |
| }) |
| fig = px.pie(df_plot, values='Weight', names='Asset', |
| title="Portfolio Allocation (Markowitz Optimization)", |
| hole=0.3) |
| |
| return res, fig |
|
|
| def inference(tickers, period): |
| try: |
| model = ottimizzazioneLagrange(tickers, period) |
| return model.run_optimization() |
| except Exception as e: |
| return f"System Error: {str(e)}", None |
|
|
| |
| with gr.Blocks(theme=gr.themes.Default()) as demo: |
| gr.Markdown("# 📈 Portfolio Optimization via Lagrange Multipliers") |
| gr.Markdown("### Author: Dr. Ottaviani Flavio Rubens") |
| |
| with gr.Row(): |
| with gr.Column(): |
| in_tickers = gr.Textbox(label="Tickers (comma separated / separati da virgola)", value="AAPL, MSFT, GOOGL") |
| in_period = gr.Dropdown(label="Analysis Period / Periodo", choices=["1y", "2y", "5y", "max"], value="1y") |
| btn = gr.Button("Calculate / Calcola", variant="primary") |
| |
| with gr.Column(): |
| out_text = gr.Textbox(label="Results / Risultati", lines=8) |
| out_plot = gr.Plot(label="Allocation Chart / Grafico Allocazione") |
|
|
| btn.click(inference, inputs=[in_tickers, in_period], outputs=[out_text, out_plot]) |
|
|
| if __name__ == "__main__": |
| demo.launch() |