Forecasting

One of the main ways that we can use the descriptive statistics that we have calculated to understand the underlying nature of assets is Monte Carlo Simulation. Playing on the idea of random outcomes, this simulation will try, given asset characteristics, to project possible alternative states of the world. These alternative states can then be used to start thinking about the range of possible outcomes.

There are two main ways that Monte Carlo Simulation can be carried out:

Parametric forecasting

In this case we use Bank of America data to estimate possible outcomes.

da <- read.csv('../../Data/BACSPY.csv')
da$Date <- as.Date(da$Date, format = "%d/%m/%Y")
da$BACR <- c(NA, da$BAC[2:length(da$BAC)]/
               da$BAC[1:length(da$BAC) -1 ] -1)

Parametric simulation

Now we assume that there is a normal distribution for daily returns with a mean of 4^{-4} and a standard deviation of 0.0292.

Start by setting some assumptions for things like the last BAC price, the expected return (\(\mu\)) and the expected level of risk (\(\sigma\)). Then create a matrix to hold the random returns drawn from a normal distribution with a mean the same as that of Bank of America returns (called mu) and a standard deviation the same as that of Bank of America returns (called sigma). How many period ahead will we simulate and how many simulations will we make?

In this case we project forward from the last value, simulating the case where we want to prject forward from today.

S0 = da$BAC[length(da$BAC)] # starting price (last value) s
mu = mean(da$BACR, na.rm = TRUE)# average daily return
sigma = sd(da$BACR, na.rm = TRUE) # average standard deviation
periods <- 252 # one year ahead
simulations <- 1000 # One thousand simulations
# Create a vector to hold the simulated price paths
myMCmatrix <- matrix(nrow = periods, ncol = simulations)
# Now fill the columns with simulated data
# loop through from 1 to the number of simulations (columns)
for(i in 1:simulations){
  myMCmatrix[ , i] <- cumprod(c(S0, 
                               1 + rnorm(periods - 1, 
                                     mean = mu, sd = sigma)))
}

Now plot the returns. Start with the first column to create the plot and then iterate through the columns to add the other simulated data.

plot(myMCmatrix[, 1], type = 'l', 
     main = "Parametric Bank of American price",
     xlab = "Days ahead", ylab = "Price", 
     ylim = c(min(myMCmatrix), max(myMCmatrix)), 
     col = rgb(0, 0, 0.4, 0.4))
apply(myMCmatrix, MARGIN = 2, function(x) 
  lines(x, col = rgb(0.0, 0, 0.4, 0.4)))

## NULL

It is possible to look at the expect return and the distribution by taking the mean and the fifth and ninety-fifth quantiles. The expected return is 27.65 and the ninety five confidence intervals run between 15.33 and 45.59.

Non-parametric returns

It is well known that financial asset returns do not usually display a normal distribution. To ensure that we have the same distribution of returns as the original (BOA) series, instead of of assuming a normal distribution and drawing from a normal distribution, we draw samples from the Bank of America returns.

In this case we use the apply() function. This is a really useful construction that will apply a written function to a data set either rows MARGIN = 1 or columns MARGIN = 2. The function can be specified in advance or in line as it is below.

This will take the form.

apply(mydata, MARGIN = 2, function(x) mean(x, na.rm = TRUE))

This means apply the specified function (in this case mean) to the columns (MARGIN = 2) of this data (mydata). In our case we want to add lines of simulated data to the plot that has already been created.

# Create a new vector for the NP returns
# These will sample from da$BACR with replacement
myMCNPmatrix <- matrix(nrow = periods, ncol = simulations)
for(i in 1:simulations){
  myMCNPmatrix[, i] <- cumprod(c(S0, (1 + sample(da$BACR[-1], 
                                             size = periods -1,
                                             replace = TRUE))))
}
plot(myMCNPmatrix[, 1], type = 'l', 
     main = "Bank of America non-parametric simulations", 
     ylim = c(min(myMCNPmatrix),  max(myMCNPmatrix)), 
     col = c(0, 0, 0.4, 0.4), ylab = 'Price', xlab = "Days")
# Using the apply function which will apply a specified 
# function to rows (1) or, more likely, columns (2)
# that is the MARGIN argument. 
apply(myMCNPmatrix[, -1], MARGIN = 2, function(x) 
  lines(x, col = rgb(0, 0, 0.4, 0.4)))

## NULL

We can compare the two models. This can be done by looking at the final values (in row 252) which is assumed to be in one year, or any time in the whole period being simulated. This will depend on the question to be answered: where can it end up or where can it go through the year?

In the first case look at the histogram of final values.

hist(myMCmatrix[periods, ], col = rgb(0, 0, 0.4, 0.4), 
     main = "Distribution of final parametric values", 
     prob = TRUE, xlab = "Final Price",
     xlim = c(0, 200))

hist(myMCNPmatrix[periods, ], col = rgb(0, 0, 0.4, 0.4), 
     main = "Distribution of final non-parametric values",
     prob = TRUE, xlab = "Final Price", 
     xlim = c(0, 200))

We can also look at some values for the whole periods

round(max(myMCmatrix), 2)
## [1] 107.25
round(max(myMCNPmatrix), 2)
## [1] 132.77
round(min(myMCmatrix), 2)  
## [1] 6.3
round(min(myMCNPmatrix), 2)  
## [1] 5.89
round(quantile(myMCmatrix, 0.95), 2) 
##   95% 
## 45.59
round(quantile(myMCmatrix, 0.05), 2)
##    5% 
## 15.33
round(quantile(myMCNPmatrix, 0.95), 2) 
##   95% 
## 44.43
round(quantile(myMCNPmatrix, 0.05), 2)
##    5% 
## 15.06