-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathVaR Markdown Report.Rmd
More file actions
170 lines (140 loc) · 7.45 KB
/
VaR Markdown Report.Rmd
File metadata and controls
170 lines (140 loc) · 7.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
---
title: "Value at Risk"
author: "Joshua Hall"
date: "`r format(Sys.time(), '%d %B %Y')`"
output:
prettydoc::html_pretty:
theme: cayman
toc: true
---
``` {css,echo=FALSE}
body{
text-align:justify;
}
span.math.display{
text-align-last:start;
}
.main-content table td, .main-content table th{
text-align:center;
}
img{
display: block;
margin-left: auto;
margin-right: auto;
}
```
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(knitr)
CSV_files <- list.files(getwd(),pattern = ".csv")
# Set up main data frame
stock_data <- data.frame(
Ticker=gsub(".csv","",list.files(getwd(),pattern = ".csv")),
NumShares="",
LastClose="",
Value="",
Weight="",
Volatility="",
WeightedVol=""
)
ind <- 1
# MARKDOWN VARIABLE ONLY
md_Num_Shares <- c(30,1,75,25,35,15)
# Loop through each stock file in the portfolio
for (file.name in CSV_files) {
# Reads files
assign(gsub(".csv","",file.name),read.csv(file.name))
# Receive user input for number of shares of the company
stock_data$NumShares[ind] <- md_Num_Shares[ind]#as.integer(readline(prompt = paste0("Enter # shares of ",gsub(".csv","",file.name),": ")))
# Calculate the 30-day historical volatility of the stock
stock <- read.csv(file.name)
prices <- stock$Close
n <- length(prices)
stock$Returns <- c(NaN, (prices[2:n] - prices[1:(n-1)]) / prices[1:(n-1)])
stock_data$Volatility[ind] <- sqrt(252) * sd(stock$Returns[2:n])
# Gets last close price
stock_data$LastClose[ind] <- prices[n]
# Calculates value of investment
stock_data$Value[ind] <- as.numeric(stock_data$LastClose[ind]) * as.integer(stock_data$NumShares[ind])
ind <- ind+1
}
# Calculate Weights
for (i in 1:length(stock_data$Ticker)){
stock_data$Weight[i] <- as.numeric(stock_data$Value[i]) / sum(as.numeric(stock_data$Value))
stock_data$WeightedVol[i] <- as.numeric(stock_data$Weight[i]) * as.numeric(stock_data$Volatility[i])
}
# Set Variables
portfolio_vol <- sum(as.numeric(stock_data$WeightedVol))
portfolio_val <- sum(as.numeric(stock_data$Value))
rfr_invest <- 0.0508 # 4-week t-bill as of May 31, 2023
sims <- 10000
t_invest <- 21/252
set.seed(12345678)
# Calculate returns using a parametric simulation
VaR <- function(pv, rfr, vol, t, simulations) {
end_price <- pv * exp((rfr - 0.5 * vol ** 2) * t + rnorm(simulations) * vol * sqrt(t))
sim_returns <- end_price - pv
return(sim_returns)
}
foo <- VaR(portfolio_val, rfr_invest, portfolio_vol, t_invest, sims)
# Display results
cat(paste0("Portfolio Value of: ",
format(round(portfolio_val, 2), nsmall = 2)),
"zł","\n","VALUE AT RISK FOR ONE MONTH INVESTMENT","\n")
hist(foo, main = "Value at Risk", xlab = "P/L on Investment", ylab = "Frequency", col = "#15935C", breaks = 75)
percentiles <- c(0.1, 0.05, 0.01)
bar <- quantile(foo, probs = percentiles)
for (i in 1:length(percentiles)) {
cat("Value at Risk at", paste0((1 - percentiles[i]) * 100, "%"), "confidence interval:", format(round(bar[i], 2), nsmall = 2), "\n")
abline(v = bar[i], col = "#155B96", lwd = 3, lty = 2)
}
```
## Introduction
In my analysis, I created a dynamic program that takes historical share price data and calculates the value at risk for a portfolio. The program takes historical share price data sets in .csv format. It then prompts the user to input the number of shares they own. It automatically calculates the value of the portfolio, its volatility, and the value at risk for holding the portfolio for one month. For demonstrative purposes, I sourced data from [Stooq](https://stooq.pl) on 6 public companies listed on the Warsaw Stock Exchange. Under normal circumstances, the user is prompted to enter the number of shares. For this report, however, this is impossible, so we provided example figures (see NumShares column in the [Table](#table) below).
## Steps
The program uses the following methodology to arrive at the final results:
1. Compile all the .csv files from the folder in the working directory.
2. Create a data frame from this data.
3. Calculate historical volatility using the formulas:
$$ Volatility = StdDev(\sum_{i=1}^{n} Return_i)$$
$$ Annualized\space{}Volatility = \sqrt252 *Volatility$$
4. Calculate the value of investment: shares owned * last close price.
5. Calculate the weights of the portfolio components and their weighted volatilities.
6. Sum all individual weighted volatilities and values to get portfolio volatility.
7. Calculate value at risk using the formulas:
$$End\space{}Price=PV*e^{(rfr-0.5*vol^2)*t+z*σ}$$
$$Investment\space{}Return = End\space{}Price - PV$$
```
Where:
rfr = Risk Free Rate #4-week t-bill as of May 31, 2023
vol = Historical Volatility
t = Time #time period for investment in years = 21/252
z = Random Variable #number of simulations run = 10000
σ = Historical Std.
```
8. Plot a histogram with vertical lines at the confidence levels.
9. Display a written record of the results of the simulation.
## Table
We use values from the data frame that holds stock data and all calculated results to form the table below. The "Last Close" column lists the prices of each stock at market close on the last trading day of May. "Volatility" is the same as the standard deviation of all the daily portfolio returns throughout the month. "Weight" is calculated by determining what fraction of the entire portfolio each individual position constitutes. Finally, that weight is multiplied by volatility to obtain the "Weighted Volatility".
```{r echo=FALSE}
md_data <- stock_data
md_data$Volatility <- round(as.numeric(md_data$Volatility), 2)
md_data$LastClose <- format(round(as.numeric(md_data$LastClose), 2),nsmall=2)
md_data$Value <- format(round(as.numeric(md_data$Value), 2),nsmall=2)
md_data$Weight <- paste0(round(as.numeric(md_data$Weight), 4) * 100,"%")
md_data$WeightedVol <- round(as.numeric(md_data$WeightedVol), 4)
knitr::kable(md_data, align=rep("c",7))
```
## Histogram
The histogram shows the results of the simulation in a comprehensible way. It shows the frequency of the various likely outcomes that follow a normal distribution. The dotted red lines indicate the values for the commonly used confidence levels of 99%, 95%, 90%, from left to right. These red lines indicate that the represented value is unlikely to be lost, with x confidence, while holding the investment for one month.
```{r foo, echo=FALSE}
hist(foo, main = "Value at Risk", xlab = "P/L on Investment", ylab = "Frequency", col = "#15935C", breaks = 75)
for (i in 1:length(percentiles)) {
cat("Value at Risk at", paste0((1 - percentiles[i]) * 100, "%"), "confidence interval:", format(round(bar[i], 2), nsmall = 2), "\n")
abline(v = bar[i], col = "#155B96", lwd = 3, lty = 2)
}
```
## Conclusion & Overall Thoughts
Value at Risk gives the investor an estimate of the potential losses within a portfolio over a given period of time with a given confidence level. In this project, it provides a useful way to measure portfolio risk based on historical price data and volatility.
However, Value at Risk has limitations. It relies on assumptions about market behavior and historical trends that may not always hold true in real-world conditions. As a result, the estimates produced by the model should be treated as approximations rather than exact predictions.
Overall, the program demonstrates how Value at Risk can be used to assess portfolio risk in a clear and practical way. While the results can be useful for analysis, they should be considered alongside other methods and broader market context rather than used as the sole basis for investment decisions.