library(tidyverse)
library(lubridate)
library(readxl)
library(highcharter)
library(tidyquant)
library(timetk)
library(tibbletime)
library(quantmod)
library(PerformanceAnalytics)
library(scales)
library(plotly)
library(rvest)
library(xml2)
library(tibble)
library(httr)
library(purrr)
library(dplyr)
rm(list = ls())

new=NULL
id_list=c('CII','DIG','HPG',"HT1",'HSG',"GAS","GVR",'TPB','TCB',
'MSN')

for (j in id_list){
for (i in 1:9){
  query_params <- list(currentPage=i,id = j)
  parameter_response <- GET("https://www.cophieu68.vn/historyprice.php", query = query_params)
  stock_share =read_html(parameter_response)
  new1=html_nodes(stock_share, xpath="//table[@class='stock']") %>%
    html_table(header = TRUE,fill=TRUE) %>% as.data.frame()
  new1=new1[,2:13]
  new1$symbol=j
  new=rbind(new,new1)
}}

stock=new

colnames(stock)=c("date","Last_closed_price","absolute_price_change",
                "Percentage_price_change", "Closed_price",
                "Trading_Volume","Open_price","Highest_price",
                "Lowest_price","Exchange_volume", "Foregin_buy_volume", "Foreign_sell_volume","symbol")

stock$date=as.Date(stock$date, format="%d-%m-%Y")
for (i in 2:12){stock[,i]=as.numeric(gsub(',', '', stock[,i]))}
stock$Trading_Volume=as.numeric(gsub(',', '', stock$Trading_Volume))
stock$Percentage_price_change=stock$absolute_price_change/stock$Last_closed_price

prices=stock %>% filter(!is.na(date))


# prices = prices %>%
#   select(date, Closed_price) %>%
#   mutate_at(vars(-date), as.numeric) %>%
#   mutate(date = ymd(parse_date_time(date, "%Y-%m-%d"))) %>%
#   arrange(date)

1 Visualizing Closing daily prices

prices %>%
    group_by(symbol) %>% 
    ggplot(aes(x = date, y = Closed_price, color = symbol)) +
    geom_line(size = 1.5) +
    labs(title = "Daily Stock Prices",
         x = "", y = "Closeded Prices", color = "") +
    facet_wrap(~ symbol, ncol = 5, scales = "free_y") +
    scale_y_continuous() +
    theme_tq() + 
    scale_color_tq()

2 Log Return Data Preparation

prices_daily_log_returns <- prices %>%
    group_by(symbol) %>%
    tq_transmute(select     = Closed_price, 
                 mutate_fun = periodReturn, 
                 period     = "daily", 
                 type       = "log",
                 col_rename = "daily.returns")

prices_daily_log_returns %>% ggplot(aes(x=date, y=daily.returns, col=symbol))+geom_line()+facet_wrap(symbol~.)

# Discard row with price tag
# 
# raw_data <- raw_data[-1,]%>%
#   select(.,-c(X,X.1,X.2,X.3))
# 
# raw_data <- raw_data[-c(1248,1249),]
# raw_data <- raw_data %>% mutate_at(vars(-Date), as.numeric) %>%
#   mutate(Date = ymd(parse_date_time(Date, "%d/%m/%Y"))) %>%
#   arrange(Date)
# 
# 
# # Extract each symbol for future usage if necessary
# symbols <- colnames(raw_data[,-1])
# 
# # Create return dataframe 
# data_wide_return <- sapply(raw_data[2:ncol(raw_data)], function(x) diff(log(x), lag =1))
# 
# data_wide_return <- cbind.data.frame(raw_data['Date'][-1,], data_wide_return)
# 
# colnames(data_wide_return)[1] = "Date"

prices_daily_log_returns %>% filter(date > "2018-06-04" ,  date < "2021-11-03") %>% pivot_wider(names_from = symbol, values_from = daily.returns) -> data_wide_return
# Remove date column: 

data_wide_return %>% select(-date) -> return_wide_train

# Calculate stock mean: 
mean_ret <- colMeans(return_wide_train) 

# Covariance matrix: 

cov_mat <- cov(return_wide_train)

# Number of observations: 
T_rows <- nrow(return_wide_train)

# Number of stock symbols: 
N <- ncol(return_wide_train)

# Risk-free rate
Rf <- 5.11/100

# Defining the Sharpe ratio function

sharpe_func <- function(w1,w2,w3,w4,w5,w6,w7,w8,w9,w10){
  weight <- c(w1,w2,w3,w4,w5,w6,w7,w8,w9,w10)
  
  # Sharpe ratio numerator (Difference between return of portfolio and return of the market)
  numerator <- numeric()
  
  for (i in 1:N) {
    numerator[i] <- weight[i]*mean_ret[i]
  }
  
  # Sharpe ratio denominator
  
  denominator<- numeric()
  for (i in 1:N) {
    denominator1 <- numeric()
    for (j in 1:N) {
      denominator1[j] <- weight[i]*weight[j]*cov_mat[i,j]
    }
    denominator[i] <-sum(denominator1)
  }

sharpe_func<- (sum(numerator) - Rf)/sum(denominator)
sharpe_func <- sharpe_func - 1e9 * (round(sum(weight),10)-1)^2

 result <- list(Score = sharpe_func, Pred = 0)
 return(result)
 
}
# Place for replicate coding input 
# x = 5:30
# 
# paste0("w", x, "= runif(20,0,1)", collapse = ",")
library(rBayesianOptimization)
# Defining search boundary

search_bound <- list(w1= c(0,0.5),w2= c(0,0.5),w3= c(0,1),w4= c(0,1),w5= c(0,0.5),w6= c(0,0.5),w7= c(0,0.5),w8= c(0,1),w9= c(0,1),w10= c(0,1))

# Defining the initial weight 

set.seed(29)
search_grid <- data.frame(w1 = runif(20,0,0.5), 
                          w2 = runif(20,0,0.5),
                          w3 = runif(20,0,1),
                          w4 = runif(20,0,1),
                          w5= runif(20,0,0.5),w6= runif(20,0,1),w7= runif(20,0,0.5),w8= runif(20,0,1),w9= runif(20,0,1),w10= runif(20,0,1))

bayes_finance_ucb <- BayesianOptimization(FUN = sharpe_func, bounds = search_bound, 
                     init_grid_dt = search_grid, init_points = 0, 
                     n_iter = 10, acq = "ei")
## elapsed = 0.02   Round = 1   w1 = 0.04984052 w2 = 0.3329466  w3 = 0.6111826  w4 = 0.4156561  w5 = 0.3312624  w6 = 0.1508912  w7 = 0.198907   w8 = 0.8652624  w9 = 0.1592352  w10 = 0.4184502 Value = -6419302564.2893 
## elapsed = 0.00   Round = 2   w1 = 0.1204511  w2 = 0.3091565  w3 = 0.002232353    w4 = 0.1553593  w5 = 0.01037559 w6 = 0.2003316  w7 = 0.0793302  w8 = 0.05953728 w9 = 0.8781436  w10 = 0.7184413 Value = -2351189330.3493 
## elapsed = 0.00   Round = 3   w1 = 0.0516069  w2 = 0.4864382  w3 = 0.9860362  w4 = 0.5596409  w5 = 0.4153229  w6 = 0.2821699  w7 = 0.424858   w8 = 0.140359   w9 = 0.1264804  w10 = 0.5893252 Value = -9377298733.1494 
## elapsed = 0.00   Round = 4   w1 = 0.1627919  w2 = 0.4911547  w3 = 0.6829247  w4 = 0.3582216  w5 = 0.1795848  w6 = 0.1353195  w7 = 0.4777378  w8 = 0.6203624  w9 = 0.8325267  w10 = 0.7825712 Value = -13862183214.0860 
## elapsed = 0.00   Round = 5   w1 = 0.2924944  w2 = 0.3108449  w3 = 0.07372197 w4 = 0.5145345  w5 = 0.1693941  w6 = 0.885249   w7 = 0.1130167  w8 = 0.7341157  w9 = 0.8221141  w10 = 0.1641373 Value = -9484076778.5601 
## elapsed = 0.00   Round = 6   w1 = 0.04654339 w2 = 0.1756746  w3 = 0.8676589  w4 = 0.7653593  w5 = 0.235783   w6 = 0.9293707  w7 = 0.005117598    w8 = 0.5512438  w9 = 0.3087414  w10 = 0.6289377 Value = -12351221645.5199 
## elapsed = 0.00   Round = 7   w1 = 0.4140838  w2 = 0.2437006  w3 = 0.9599468  w4 = 0.5132438  w5 = 0.4804521  w6 = 0.3827009  w7 = 0.2728062  w8 = 0.04626104 w9 = 0.4052774  w10 = 0.396292  Value = -9701758685.6108 
## elapsed = 0.00   Round = 8   w1 = 0.4331525  w2 = 0.4496016  w3 = 0.7208769  w4 = 0.6422553  w5 = 0.3821826  w6 = 0.7945976  w7 = 0.2243422  w8 = 0.9881893  w9 = 0.6558969  w10 = 0.8591197 Value = -26524712085.9509 
## elapsed = 0.00   Round = 9   w1 = 0.05999622 w2 = 0.3407801  w3 = 0.5997722  w4 = 0.4208255  w5 = 0.03845926 w6 = 0.5476572  w7 = 0.03492753 w8 = 0.2753723  w9 = 0.08356558 w10 = 0.8498428 Value = -5067895807.8965 
## elapsed = 0.00   Round = 10  w1 = 0.1165734  w2 = 0.08033245 w3 = 0.6492987  w4 = 0.2934759  w5 = 0.2339024  w6 = 0.1455085  w7 = 0.3942132  w8 = 0.4299034  w9 = 0.1360977  w10 = 0.64035   Value = -4492940151.0987 
## elapsed = 0.00   Round = 11  w1 = 0.4912949  w2 = 0.1830575  w3 = 0.4626285  w4 = 0.1177303  w5 = 0.3422389  w6 = 0.5254235  w7 = 0.4546273  w8 = 0.01006644 w9 = 0.3475411  w10 = 0.7914048 Value = -7431148543.6026 
## elapsed = 0.00   Round = 12  w1 = 0.1965482  w2 = 0.06592472 w3 = 0.7139501  w4 = 0.892861   w5 = 0.2125736  w6 = 0.37759    w7 = 0.4457036  w8 = 0.1197284  w9 = 0.4222592  w10 = 0.6565981 Value = -9633182230.5617 
## elapsed = 0.00   Round = 13  w1 = 0.1505191  w2 = 0.03732479 w3 = 0.2014642  w4 = 0.2470552  w5 = 0.264667   w6 = 0.3697815  w7 = 0.1900549  w8 = 0.1177646  w9 = 0.5620651  w10 = 0.951605  Value = -4377724973.3363 
## elapsed = 0.00   Round = 14  w1 = 0.3157334  w2 = 0.3610581  w3 = 0.621876   w4 = 0.07783208 w5 = 0.2021581  w6 = 0.964011   w7 = 0.2376033  w8 = 0.185089   w9 = 0.889262   w10 = 0.04787636    Value = -8424501834.9537 
## elapsed = 0.00   Round = 15  w1 = 0.08808544 w2 = 0.2461224  w3 = 0.5012273  w4 = 0.02612822 w5 = 0.1309003  w6 = 0.09747287 w7 = 0.2338389  w8 = 0.1404766  w9 = 0.6059731  w10 = 0.9389886 Value = -4036940142.9839 
## elapsed = 0.00   Round = 16  w1 = 0.413705   w2 = 0.04976043 w3 = 0.4914928  w4 = 0.2887795  w5 = 0.08058905 w6 = 0.2680898  w7 = 0.06733307 w8 = 0.3849319  w9 = 0.1917522  w10 = 0.8272932 Value = -4258969178.5048 
## elapsed = 0.00   Round = 17  w1 = 0.3312638  w2 = 0.4608563  w3 = 0.5167407  w4 = 0.8971432  w5 = 0.2424163  w6 = 0.7004453  w7 = 0.02640971 w8 = 0.2664996  w9 = 0.7812782  w10 = 0.1021141 Value = -11056736418.3749 
## elapsed = 0.00   Round = 18  w1 = 0.18106    w2 = 0.157966   w3 = 0.8234472  w4 = 0.05974056 w5 = 0.3067763  w6 = 0.8400222  w7 = 0.2505397  w8 = 0.5682885  w9 = 0.7567963  w10 = 0.04945041    Value = -8964557769.6340 
## elapsed = 0.00   Round = 19  w1 = 0.4333727  w2 = 0.1638351  w3 = 0.5613287  w4 = 0.007461678    w5 = 0.3816424  w6 = 0.5831163  w7 = 0.1469588  w8 = 0.01129588 w9 = 0.4386172  w10 = 0.4383498 Value = -4691462833.6173 
## elapsed = 0.00   Round = 20  w1 = 0.1813132  w2 = 0.03351547 w3 = 0.1473852  w4 = 0.2175045  w5 = 0.1893821  w6 = 0.5741353  w7 = 0.1201772  w8 = 0.6580939  w9 = 0.4580795  w10 = 0.8342627 Value = -5826666939.5675 
## elapsed = 0.02   Round = 21  w1 = 0.3206193  w2 = 0.5000 w3 = 2.220446e-16   w4 = 2.220446e-16   w5 = 2.220446e-16   w6 = 2.220446e-16   w7 = 2.220446e-16   w8 = 2.220446e-16   w9 = 2.220446e-16   w10 = 2.220446e-16  Value = -32177637.3572 
## elapsed = 0.00   Round = 22  w1 = 2.220446e-16   w2 = 2.220446e-16   w3 = 2.220446e-16   w4 = 2.220446e-16   w5 = 0.5000 w6 = 2.220446e-16   w7 = 2.220446e-16   w8 = 2.220446e-16   w9 = 2.220446e-16   w10 = 2.220446e-16  Value = -250000242.4519 
## elapsed = 0.00   Round = 23  w1 = 2.220446e-16   w2 = 2.220446e-16   w3 = 2.220446e-16   w4 = 2.220446e-16   w5 = 2.220446e-16   w6 = 2.220446e-16   w7 = 2.220446e-16   w8 = 0.6530171  w9 = 2.220446e-16   w10 = 0.1425383 Value = -41797810.3427 
## elapsed = 0.00   Round = 24  w1 = 2.220446e-16   w2 = 2.220446e-16   w3 = 1.0000 w4 = 1.0000 w5 = 2.220446e-16   w6 = 2.220446e-16   w7 = 0.5000 w8 = 2.220446e-16   w9 = 2.220446e-16   w10 = 1.0000    Value = -6.25e+09 
## elapsed = 0.00   Round = 25  w1 = 0.4998943  w2 = 0.5000 w3 = 2.220446e-16   w4 = 2.220446e-16   w5 = 2.220446e-16   w6 = 2.220446e-16   w7 = 2.220446e-16   w8 = 0.0002114512   w9 = 1.0000 w10 = 0.0002114512  Value = -1000634500.3461 
## elapsed = 0.00   Round = 26  w1 = 0.5000 w2 = 0.5000 w3 = 1.0000 w4 = 2.220446e-16   w5 = 2.220446e-16   w6 = 2.220446e-16   w7 = 0.5000 w8 = 2.220446e-16   w9 = 2.220446e-16   w10 = 0.01161607    Value = -2284983171.1011 
## elapsed = 0.00   Round = 27  w1 = 0.2598206  w2 = 0.006403978    w3 = 1.0000 w4 = 0.1690654  w5 = 0.4757668  w6 = 2.220446e-16   w7 = 0.4210082  w8 = 0.09002675 w9 = 1.0000 w10 = 0.6111853 Value = -9200769803.5739 
## elapsed = 0.00   Round = 28  w1 = 2.220446e-16   w2 = 2.220446e-16   w3 = 2.220446e-16   w4 = 2.220446e-16   w5 = 2.220446e-16   w6 = 0.5000 w7 = 2.220446e-16   w8 = 2.220446e-16   w9 = 2.220446e-16   w10 = 2.220446e-16  Value = -250000458.0758 
## elapsed = 0.00   Round = 29  w1 = 0.4999998  w2 = 0.5000 w3 = 2.220446e-16   w4 = 0.01411956 w5 = 0.4929404  w6 = 4.71866e-08    w7 = 0.461341   w8 = 0.9999995  w9 = 2.220446e-16   w10 = 1.0000    Value = -8811400648.5044 
## elapsed = 0.00   Round = 30  w1 = 0.1638408  w2 = 0.5000 w3 = 2.220446e-16   w4 = 2.220446e-16   w5 = 5.703455e-10   w6 = 5.245444e-10   w7 = 2.220446e-16   w8 = 0.01920682 w9 = 0.987083   w10 = 1.0000    Value = -2789336320.9519 
## 
##  Best Parameters Found: 
## Round = 21   w1 = 0.3206193  w2 = 0.5000 w3 = 2.220446e-16   w4 = 2.220446e-16   w5 = 2.220446e-16   w6 = 2.220446e-16   w7 = 2.220446e-16   w8 = 2.220446e-16   w9 = 2.220446e-16   w10 = 2.220446e-16  Value = -32177637.3572
markowitz_portfolio <- function(...) {
  
  top_mat <- cbind(2*cov_mat, rep(1, N))
  
  bot_vec <- c(rep(1, N), 0)
  
  Am_mat <- rbind(top_mat, bot_vec)
  
  b_vec <- c(rep(0, N), 1)
  
  zm_mat <- solve(Am_mat) %*% b_vec
  
  X_min_var_markowitz <- zm_mat[1:N, 1]
  
  return(X_min_var_markowitz)
}

markowitz_portfolio()
##         CII         DIG         HPG         HT1         HSG         GAS 
##  0.24920592  0.04889129  0.12661811  0.13792272 -0.06046167  0.07255599 
##         GVR         TPB         TCB         MSN 
##  0.01241077  0.16556898  0.04531483  0.20197308