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 matplotlibThe 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