## ---- include = FALSE--------------------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 6, fig.align = 'center' ) ## ----setup-------------------------------------------------------------------- library(LSMRealOptions) set.seed(1) ## ----------------------------------------------------------------------------- # Step 1 - Simulate stock prices: stock_prices <- GBM_simulate(n = 1e4, t = 1, mu = 0.06, sigma = 0.2, S0 = 36, dt = 1/50) ## ----------------------------------------------------------------------------- # Step 2 - Value American put option: put_option_value <- LSM_american_option(state_variables = stock_prices, payoff = stock_prices, K = 40, dt = 1/50, rf = 0.06, verbose = TRUE) print(round(unlist(put_option_value[1:5]),4)) ## ----------------------------------------------------------------------------- # Step 1 - Simulate asset prices: asset_prices <- array(dim = c(51, 1e3, 2)) for(i in seq_len(2)) { asset_prices[,,i] <- GBM_simulate(n = 1e3, t = 1, mu = 0.06, sigma = c(0.2, 0.3)[i], S0 = c(38, 35)[i], dt = 1/50)} ## ----------------------------------------------------------------------------- # Step 2 - Value American-style option: OptionValue <- LSM_american_option(state_variables = asset_prices, payoff = pmax(asset_prices[,,1], asset_prices[,,2]), K = 40, dt = 1/50, rf = 0.06, verbose = TRUE, cross_product = TRUE, orthogonal = "Laguerre", degree = 9) print(round(unlist(OptionValue[1:5]),4)) ## ----------------------------------------------------------------------------- ## Exercise opportunities per year: dt <- 1/50 ## strike price : K <- 40 ## short-term interest rate: rf <- 0.06 ## 100,000 simulations (50% antithetic): n_simulations <- 1e5 ## Stock price volatility: sigma <- rep(c(rep(0.2,2),rep(0.4,2)),5) ## Stock price: S0 <- sort(rep(seq(36,44,2),4)) ## Option maturity: TTM <- rep(1:2, 10) LSM_output <- matrix(0, 20, 2, dimnames = list(NULL, c("Simulated American", "(s.e)"))) ## Cycle through the rows of the table: for(i in 1:20){ simulated_values <- GBM_simulate(n = n_simulations, t = TTM[i], mu = rf, sigma = sigma[i], S0 = S0[i], dt = dt) ## American option pricing through LSM Simulation output <- LSM_american_option(state_variables = simulated_values, payoff = simulated_values, call = FALSE, K = K, dt = dt, rf = rf, verbose = TRUE, orthogonal = "Laguerre", degree = 3 ) LSM_output[i,1] <- output$Value LSM_output[i,2] <- output$`Standard Error` } ## Compile and print results: LnS_table1 <- cbind.data.frame(S = S0, sigma = sigma, T = TTM, LSM_output) print(round(LnS_table1,3)) ## ----------------------------------------------------------------------------- # Step 1 - Simulate the underlying asset price: ## Initial underlying price: initial_price <- 36 ## discrete time step: dt <- 1/12 ## Project lifetime (in years): project_lifetime <- 10 forecasting_periods <- seq(0, project_lifetime, dt) revenue_prices <- GBM_simulate(n = 2e4, t = project_lifetime, mu = 0.06, sigma = 0.2, S0 = initial_price, dt = dt) # Step 2 - Evaluate cash flows: ## Fixed cash flow: # FCF <- 1e4 * initial_price FCF <- 1e4 * 36 ## Net cash flow is equal to variable cash flows subtract fixed cash flows: NCF <- (1e4 * revenue_prices - FCF) * dt ## Financial Parameters: construction <- 0.5 / dt rf <- 0.05 ## Initial capital investment: learning_rate <- 0.01 CAPEX <- 1e5 * exp(- learning_rate * dt * (1:nrow(revenue_prices)-1)) # Step 3 - Evaluate Project Value through Real Options Analysis: project_value <- LSM_real_option(state_variables = revenue_prices, NCF = NCF, CAPEX = CAPEX, dt = dt, rf = rf, construction = construction, verbose = TRUE) print(format(unlist(project_value[1:6]), big.mark = ",")) ## ----------------------------------------------------------------------------- ## Evaluate Project Value with OF through ROA: project_value_OF <- LSM_real_option_OF(state_variables = revenue_prices, NCF = NCF, CAPEX = CAPEX, dt = dt, rf = rf, construction = construction, suspend_CAPEX = 0.1 * CAPEX[1], suspend_OPEX = 0.05 * CAPEX[1] * dt, resume_CAPEX = 0.1 * CAPEX[1], abandon_CAPEX = 0.2 * CAPEX[1], save_states = TRUE, verbose = TRUE, debugging = TRUE ) print(format(unlist(project_value_OF[1:7]), big.mark = ",")) ## ----------------------------------------------------------------------------- matplot(forecasting_periods, cbind(project_value$`Cumulative Investment Prob`, project_value_OF$`Cumulative Investment Prob`), type = 'l', ylim = c(0,1), xlab = "Forecasting Horizon", ylab = "Cumulative Investment Proportion", main = "Cumulative Investment Prop. over Forecasting Horizon") legend("right", c("ROV", "ROV + OF"),cex=0.8, col = 1:2, fill = 1:2) ## ---- warning = FALSE--------------------------------------------------------- states_list <- apply(matrix(colnames(project_value_OF$`Project States`)), 1, FUN = function(x) cbind.data.frame(x, project_value_OF$`Project States`[,x], forecasting_periods)) states_ggplot <- suppressWarnings(dplyr::bind_rows(states_list)) states_ggplot[,1] <- factor(states_ggplot[,1], levels = rev(colnames(project_value_OF$`Project States`))) colnames(states_ggplot) <- c("state", "count", "time") library(ggplot2) ggplot(states_ggplot, aes(x = time, y = count, fill = state)) + geom_bar(position = "fill", stat = "identity", width = 1) + scale_y_continuous(labels = scales::percent, breaks = seq(0,1,0.1)) + scale_x_continuous(breaks = seq(0, project_lifetime, 1)) + ggtitle("Proportion of Project States over Project Planning Horizon") + xlab("Planning Horizon (Years)") ## ----------------------------------------------------------------------------- # Instantiate iterations: it <- 0 current_price <- initial_price # Begin Investment Trigger Value Calculate: repeat{ # Step 1: Calculate the ROV using real options analysis LSM_results <- LSM_real_option(state_variables = revenue_prices, NCF = NCF, CAPEX = CAPEX, dt = dt, rf = rf, construction = construction) NPV <- LSM_results$NPV WOV <- LSM_results$WOV # Step 2: Evaluate the next initial asset price through the 'secant' method: ## For the first iteration, use an arbitrary initial price multiplier of 2 if(it == 0){ multiplier = 2 new_price = current_price * multiplier } if(it > 0){ ## NPV - a linear function of initial prices, so we can find it exactly after two iterations: NPV_gradient = (NPV - NPV_old) / (current_price - old_price) NPV_new_price = current_price + (0 - NPV)/NPV_gradient if(it == 2) NPV_crit_value = NPV_new_price ## ROV - Secant Method: new_price = current_price - WOV * ((current_price - old_price) / (WOV - WOV_old)) ## Which is a multiple of: multiplier = new_price / current_price ## The WOV does not have to be exactly zero. Having it within a tolerance value ## can be adequate and decrease processing time: WOV_tolerance <- abs(WOV) < 100 ## If the price is identical within one cent, this can be considered the critical value: price_tolerance <- round(new_price,2)==round(current_price, 2) ## If the underlying asset impacts costs, and the iteration has pushed the price of the asset ## below zero, it's never optimal to invest immediately: negative_price <- new_price < 0 ## Recursion break to ensure infinite loop does not occur: loop_break <- it > 20 ##Approximate the root of WOV to 2 significant figures: if(price_tolerance || WOV_tolerance || negative_price || loop_break){ ROV_crit_value = new_price break } } # Step 3: Update values: ## Updating simulated prices: revenue_prices <- revenue_prices * multiplier ## Updating the NCF of each period: NCF <- (1e4 * revenue_prices - FCF) * dt ## Updating values old_price <- current_price current_price <- new_price WOV_old <- WOV NPV_old <- NPV # Step 4: Re-iterate: it <- it + 1 } print(round(c(NPV = NPV_crit_value, ROV = ROV_crit_value),2)) ## ----------------------------------------------------------------------------- print(NFCP::SS_oil$two_factor[2:7]) ## ----------------------------------------------------------------------------- # Step 1 - List project parameters: ## Initial Price: initial_oil_price <- 60 ## Initial State vector: initial_state_vector <- c(log(initial_oil_price), 0) ## discrete time step: dt <- 1/12 ## Project lifetime (in years): project_lifetime <- 10 forecasting_periods <- seq(0, project_lifetime, dt) # Financial Parameters: ## Capital investment: CAPEX <- 1e4 ## Fixed cash flow: FCF <- 5e4 * initial_oil_price ## Construction - 6 months: construction <- 0.5 / dt ## Risk-free interest rate: rf <- 0.05 # Step 1 - Simulate spot prices: ## 10,000 antithetic simulations of one year of monthly observations simulated_oil_prices <- NFCP::spot_price_simulate( x_0 = initial_state_vector, parameters = NFCP::SS_oil$two_factor, t = 10, dt = dt, N_simulations = 1e4, antithetic = TRUE, verbose = TRUE) oil_revenue <- simulated_oil_prices$spot_prices state_variables = array(dim = c(dim(simulated_oil_prices$spot_prices), 3)) state_variables[,,1:2] = simulated_oil_prices$state_variables ## Include the price as a state variable: state_variables[,,3] = simulated_oil_prices$spot_prices ## Net cash flow of simulated price paths: NCF <- (1e5 * oil_revenue - FCF) * dt ## ----------------------------------------------------------------------------- project_value <- LSM_real_option(state_variables = state_variables, NCF = NCF, CAPEX = CAPEX, dt = dt, rf = rf, construction = construction, orthogonal = "Laguerre", degree = 9, verbose = T) print(format(round(unlist(project_value[1:6]),2), big.mark = ","))