import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime
# Define tickers and portfolio weights
tickers = ['
IMAB11.SA', '
SPXI11.SA', '
BOVA11.SA']
portfolios = {
'GOAT11: 80% IMAB11 20% SPXI11': {'
IMAB11.SA': 0.8, '
SPXI11.SA': 0.2},
'40RF/60RVUS: 40% IMAB11 60% SPXI11': {'
IMAB11.SA': 0.4, '
SPXI11.SA': 0.6},
'20RF/80RVUS: 20% IMAB11 80% SPXI11': {'
IMAB11.SA': 0.1, '
SPXI11.SA': 0.8},
'100RVBR: 100% BOVA11': {'
BOVA11.SA': 1},
'50% IMAB11 50% SPXI11': {'
IMAB11.SA': 0.5, '
SPXI11.SA': 0.5}
}
# Download historical data from Yahoo Finance
data =
yf.download(tickers, period='max', auto_adjust=True)['Close']
# Find the oldest common date (latest start date among all tickers)
start_date = data[tickers].dropna().index[0]
data = data.loc[start_date:]
# Calculate daily log returns
returns = np.log(data / data.shift(1)).dropna()
# Initialize a DataFrame to store portfolio returns
portfolio_returns = pd.DataFrame(index=returns.index)
# Calculate portfolio returns based on weights
for portfolio_name, weights in portfolios.items():
portfolio_return = sum(returns[ticker] * weight for ticker, weight in weights.items())
portfolio_returns[portfolio_name] = portfolio_return
# Calculate cumulative returns
cumulative_returns = (1 portfolio_returns).cumprod()
# Calculate performance metrics
trading_days_per_year = 252
metrics = pd.DataFrame(index=portfolios.keys(), columns=['Annualized Return', 'Annualized Std Dev'])
for portfolio in portfolio_returns.columns:
# Annualized Return (Geometric Mean)
total_return = cumulative_returns[portfolio].iloc[-1] - 1 # Fixed indexing
years = len(portfolio_returns) / trading_days_per_year
annualized_return = (1 total_return) ** (1 / years) - 1
metrics.loc[portfolio, 'Annualized Return'] = annualized_return
# Annualized Standard Deviation
daily_std = portfolio_returns[portfolio].std()
annualized_std = daily_std * np.sqrt(trading_days_per_year)
metrics.loc[portfolio, 'Annualized Std Dev'] = annualized_std
# Convert metrics to percentage
metrics = metrics * 100
# Plot cumulative returns with distinct colors
plt.figure(figsize=(12, 6))
colors = ['blue', 'green', 'red', 'purple','orange']
for i, portfolio in enumerate(cumulative_returns.columns):
plt.plot(cumulative_returns.index, cumulative_returns[portfolio], label=portfolio, color=colors[i])
plt.title(f'Cumulative Returns of ETF Portfolios (Since {start_date.strftime("%Y-%m-%d")})')
plt.xlabel('Date')
plt.ylabel('Cumulative Return')
plt.legend()
plt.grid(True)
plt.savefig('cumulative_returns.png') # Save the plot
plt.show() # Display the plot interactively
plt.close()
# Display metrics
print("\nPerformance Metrics (in %):")
print(metrics.round(2))
# Save metrics to a CSV file
metrics.to_csv('portfolio_metrics.csv')