File size: 3,028 Bytes
5e702e0
 
 
0527f0f
c3d0e6b
 
 
 
 
 
0527f0f
c3d0e6b
 
 
 
 
 
0527f0f
c3d0e6b
 
 
 
 
 
0527f0f
c3d0e6b
 
 
 
 
 
 
 
 
 
 
 
 
5e702e0
0527f0f
c3d0e6b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0527f0f
c3d0e6b
 
 
 
 
 
 
 
 
 
 
 
 
 
0527f0f
c3d0e6b
0527f0f
5e702e0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import sys
import subprocess
subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'websockets>=13.0'])

import gradio as gr
import yfinance as yf
import pandas as pd
import matplotlib.pyplot as plt
from io import BytesIO
import base64

# Define the portfolio data
portfolio = {
    'Ticker': ['TSLA', 'PLTR', 'SOUN'],
    'Shares': [200, 490, 652],
    'Avg Cost': [245.0, 52.0, 7.5]
}

def get_current_prices(tickers):
    """
    Fetch the latest closing prices for the given tickers.
    """
    data = yf.download(tickers, period='1d')['Close']
    return data.iloc[-1]

def generate_pie_chart(values, labels):
    """
    Generate a pie chart as a base64-encoded image.
    """
    fig, ax = plt.subplots()
    ax.pie(values, labels=labels, autopct='%1.1f%%', startangle=90)
    ax.set_title('Portfolio Allocation by Current Value')
    ax.axis('equal')  # Equal aspect ratio ensures the pie is circular.
    buf = BytesIO()
    plt.savefig(buf, format='png')
    buf.seek(0)
    img_base64 = base64.b64encode(buf.read()).decode('utf-8')
    plt.close(fig)
    return f"data:image/png;base64, {img_base64}"

def display_portfolio():
    """
    Compute portfolio metrics and generate outputs.
    """
    df = pd.DataFrame(portfolio)
    try:
        prices = get_current_prices(df['Ticker'].tolist())
        df['Current Price'] = prices.values
    except Exception as e:
        return f"Error fetching prices: {str(e)}", "", "N/A", "N/A"
    df['Cost Basis'] = df['Shares'] * df['Avg Cost']
    df['Current Value'] = df['Shares'] * df['Current Price']
    df['Gain/Loss'] = df['Current Value'] - df['Cost Basis']
    df['Gain/Loss %'] = (df['Gain/Loss'] / df['Cost Basis']) * 100
    total_cost = df['Cost Basis'].sum()
    total_value = df['Current Value'].sum()
    total_gain = total_value - total_cost
    # Format the table as HTML
    table_html = df.to_html(index=False, float_format=lambda x: f'{x:.2f}')
    # Generate pie chart
    pie_img = generate_pie_chart(df['Current Value'], df['Ticker'])
    total_value_str = f"${total_value:.2f}"
    total_gain_str = f"${total_gain:.2f} ({(total_gain / total_cost * 100):.2f}%)"
    return table_html, pie_img, total_value_str, total_gain_str

# Create the Gradio interface
with gr.Blocks(title="Investment Portfolio Dashboard") as demo:
    gr.Markdown("# Investment Portfolio Dashboard")
    gr.Markdown("View your portfolio metrics with real-time stock prices.")
    refresh_btn = gr.Button("Refresh Data")
    table_output = gr.HTML(label="Portfolio Table")
    pie_output = gr.Image(label="Portfolio Allocation", type="pil")  # Will display base64 image
    total_value_output = gr.Textbox(label="Total Portfolio Value")
    total_gain_output = gr.Textbox(label="Total Gain/Loss")
    refresh_btn.click(
        fn=display_portfolio,
        inputs=[],
        outputs=[table_output, pie_output, total_value_output, total_gain_output]
    )

# Launch the demo (automatically handled in Hugging Face Spaces)
if __name__ == "__main__":
    demo.launch()