CodeForFinance
PythonIntermediate

Build a Portfolio Tracker with Python

Track your stock portfolio, calculate returns, and generate visual reports. This project uses OOP principles and creates a reusable Portfolio class you can extend.

Install Dependencies

pip install yfinance pandas matplotlib

The Portfolio Class

We create a Portfolio class that stores holdings and fetches live prices to calculate current values, gains/losses, and percentage returns.

import yfinance as yf
import pandas as pd
from datetime import datetime

class Portfolio:
    def __init__(self):
        self.holdings = []

    def add_holding(self, ticker: str, shares: float, buy_price: float, buy_date: str):
        self.holdings.append({
            "ticker": ticker,
            "shares": shares,
            "buy_price": buy_price,
            "buy_date": buy_date,
            "cost_basis": shares * buy_price
        })

    def get_current_values(self) -> pd.DataFrame:
        rows = []
        for h in self.holdings:
            stock = yf.Ticker(h["ticker"])
            current_price = stock.info.get("currentPrice", 0)
            current_value = h["shares"] * current_price
            gain_loss = current_value - h["cost_basis"]
            gain_pct = (gain_loss / h["cost_basis"]) * 100

            rows.append({
                "Ticker": h["ticker"],
                "Shares": h["shares"],
                "Buy Price": f"£{h['buy_price']:.2f}",
                "Current Price": f"£{current_price:.2f}",
                "Cost Basis": f"£{h['cost_basis']:.2f}",
                "Current Value": f"£{current_value:.2f}",
                "Gain/Loss": f"£{gain_loss:.2f}",
                "Return %": f"{gain_pct:.1f}%"
            })

        return pd.DataFrame(rows)

Using the Tracker

# Create and use the portfolio
portfolio = Portfolio()

# Add your holdings
portfolio.add_holding("AAPL", 10, 150.00, "2024-01-15")
portfolio.add_holding("MSFT", 5, 380.00, "2024-03-01")
portfolio.add_holding("GOOGL", 8, 140.00, "2024-02-10")
portfolio.add_holding("AMZN", 6, 178.00, "2024-04-01")
portfolio.add_holding("NVDA", 3, 800.00, "2024-05-15")

# Display current values
df = portfolio.get_current_values()
print(df.to_string(index=False))

# Total portfolio value
total_cost = sum(h["cost_basis"] for h in portfolio.holdings)
total_value = sum(float(row["Current Value"].replace("£","").replace(",",""))
                  for _, row in df.iterrows())
total_return = ((total_value / total_cost) - 1) * 100

print(f"\nTotal Invested: £{total_cost:,.2f}")
print(f"Current Value: £{total_value:,.2f}")
print(f"Total Return: {total_return:.1f}%")

Visualise Your Portfolio

# Visualise portfolio allocation
import matplotlib.pyplot as plt

values = [float(row["Current Value"].replace("£","").replace(",",""))
          for _, row in df.iterrows()]
labels = df["Ticker"].tolist()

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))

# Pie chart - allocation
ax1.pie(values, labels=labels, autopct="%1.1f%%", startangle=90)
ax1.set_title("Portfolio Allocation")

# Bar chart - gains/losses
gains = [float(row["Return %"].replace("%","")) for _, row in df.iterrows()]
colors = ["green" if g >= 0 else "red" for g in gains]
ax2.bar(labels, gains, color=colors)
ax2.set_ylabel("Return %")
ax2.set_title("Individual Stock Returns")
ax2.axhline(y=0, color="gray", linestyle="--", linewidth=0.5)

plt.tight_layout()
plt.savefig("portfolio_report.png", dpi=150)
plt.show()

Next Steps

  • Add dividend tracking and reinvestment calculations
  • Calculate portfolio beta and Sharpe ratio
  • Add CSV import/export for transaction history
  • Build a Streamlit web interface (see our dashboard tutorial)
  • Add alerts for price targets and stop losses

Developer Essentials

As an Amazon Associate we may earn from qualifying purchases.