library(quantmod)
## Loading required package: xts
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
## Loading required package: TTR
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
library(PerformanceAnalytics)
## 
## Attaching package: 'PerformanceAnalytics'
## The following object is masked from 'package:graphics':
## 
##     legend
# Portfolio stocks
stocks <- c(
  "NVDA","LLY","COST","MSFT",
  "AAPL","META","V","MA"
)
# Portfolio weights
weights <- c(
  0.30,0.30,0.20,0.04,
  0.04,0.04,0.04,0.04
)
# Download stock data
getSymbols(stocks,
           from = "2022-01-01",
           to = "2024-12-31",
           src = "yahoo")
## [1] "NVDA" "LLY"  "COST" "MSFT" "AAPL" "META" "V"    "MA"
# Merge adjusted prices
prices <- merge(
  Ad(NVDA),
  Ad(LLY),
  Ad(COST),
  Ad(MSFT),
  Ad(AAPL),
  Ad(META),
  Ad(V),
  Ad(MA)
)
# Rename columns
colnames(prices) <- stocks
# Calculate returns
returns <- na.omit(Return.calculate(prices))
# Portfolio returns
portfolio_returns <- Return.portfolio(
  returns,
  weights = weights
)
# Benchmark
getSymbols("SPY",
           from = "2022-01-01",
           to = "2024-12-31",
           src = "yahoo")
## [1] "SPY"
spy_returns <- na.omit(
  Return.calculate(Ad(SPY))
)
# Performance chart
charts.PerformanceSummary(
  merge(portfolio_returns, spy_returns),
  legend.loc = "topright",
  main = "QM Portfolio vs SPY"
)

pie(
  weights,
  labels = stocks,
  main = "Portfolio Weights"
)

table.AnnualizedReturns(
  merge(portfolio_returns, spy_returns)
)
##                           portfolio.returns SPY.Adjusted
## Annualized Return                    0.4271       0.0882
## Annualized Std Dev                   0.2670       0.1752
## Annualized Sharpe (Rf=0%)            1.5994       0.5037
portfolio_sd <- StdDev.annualized(portfolio_returns)
spy_sd <- StdDev.annualized(spy_returns)

portfolio_ret <- Return.annualized(portfolio_returns)
spy_ret <- Return.annualized(spy_returns)

plot(
  c(spy_sd, portfolio_sd),
  c(spy_ret, portfolio_ret),
  xlab = "Risk (Volatility)",
  ylab = "Annual Return",
  main = "Risk vs Return"
)
text(
  c(spy_sd, portfolio_sd),
  c(spy_ret, portfolio_ret),
  labels = c("SPY", "QM Portfolio"),
  pos = 4
)

SharpeRatio.annualized(portfolio_returns)
##                                         portfolio.returns
## Annualized Sharpe Ratio (Rf=0%, p=95%):          1.465723
maxDrawdown(portfolio_returns)
## [1] 0.2224686
CAPM.alpha(
  portfolio_returns,
  spy_returns
)
## [1] 0.001088806
CAPM.beta(
  portfolio_returns,
  spy_returns
)
## [1] 1.171219

Including Plots

You can also embed plots, for example:

Note that the echo = FALSE parameter was added to the code chunk to prevent printing of the R code that generated the plot.