title: "Portfolio Risk Attribution & Scenario Analysis"
author: "Ruchi Malhotra"
date: "2025-08-06"
output:
  html_document:
    toc: true
    toc_float: true
    number_sections: true
    theme: readable
    highlight: tango
    code_folding: hide

📊 Portfolio Returns and Composition

knitr::opts_chunk$set(echo = FALSE, warning = FALSE, message = FALSE)
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.2     ✔ readr     2.1.4
✔ forcats   1.0.0     ✔ stringr   1.5.0
✔ ggplot2   3.4.2     ✔ tibble    3.2.1
✔ lubridate 1.9.2     ✔ tidyr     1.3.0
✔ purrr     1.0.1     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(PerformanceAnalytics)
Loading required package: xts
Loading required package: zoo

Attaching package: 'zoo'

The following objects are masked from 'package:base':

    as.Date, as.Date.numeric


######################### Warning from 'xts' package ##########################
#                                                                             #
# The dplyr lag() function breaks how base R's lag() function is supposed to  #
# work, which breaks lag(my_xts). Calls to lag(my_xts) that you type or       #
# source() into this session won't work correctly.                            #
#                                                                             #
# Use stats::lag() to make sure you're not using dplyr::lag(), or you can add #
# conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop           #
# dplyr from breaking base R's lag() function.                                #
#                                                                             #
# Code in packages is not affected. It's protected by R's namespace mechanism #
# Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning.  #
#                                                                             #
###############################################################################

Attaching package: 'xts'

The following objects are masked from 'package:dplyr':

    first, last


Attaching package: 'PerformanceAnalytics'

The following object is masked from 'package:graphics':

    legend
library(quantmod)
Loading required package: TTR
Registered S3 method overwritten by 'quantmod':
  method            from
  as.zoo.data.frame zoo 
library(xts)
library(knitr)
library(corrr)
Warning: package 'corrr' was built under R version 4.3.3
[1] "SPY" "TLT" "VNQ"
[1] "AGG"

🗺 Correlation Map

📉 Performance Summary

🔍 Performance Comparison Table

                          Portfolio Benchmark
Annualized Return            0.0448    0.0628
Annualized Std Dev           0.1502    0.1149
Annualized Sharpe (Rf=0%)    0.2981    0.5461

📉 Drawdown Comparison

📦 Distributional View

🧮 Brinson-Style Risk Attribution (SPY/AGG Benchmark)

      SPY       TLT       VNQ 
 0.000528 -0.000204  0.000137 
     SPY      TLT      VNQ 
0.000528 0.000019      NaN 
Brinson-Style Attribution: Portfolio vs SPY/AGG Benchmark
Asset Allocation Selection Total
SPY 0.000 0.0000 0.000
TLT -0.001 -0.0281 -0.029
VNQ NaN NaN NaN

📈 Scenario Analysis: Rate Shock Simulation

📊 Monte Carlo Simulation & 95% Value at Risk

🔐 Summary

This report demonstrates multi-asset portfolio analysis with risk attribution, scenario modeling, and Value at Risk simulation using real market data.

  • Portfolio is a 3-asset blend of SPY (equity), TLT (bonds), and VNQ (REITs)
  • Benchmark is a 50/50 SPY + AGG mix
  • Compared performance, volatility, drawdowns, and 95% VaR
  • Brinson attribution removed due to asset mismatch between portfolio and benchmark