Pemodelan dan Teori Risiko

~ Mid Exam ~


Kontak : \(\downarrow\)
Email
Instagram https://www.instagram.com/diasary_nm/
RPubs https://rpubs.com/diyasarya/

Soal 1

Consider a portfolio consisting of five stocks from different sectors in Indonesia and analyze the diversification benefits of combining stocks. Your answer should cover at least the following steps:

library(quantmod)
library(plotly)
library(PerformanceAnalytics)

# a. Use quantmod for downloading stock data.

saham <- c('BBCA.JK', 'ASII.JK', 'TLKM.JK', 'UNVR.JK', 'ICBP.JK')
sahamlabel = c("Bank Central Asia Tbk.", "Astra International Tbk.", "Telkom Indonesia (Persero)", "Unilever Indonesia Tbk.", "Indofood CBP Sukses Makmur Tbk.")

HargaPenutupan <- NULL                                                          
for (data in saham)
HargaPenutupan <- cbind(HargaPenutupan,getSymbols.yahoo(data, from="2022-01-01", auto.assign=FALSE)[,4])    # kombinasikan data harga saham (data frame)
HargaPenutupan <- HargaPenutupan[apply(HargaPenutupan,1,function(x) all(!is.na(x))),]                              # hapus semua data tanpa harga (jika ada) 
names(HargaPenutupan)[names(HargaPenutupan) ==
                 c("BBCA.JK.Close", "ASII.JK.Close", "TLKM.JK.Close", "UNVR.JK.Close", "ICBP.JK.Close")] <-
  
                 c("BBCA", "ASII", "TLKM", "UNVR", "ICBP")

Saham yang digunakan dalam diversifikasi portofolio yaitu,
1. Bank Central ASia (BBCA.JK)
2. Astra International (ASII.JK)
3. Telkom Indonesia (TLKM.JK)
4. Unilever Indonesia (UNVR.JK)
5. Indofood CBP Sukses Makmur (ICBP.JK)

# b. Define a function calculate_returns() to calculate daily returns from the closing prices of the stocks and apply this function to each stock's price series

calculate_returns <- function(hargasaham) {
  returns <- diff(log(hargasaham))              # Perhitungan return menggunakan metode log
  return(returns)
}
returnsaham <- lapply(HargaPenutupan, calculate_returns)

# c. Combine the returns of all stocks into a single data frame.

dfreturn <- do.call(cbind, returnsaham)

head(dfreturn)
##                    BBCA         ASII         TLKM         UNVR         ICBP
## 2022-01-03           NA           NA           NA           NA           NA
## 2022-01-04  0.010186845  0.008695707 -0.002395211  0.004716990  0.017241806
## 2022-01-05  0.006734032 -0.035245939 -0.029199155 -0.009456335  0.005681833
## 2022-01-06  0.003350087  0.017778246  0.017136282  0.004739345  0.002828856
## 2022-01-07  0.023141529  0.004395611  0.012062872 -0.002366865  0.002820876
## 2022-01-10 -0.006557401 -0.008810630 -0.016929062  0.007083855 -0.002820876

Untuk perhitungan return menggunakan metode log, harga saham dilogkan lalu cari selisihnya waktu ke-n dengan ke-(n-1). Tabel diatas adalah return dari masing-masing saham.

# d. Calculate the correlation matrix of returns using cor().

korelasisaham = cor(dfreturn, use = "pairwise.complete.obs")    # Korelasi dengan metode Pairwise
data.frame(korelasisaham)

Untuk melakukan perhitungan korelasi antar saham, disini menggunakan metode pairwise dengan “pairwise.complete.obs”. Tabel diatas adalah nilai korelasi antar saham.

# e. Visualize the correlation matrix using corrplot().

colnames(korelasisaham) = rownames(korelasisaham) = sahamlabel # Penamaan pada data frame korelasi

mask = matrix(F, nrow=nrow(korelasisaham), ncol=ncol(korelasisaham))
mask[lower.tri(mask)] = T

heatmap = plot_ly(z=korelasisaham, x=sahamlabel, y=sahamlabel, type="heatmap")
heatmap = heatmap %>%
  layout(title = "Correlation Heatmap of Indonesian Stocks Return Price", 
         xaxis = list(title=""), 
         yaxis=list(title=""),
         colorscale= "Inferno",
         margin = list(l=60, r=80, t=100, b=60))

heatmap

Untuk memudahkan melihat korelasi atau hubungan antar saham maka dibuat visualisasi heatmap. Dari visualisasi diatas didapat bahwa korelasi antar saham tidak begitu kuat yang artinya karakteristik dari satu saham dengan saham yang lain tidak sama.

# f. Calculate the portfolio's returns and standard deviation based on equal weights for each stock.

n <- length(HargaPenutupan)
weights <- rep(1/n, n)
  
portreturn <- colSums(na.omit(dfreturn * weights))   # na.omit untuk mengabaikan nilai NA
portsd <- sqrt(var(portreturn))
    
    
print(paste("Portfolio Returns:", mean(portreturn)))
## [1] "Portfolio Returns: -1.39994340181562e-06"
print(paste("Portfolio Standard Deviation:", portsd)) 
## [1] "Portfolio Standard Deviation: 0.000112515613133091"

Berdasarkan perhitungan rata-rata portofolio return dan standart deviasi didapatkan bahwa portofolio return sebesar - 0,001399% dengan standar deviasi sebesar 0,01%. Artinya portofolio investasi yang dihasilkan lebih stabil dikarenakan return yang rendah dengan standar deviasi yang rendah pula. Hal ini cocok bagi investor pemula agar modal investasi lebih terjaga karena risiko kerugiannya rendah.

return = na.omit(dfreturn)
colmean = apply(return, 2, mean, na.rm=T)
colsd <- apply(return, 2, sd, na.rm = TRUE)

print(colsd)
##       BBCA       ASII       TLKM       UNVR       ICBP 
## 0.01261183 0.01634538 0.01416644 0.02009436 0.01606686

Tabel diatas adalah standar deviasai dari masing-masing saham.

# g. Calculate the diversification ratio, which measures the extent to which the portfolio's risk is reduced due to diversification.
calculate_diversification_ratio <- function(portsd, colsd) {
weight_persaham <- sum(colsd) / length(colsd)
  
# Calculate diversification ratio
diversification_ratio <- portsd / weight_persaham
  
  return(diversification_ratio)
}

diversification_ratio <- calculate_diversification_ratio(portsd, colsd)
print(paste("Diversification Ratio:", diversification_ratio))
## [1] "Diversification Ratio: 0.00709565504812256"

Dari hasil perhitungan rasio diversifikasi didapat 0,007 atau 0,7% yang artinya bahwa diversifikasi dalam portofolio mampu mengurangi risiko sebesar 0,7%.

# h. Define the objective function and constraints for portfolio optimization. Here, we aim to maximize the portfolio return subject to the constraint that the sum of portfolio weights equals 1.
library(quadprog)

ekpektasireturn <- c(0.1, 0.1, 0.1, 0.1, 0.1)  # Return yang diinginkan dari masing-masing saham
cov_matrix <- matrix(korelasisaham, nrow=5)  # Covariance matrix

library(Matrix)
## Warning: package 'Matrix' was built under R version 4.1.3
pd_D_mat <- nearPD(cov_matrix)

D_mat <- as.matrix(pd_D_mat$mat)
d_vec <- rep(0, length(ekpektasireturn))
A_mat <- cbind(rep(1, length(ekpektasireturn)), diag(length(ekpektasireturn)))
b_vec <- c(1, d_vec)

# i. Find the optimal portfolio weights that maximize the portfolio return given the covariance matrix and constraints.
# Metode optimasi maksimum
library(quadprog)
output <- solve.QP(Dmat = D_mat, dvec = d_vec, Amat = A_mat, bvec = b_vec, meq = 1)

# Optimal portfolio weights
optimal_weights <- output$solution
print(optimal_weights)
## [1] 0.1596782 0.2127760 0.2036109 0.2066979 0.2172369

Dengan mengharapkan return masing-masing saham sebesar 10% maka proporsi yang optimal untuk masing-masing saham yaitu 15,9% (BBCA), 21,2% (ASSI), 20,3% (TLKM), 20,7% (UNVR), 21,7% (ICBP).

# j. Visualize the optimal weights assigned to each stock in the portfolio.
library(plotly)

colors <- c("#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd")
plot_data <- data.frame(Symbol = saham, Weight = optimal_weights, Color = colors)

bar_plot <- plot_ly(plot_data, x = ~Symbol, y = ~Weight, type = 'bar', 
                    marker = list(color = ~Color)) %>%
  layout(title = "Optimal Weights of Stocks in Portfolio",
         xaxis = list(title = "Stocks"),
         yaxis = list(title = "Weight"))

bar_plot

Atau untuk mempermudah dapat dilihat dari visualisasi diatas.

# k. Calculate the expected return and volatility of the optimized portfolio using the optimal weights and covariance matrix.
portekpektasireturn <- sum(optimal_weights * ekpektasireturn)

# Calculate portfolio volatility (standard deviation)
portvolatility <- sqrt(t(optimal_weights) %*% cov_matrix %*% optimal_weights)

# Print the results

print(paste("Expected Return of the Portfolio:", portekpektasireturn))
## [1] "Expected Return of the Portfolio: 0.1"
print(paste("Portfolio Volatility (Standard Deviation):", portvolatility*portsd))
## [1] "Portfolio Volatility (Standard Deviation): 6.08146141944616e-05"

Dengan return yang diharapkan sebesar 10% volatilitasnya sebesar 0,0608%.

Soal 2

Assume you are working as an Actuary at an Insurance Company. Your job is to define insurance claims data and analyze the risk associated with different scenarios. Consider explaining your answer in details as the following instructions:

# a. Generate insurance claims data for a hypothetical insurance company with 10000 policies over 17 years.
set.seed(863)
policies <- 10000
years <- 17

# Mean number of claims per policy per year (assuming Poisson distribution)
lambda <- 0.1


# Initialize empty data frame to store claims data
claims_data <- data.frame(
  Policy_ID = integer(),
  Year = integer(),
  Claims = numeric(),
  Claim_Amount = numeric()
)

# Generate claims data for each policy and year
for (policy_id in 1:policies) {
  for (year in 1:years) {
# c. Simulate claim frequencies for each policy from a Poisson distribution with a mean of 0.1 (i.e., on average, each policy has 0.1 claims per year).
    num_claims <- rpois(1, lambda)
    
    if (num_claims > 0) {
# d. Simulate claim amounts for each policy and each year from a normal distribution with a mean of 5007 and a standard deviation of 2007.
    claim_amounts <- round(rnorm(num_claims, 5007, 2007),2)
    
    claims_data <- rbind(claims_data, data.frame(
      Policy_ID = rep(policy_id, num_claims),
      Year = rep(year, num_claims),
      Claims = num_claims,
      Claim_Amount = claim_amounts
    ))
  }
}
}

claims_data
# b. Generate random policy premiums from a normal distribution with a mean of 1007 and a standard deviation of 2007.
set.seed(863)
policy_premiums <- abs(round(rnorm((nrow(claims_data)), mean = 1007, sd = 2007), 2))
claims_data$Premiums = policy_premiums
# e. Calculate total claim amounts per policy and then calculate loss ratios (total claims divided by premiums) to assess the risk associated with each policy.
total_claim_amounts <- tapply(claims_data$Claim_Amount, claims_data$Policy_ID, sum)

total_premiums <- tapply(claims_data$Premiums, claims_data$Policy_ID, sum)

loss_ratios <- total_claim_amounts / total_premiums

loss = data.frame(loss_ratios)
loss
# f. Plot a histogram of the loss ratios to visualize the distribution of risk.
loss_ratio_histogram <- plot_ly(x = loss_ratios, type = "histogram", 
                                name = "Loss Ratios", 
                                xbins = list(size = 0.1), 
                                marker = list(color = "yellow"))

loss_ratio_histogram <- loss_ratio_histogram %>% 
  layout(title = "Histogram of Loss Ratios",
         xaxis = list(title = "Loss Ratio"),
         yaxis = list(title = "Frequency"))

loss_ratio_histogram

Berdasarkan hasil plot bahwa loss ratio berkumpul pada titik 0 tetapi frequensi klaim masih tinggi.

# g. Calculate summary statistics including the mean, median, and 95th percentile of the loss ratios.
mean_loss_ratio <- mean(loss_ratios)
median_loss_ratio <- median(loss_ratios)
p95_loss_ratio <- quantile(loss_ratios, probs = 0.95)

# Display summary statistics
cat("Mean Loss Ratio:", mean_loss_ratio, "\n")
## Mean Loss Ratio: 6.868065
cat("Median Loss Ratio:", median_loss_ratio, "\n")
## Median Loss Ratio: 2.980516
cat("95th Percentile of Loss Ratios:", p95_loss_ratio, "\n")
## 95th Percentile of Loss Ratios: 16.02537