- Soal 1
- Stock Data Import
- Calculate daily returns and Combine (B&C)
- Correlation matrix using Cor()
- Using the Corrplot()
- Using Plotly
- Calculate the portfolios returns and standard deviation based on equal weights for each stock.
- Diversification Ratio
- Define Functions and Constraints for Portofolio Optimizations
- Visualize Optimal Weight
- Expected Return and Volatility.
- Soal 2
Soal 1
Consider a portfolio consisting of five stocks from different sectors in Indonesia and analyze the diversification benefits of combining stocks.
Stock Data Import
Menggunakan Library quantmod yang terhubung ke yahoo
finance, Kita akan melakukan analisis terhadap 5 emiten saham di
Indonesia. Yaitu 1. Adaro Energy Tbk. (ADRO) di bidang Energy 2.
Barito Pacific Tbk. (BRPT) di bidang Energy 3. Indofood CBP Sukses
Makmur Tbk. (ICBP) di bidang Produksi Pangan 4. PT. Saratoga
Investama Sedaya (SRTG) di bidang Investasi 5. Sumber Alfaria
Trijaya Tbk (AMRT) di bidang Perdagangan, Jasa dan Investasi
library(quantmod)
library(plotly)
library(PerformanceAnalytics)
tick = c('ADRO.JK', 'BRPT.JK', 'ICBP.JK','SRTG.JK', 'AMRT.JK')
ticklabel = c("Adaro Energy Tbk.", "Barito Pacific Renewable Energy", "Indofood CBP Sukses Makmur Tbk.", " PT. Saratoga Investama Sedaya ", "Sumber Alfaria Trijaya Tbk.")
stocksss = getSymbols(tick, from="2022-03-01", to="2024-03-01", src="yahoo", adjust=F)
stocksss## [1] "ADRO.JK" "BRPT.JK" "ICBP.JK" "SRTG.JK" "AMRT.JK"
Calculate daily returns and Combine (B&C)
closing = NULL
for (stock in tick) { closing = cbind(closing, Cl(get(stock)))}
return = Return.calculate(closing)
return = data.frame(return)
head (return)## ADRO.JK.Close BRPT.JK.Close ICBP.JK.Close SRTG.JK.Close
## 2022-03-01 NA NA NA NA
## 2022-03-02 0.01162791 0.00000000 -0.039393939 0.05109489
## 2022-03-04 0.16475096 0.00000000 -0.012618297 0.06250000
## 2022-03-07 0.06578947 -0.06629833 -0.054313099 -0.03594771
## 2022-03-08 -0.03703704 -0.02366863 0.027027027 0.01016949
## 2022-03-09 -0.01282051 0.01818178 0.003289474 -0.03020134
## AMRT.JK.Close
## 2022-03-01 NA
## 2022-03-02 0.000000000
## 2022-03-04 -0.004587156
## 2022-03-07 0.055299539
## 2022-03-08 -0.065502183
## 2022-03-09 -0.014018692
Correlation matrix using Cor()
## ADRO.JK.Close BRPT.JK.Close ICBP.JK.Close SRTG.JK.Close
## ADRO.JK.Close 1.000000000 0.11337547 -0.007553162 0.47225880
## BRPT.JK.Close 0.113375466 1.00000000 0.118088004 0.03514881
## ICBP.JK.Close -0.007553162 0.11808800 1.000000000 0.01073091
## SRTG.JK.Close 0.472258801 0.03514881 0.010730909 1.00000000
## AMRT.JK.Close 0.104400474 0.02611816 -0.048232684 0.06136409
## AMRT.JK.Close
## ADRO.JK.Close 0.10440047
## BRPT.JK.Close 0.02611816
## ICBP.JK.Close -0.04823268
## SRTG.JK.Close 0.06136409
## AMRT.JK.Close 1.00000000
Using the Corrplot()
## corrplot 0.92 loaded
Using Plotly
colnames(corstock) = rownames(corstock) = ticklabel #Renaming
mask = matrix(F, nrow=nrow(corstock), ncol=ncol(corstock))
mask[lower.tri(mask)] = T
heatmap = plot_ly(z=corstock, x=ticklabel, y=ticklabel, 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))
heatmapEach Stocks Tends to have low correlation between each others. This means that the portfolio has slightly been diversed.
Calculate the portfolios returns and standard deviation based on equal weights for each stock.
num_stocks <- length(closing)
weights <- rep(1/num_stocks, num_stocks)
portfolio_returns <- rowSums(closing * weights)
portfolio_sd <- sqrt(var(portfolio_returns))
cat("Portfolio Returns:", mean(portfolio_returns), "\n")## Portfolio Returns: 7.641943
## Portfolio Standard Deviation: 0.4734845
If a portfolio has a return of 7.64%, it means that over a specific period (in this case 2 years), the value of the portfolio has increased by 7.64% compared to its initial value. With the standard Deviation of 0.47%. Which brings us to the growth interval of 7-8%.
Diversification Ratio
return = na.omit(return)
column_mean = apply(return, 2, mean, na.rm=T)
column_sd <- apply(return, 2, sd, na.rm = TRUE)
# Print the standard deviation of each column
print(column_sd)## ADRO.JK.Close BRPT.JK.Close ICBP.JK.Close SRTG.JK.Close AMRT.JK.Close
## 0.02598076 0.03410616 0.01638133 0.02718201 0.02349844
calculate_diversification_ratio <- function(portfolio_sd, column_sd) {
weighted_avg_individual_sd <- sum(column_sd) / length(column_sd)
# Calculate diversification ratio
diversification_ratio <- weighted_avg_individual_sd / portfolio_sd
return(diversification_ratio)
}
diversification_ratio <- calculate_diversification_ratio(portfolio_sd, column_sd)
cat("Diversification Ratio:", diversification_ratio, "\n")## Diversification Ratio: 0.05370765
A diversification ratio of 0.05 suggests that diversification has significantly reduced the portfolio’s risk. Typically, a lower diversification ratio indicates a greater reduction in risk due to diversification.
Define Functions and Constraints for Portofolio Optimizations
Assume we want a flat 8% Profit of returns, and the covariance matrix is the corelation between the Stocks.
library(quadprog)
# Example data (replace with your actual data)
expected_returns <- c(0.08, 0.08, 0.08, 0.08, 0.08) # Expected returns for assets
cov_matrix <- matrix(corstock, nrow=5) # Covariance matrix
library(Matrix)
pd_D_mat <- nearPD(cov_matrix)
# Use the positive definite matrix for optimization
D_mat <- as.matrix(pd_D_mat$mat)
d_vec <- rep(0, length(expected_returns))
A_mat <- cbind(rep(1, length(expected_returns)), diag(length(expected_returns)))
b_vec <- c(1, d_vec)
# Solve quadratic programming problem
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.1320957 0.2040455 0.2474381 0.1735723 0.2428484
The Conclusion will then be Visualize.
Visualize Optimal Weight
Expected Return and Volatility.
expected_return_portfolio <- sum(optimal_weights * expected_returns)
# Calculate portfolio volatility (standard deviation)
portfolio_volatility <- sqrt(t(optimal_weights) %*% cov_matrix %*% optimal_weights)
# Print the results
cat("Expected Return of the Portfolio:", expected_return_portfolio, "\n")## Expected Return of the Portfolio: 0.08
## Portfolio Volatility (Standard Deviation): 0.2417485
As the expected Return was flat 8%, so does the restult of Optimized Portfolio. Meanwhile, Volatility is often expressed as the standard deviation of returns. A standard deviation measures the dispersion or variability of a set of values. In this case, it measures how much the returns of the financial instrument fluctuate around their 0.24% of their average return of 8% .
Soal 2
Data Generating
# Set the seed for reproducibility
set.seed(123)
# Number of policies
policies <- 10000
# Number of years
years <- 16
# 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(
PolicyID = integer(),
Year = integer(),
Claims = numeric(),
ClaimAmount = numeric()
)
# Generate claims data for each policy and year
for (policy_id in 1:policies) {
for (year in 1:years) {
# Generate number of claims for the policy and year
num_claims <- rpois(1, lambda)
if (num_claims > 0) {
# Generate claim amounts for each claim
claim_amounts <- rnorm(num_claims, 5006, 2006)
# Append data to claims_data data frame
claims_data <- rbind(claims_data, data.frame(
PolicyID = rep(policy_id, num_claims),
Year = rep(year, num_claims),
Claims = num_claims,
ClaimAmount = claim_amounts
))
}
}
}
# View the first few rows of the claims data
head(claims_data)## PolicyID Year Claims ClaimAmount
## 1 1 5 1 1616.751
## 2 1 9 1 4770.813
## 3 1 16 1 7461.508
## 4 2 2 1 5809.948
## 5 2 7 1 7603.295
## 6 5 13 1 7499.295
Simulate Claim Amounts
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). and then Simulate claim amounts for each policy and each year from a normal distribution with a mean of 5006 and a standard deviation of 2006.
All was Done in Point 1
## PolicyID Year Claims ClaimAmount Premiums
## 1 1 5 1 1616.751 118.3141
## 2 1 9 1 4770.813 544.2640
## 3 1 16 1 7461.508 4132.7689
## 4 2 2 1 5809.948 1147.4398
## 5 2 7 1 7603.295 1265.3512
## 6 5 13 1 7499.295 4446.4204
Calculate total claim amounts per policy and then calculate loss ratios
total_claim_amounts <- tapply(claims_data$ClaimAmount, claims_data$PolicyID, sum)
total_premiums <- tapply(claims_data$Premiums, claims_data$PolicyID, sum)
loss_ratios <- total_claim_amounts / total_premiums
# Display the first few loss ratios
ratio = data.frame(loss_ratios)
head(ratio)## loss_ratios
## 1 2.888023
## 2 5.559223
## 5 1.686592
## 6 5.225253
## 7 1.619086
## 8 2.596906
Only Positice Ratio Loss were viewed. If the loss ratios are positive, it means that the total claim amounts for a policy exceed the premiums paid for that policy.The insurance company is experiencing losses on those policies. It suggests that the company is paying out more in claims than it had anticipated based on the premiums it charged.
Histogram
loss_ratio_histogram <- plot_ly(x = loss_ratios, type = "histogram",
name = "Loss Ratios",
xbins = list(size = 0.1),
marker = list(color = "pink"))
loss_ratio_histogram <- loss_ratio_histogram %>%
layout(title = "Histogram of Loss Ratios",
xaxis = list(title = "Loss Ratio"),
yaxis = list(title = "Frequency"))
# Show the histogram
loss_ratio_histogramAn Outlier Detected that messed up the Histogram created, here let we see where the outlieres were
Terdapat banyak outliers, mengindikasikan operusahaan banyak mengalami kerugian.
Summary
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: 9.421615
## Median Loss Ratio: 2.954068
## 95th Percentile of Loss Ratios: 16.92062
Mean of the Loss Ratio was 9.42 with 95th Percentile in 16.9 Implying that the company is suffering loss because more claims than premium acquired.