knitr::opts_chunk$set(echo = TRUE, warning = FALSE, message = FALSE)
library(quantmod)
## 载入需要的程序包:xts
## 载入需要的程序包:zoo
##
## 载入程序包:'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
## 载入需要的程序包:TTR
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
library(GGally)
## 载入需要的程序包:ggplot2
library(dplyr)
##
## ######################### Warning from 'xts' package ##########################
## # #
## # The dplyr lag() function breaks how base R's lag() function is supposed to #
## # work, which breaks lag(my_xts). Calls to lag(my_xts) that you type or #
## # source() into this session won't work correctly. #
## # #
## # Use stats::lag() to make sure you're not using dplyr::lag(), or you can add #
## # conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop #
## # dplyr from breaking base R's lag() function. #
## # #
## # Code in packages is not affected. It's protected by R's namespace mechanism #
## # Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning. #
## # #
## ###############################################################################
##
## 载入程序包:'dplyr'
## The following objects are masked from 'package:xts':
##
## first, last
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
Question 1
- Summary Statistics
# Define stock codes and names
symbols <- c("0700.HK", "9988.HK", "0005.HK", "0011.HK", "0941.HK", "0003.HK")
stock_names <- c("Tencent", "Alibaba", "HSBC", "Hang Seng Bank", "China Mobile", "Towngas")
# Date range
start_date <- "2025-08-01"
end_date <- "2025-08-29"
# Fetch adjusted prices
prices_list <- lapply(symbols, function(sym) {
data <- getSymbols(sym, from = start_date, to = end_date, auto.assign = FALSE)
Ad(data)
})
names(prices_list) <- stock_names
# Combine into xts
prices_xts <- do.call(cbind, prices_list)
colnames(prices_xts) <- stock_names
# Compute log returns
returns_xts <- diff(log(prices_xts))
# Price stats
price_stats <- data.frame(
Stock = stock_names,
Mean_Adj_Price = round(apply(prices_xts, 2, mean, na.rm = TRUE), 2),
SD_Adj_Price = round(apply(prices_xts, 2, sd, na.rm = TRUE), 2)
)
# Return stats
return_stats <- data.frame(
Stock = stock_names,
Mean_Daily_Return = round(apply(returns_xts, 2, mean, na.rm = TRUE), 4),
SD_Daily_Return = round(apply(returns_xts, 2, sd, na.rm = TRUE), 4)
)
# Merge
results <- left_join(price_stats, return_stats, by = "Stock")
results
(b) Boxplots
par(mfrow = c(1, 2), mar = c(6, 4, 4, 2) + 0.1)
# Adjusted prices
boxplot(prices_xts,
main = "Adjusted Share Prices (HKD)",
ylab = "Price (HKD)",
col = rainbow(6),
notch = TRUE,
las = 2, cex.axis = 0.8)
# Daily returns
boxplot(returns_xts,
main = "Daily Log Returns",
ylab = "Log Return",
col = rainbow(6),
notch = TRUE,
las = 2, cex.axis = 0.8)

par(mfrow = c(1, 1))
(c) Scatter Plots and Correlations
# Scatter plot matrix for prices
ggpairs(as.data.frame(prices_xts),
title = "Adjusted Share Prices (HKD)",
upper = list(continuous = wrap("cor", size = 4)),
lower = list(continuous = "points"),
diag = list(continuous = "densityDiag"))

# Scatter plot matrix for returns
ggpairs(as.data.frame(returns_xts),
title = "Daily Log Returns",
upper = list(continuous = wrap("cor", size = 4)),
lower = list(continuous = "points"),
diag = list(continuous = "densityDiag"))

# Correlation matrices
cor_prices <- cor(prices_xts, use = "complete.obs")
cor_returns <- cor(returns_xts, use = "complete.obs")
cat("Correlation Matrix for Adjusted Share Prices:\n")
## Correlation Matrix for Adjusted Share Prices:
print(round(cor_prices, 3))
## Tencent Alibaba HSBC Hang Seng Bank China Mobile Towngas
## Tencent 1.000 0.555 0.851 -0.117 0.870 0.138
## Alibaba 0.555 1.000 0.515 0.267 0.492 0.458
## HSBC 0.851 0.515 1.000 0.322 0.918 0.450
## Hang Seng Bank -0.117 0.267 0.322 1.000 0.096 0.815
## China Mobile 0.870 0.492 0.918 0.096 1.000 0.250
## Towngas 0.138 0.458 0.450 0.815 0.250 1.000
cat("\nCorrelation Matrix for Daily Returns:\n")
##
## Correlation Matrix for Daily Returns:
print(round(cor_returns, 3))
## Tencent Alibaba HSBC Hang Seng Bank China Mobile Towngas
## Tencent 1.000 0.626 0.407 0.044 0.044 0.242
## Alibaba 0.626 1.000 0.349 0.297 0.153 0.524
## HSBC 0.407 0.349 1.000 0.652 0.257 0.497
## Hang Seng Bank 0.044 0.297 0.652 1.000 0.350 0.644
## China Mobile 0.044 0.153 0.257 0.350 1.000 0.177
## Towngas 0.242 0.524 0.497 0.644 0.177 1.000
(d) Investment Recommendation
# Allocation weights
allocation <- c(Tencent = 0.15,
`China Mobile` = 0.50,
`Hang Seng Bank` = 0.30,
Alibaba = 0.05)
# Select returns
selected_returns <- returns_xts[, names(allocation)]
# Portfolio returns
portfolio_returns <- as.numeric(selected_returns %*% allocation)
# Portfolio stats
port_mean <- mean(portfolio_returns, na.rm = TRUE)
port_sd <- sd(portfolio_returns, na.rm = TRUE)
# Print recommendation
cat("Investment Recommendation (HK$1 million):\n")
## Investment Recommendation (HK$1 million):
for (i in seq_along(allocation)) {
cat("-", allocation[i] * 100, "% in", names(allocation)[i], "\n")
}
## - 15 % in Tencent
## - 50 % in China Mobile
## - 30 % in Hang Seng Bank
## - 5 % in Alibaba
cat("\nJustification:\n")
##
## Justification:
cat("1. Performance (part a): Tencent has the highest mean return; China Mobile is stable; Hang Seng Bank has relatively low volatility; Alibaba adds optional upside.\n")
## 1. Performance (part a): Tencent has the highest mean return; China Mobile is stable; Hang Seng Bank has relatively low volatility; Alibaba adds optional upside.
cat("2. Distribution (part b): Boxplots confirm Tencent’s wider spread (growth potential), China Mobile’s compact spread (stability), and Hang Seng Bank’s moderate risk.\n")
## 2. Distribution (part b): Boxplots confirm Tencent’s wider spread (growth potential), China Mobile’s compact spread (stability), and Hang Seng Bank’s moderate risk.
cat("3. Association (part c): Correlations show Tencent, China Mobile, and Hang Seng Bank are not highly correlated, improving diversification.\n")
## 3. Association (part c): Correlations show Tencent, China Mobile, and Hang Seng Bank are not highly correlated, improving diversification.
cat("4. Portfolio Balance: The 15-50-30-5 allocation balances growth, stability, and diversification.\n\n")
## 4. Portfolio Balance: The 15-50-30-5 allocation balances growth, stability, and diversification.
cat("Expected Portfolio Mean Daily Return:", round(port_mean, 4), "\n")
## Expected Portfolio Mean Daily Return: 0.002
cat("Expected Portfolio Daily Risk (SD):", round(port_sd, 4), "\n")
## Expected Portfolio Daily Risk (SD): 0.0057