Trong kỷ nguyên tài chính Định lượng, các quyết định đầu tư ngày càng được dẫn dắt bởi sự phân tích chặt chẽ các chỉ số hiệu suất, định giá và yếu tố rủi ro. Nghiên cứu này tập trung vào việc áp dụng ngôn ngữ lập trình R để thực hiện phân tích chuyên sâu về mối liên hệ giữa các Chỉ số Tài chính, Định giá, và Yếu tố Môi trường, Xã hội và Quản trị (ESG) với hiệu suất đầu tư thực tế.
Bộ dữ liệu nền tảng là “400K NYSE Random Investments + Financial Ratios” (thu thập từ Kaggle), mô phỏng hơn 400.000 giao dịch đầu tư ngẫu nhiên vào các cổ phiếu niêm yết trên Sàn giao dịch Chứng khoán New York (NYSE) trong giai đoạn 2013-2018. Khác với các phân tích tập trung vào Hành vi Giao dịch, nghiên cứu này khai thác Nhóm Biến 2 (Chỉ số Công ty, Định giá, ESG), bao gồm các chỉ số trọng yếu như Tỷ số Giá/Thu nhập (PE), Tỷ suất Sinh lời trên Vốn Chủ Sở Hữu (ROE), Đòn bẩy Tài chính (Leverage_Ratio), và Xếp hạng ESG.
Nghiên cứu này được thực hiện với các mục tiêu định lượng và khám phá cụ thể như sau:
Lượng hóa Đặc trưng Phân bố: Thực hiện các tiêu
chí như thống kê mô tả, tương quan, và kiểm định giả thuyết) để lượng
hóa độ tập trung, độ phân tán và hình dạng phân bố của các chỉ số tài
chính và lợi suất thực tế (Real_Return).
Trực quan hóa Khám phá: Xây dựng tối thiểu các
biểu đồ (Violin Plot, Heatmap, Box Plot so sánh nhóm,..) để trực quan
hóa mối quan hệ giữa các chỉ số (Log_PE, ROE,
ESG) và hiệu suất đầu tư.
Kiểm định Giả thuyết: Kiểm tra sự khác biệt có ý
nghĩa thống kê về hiệu suất đầu tư (Real_Return) và đặc
điểm tài chính (ví dụ: Log_PE) giữa các nhóm ngành
(sector) và nhóm kết quả đầu tư (investment
GOOD/BAD) thông qua các kiểm định như \(t\)-test và ANOVA.
Kiểm soát Độ tin cậy: Thực hiện bắt buộc bước
nhận diện và xử lý Outlier trong các biến số quan trọng (như
Real_Return, PE_ratio) để đảm bảo các kết quả
thống kê và kiểm định là đáng tin cậy.
Xây dựng Storytelling Định lượng: Kết nối các phát hiện thống kê và kiểm định thành một câu chuyện logic về tài chính, giải thích mức độ ảnh hưởng của sức khỏe doanh nghiệp, định giá và yếu tố phi tài chính lên sự thành công của một khoản đầu tư ngẫu nhiên trên sàn NYSE.
Nghiên cứu sẽ tuân theo cấu trúc khoa học chặt chẽ, được thực hiện
hoàn toàn trong môi trường R để đảm bảo tính minh bạch và khả năng tái
lập của các kết quả định lượng. Phạm vi phân tích sẽ giới hạn trong các
biến thuộc Nhóm 2, bao gồm: Real_Return (Biến phụ thuộc),
Log_PE, PB, PS, ROE,
ROA, EPS, NetProfitMargin,
Current_Ratio, Leverage_Ratio,
ESG, và các biến phân loại liên quan (sector,
investment).
Lý thuyết 1: Lý thuyết cấu trúc vốn (Trade-Off Theory of Capital Structure)
Lý thuyết cấu trúc vốn được hình thành từ các nghiên cứu kinh điển của Modigliani & Miller (1958, 1963) và được phát triển thành thuyết đánh đổi (Trade-Off Theory). Theo lý thuyết này, doanh nghiệp sẽ lựa chọn một tỷ lệ nợ tối ưu (optimal leverage) nhằm cân bằng giữa lợi ích và chi phí của việc sử dụng nợ vay. Cụ thể, việc sử dụng nợ giúp doanh nghiệp tận dụng lá chắn thuế từ chi phí lãi vay (tax shield), qua đó làm gia tăng lợi nhuận cho cổ đông. Tuy nhiên, khi mức đòn bẩy tài chính quá cao, chi phí rủi ro tài chính và chi phí phá sản (financial distress costs) cũng tăng lên, khiến giá trị doanh nghiệp giảm.
Do đó, doanh nghiệp cần đạt đến điểm đánh đổi tối ưu
giữa lợi ích thuế và rủi ro phá sản để tối đa hóa giá trị. Trong thực
tiễn, các yếu tố như đặc điểm ngành, quy mô, dòng tiền và mức độ ổn định
của lợi nhuận đều ảnh hưởng đến cấu trúc vốn hợp lý. Theo lý thuyết này,
tỷ lệ đòn bẩy (Leverage Ratio) có mối quan hệ phi tuyến
với hiệu quả tài chính (ROE): ở mức thấp, tăng đòn bẩy
giúp cải thiện ROE; nhưng ở mức cao, đòn bẩy quá mức lại làm gia tăng
rủi ro và suy giảm hiệu suất đầu tư (Myers, 1984; Kraus &
Litzenberger, 1973). Trong nghiên cứu này, biến
Leverage_Ratio được sử dụng để kiểm định mối quan hệ giữa
cấu trúc vốn và hiệu quả tài chính của doanh nghiệp trên thị trường
NYSE.
Lý thuyết 2: Lý thuyết ESG và hiệu suất doanh nghiệp (ESG Performance and Stakeholder Theory)
Lý thuyết ESG bắt nguồn từ các nền tảng của Thuyết các bên liên quan (Stakeholder Theory – Freeman, 1984) và Thuyết hợp pháp hóa (Legitimacy Theory), cho rằng doanh nghiệp không chỉ chịu trách nhiệm với cổ đông mà còn với toàn bộ các bên liên quan – bao gồm nhân viên, khách hàng, cộng đồng và môi trường. Thực hiện tốt các tiêu chí về Môi trường (E), Xã hội (S), và Quản trị (G) giúp doanh nghiệp giảm thiểu rủi ro pháp lý, nâng cao uy tín, tăng cường niềm tin của nhà đầu tư, đồng thời cải thiện hiệu quả tài chính dài hạn (Eccles, Ioannou & Serafeim, 2014; Fatemi et al., 2018).
Theo hướng tiếp cận này, điểm số ESG (ESG Score)
phản ánh chất lượng quản trị và cam kết phát triển bền vững của doanh
nghiệp, từ đó ảnh hưởng tích cực đến tỷ suất sinh lời (ROE,
ROA) và hiệu suất đầu tư thực tế
(Real_Return). Các nghiên cứu gần đây (ví dụ: Bhaskaran et
al., 2020; Broadstock et al., 2021) cũng chỉ ra rằng doanh nghiệp
có điểm ESG cao thường có chi phí vốn thấp hơn, dễ thu
hút dòng vốn đầu tư bền vững và đạt mức lợi nhuận điều chỉnh rủi
ro cao hơn so với nhóm còn lại. Trong nghiên cứu này, biến
ESG được dùng để kiểm định vai trò của hiệu suất bền vững
trong việc giải thích sự khác biệt về lợi suất đầu tư giữa các công ty
niêm yết.
Trước khi đi vào phân tích chuyên sâu Nhóm Biến 2, cần tái khẳng định
quá trình làm sạch, chuẩn hóa và tạo biến phái sinh đã được thực hiện
trên dữ liệu gốc (nyse_raw). Quá trình này bao gồm việc
loại bỏ cột thừa (...1, date_SELL_fix), chuẩn
hóa tên biến, chuyển đổi kiểu dữ liệu (từ character sang
factor cho sector, investment),
và tạo ra các biến mới có ý nghĩa tài chính/thống kê như sau:
Real_Return: Lợi suất thực tế (sau khi
điều chỉnh lạm phát).Log_PE: Logarit tự nhiên của Tỷ số P/E
(nhằm chuẩn hóa phân bố lệch phải nặng).Leverage_Ratio: Tỷ số Đòn bẩy Tài
chính (ví dụ: Tổng Tài sản/Vốn CSH).Sử dụng lại các bước tiền xử lý đã hoàn thành (giả định đã được chạy
và lưu vào file .RData).
# KHỐI NÀY GIẢ ĐỊNH QUÁ TRÌNH TIỀN XỬ LÝ ĐÃ HOÀN TẤT
# VÍ DỤ:
# nyse_processed <- nyse_raw %>%
# select(-c("...1", "date_SELL_fix")) %>%
# rename(Horizon_Days = `horizon (days)`, Nominal_Return = nominal_return,
# Expected_Return_Yr = `expected_return (yearly)`, ESG = ESG_ranking,
# PE = PE_ratio, EPS = EPS_ratio, PS = PS_ratio, PB = PB_ratio,
# NetProfitMargin = NetProfitMargin_ratio, Current_Ratio = current_ratio,
# ROA = roa_ratio, ROE = roe_ratio) %>%
# mutate(
# sector = as.factor(sector),
# investment = as.factor(investment),
# Date_Buy = as.Date(date_BUY_fix),
# # Feature Engineering
# Real_Return = Nominal_Return - inflation,
# Log_PE = log(PE),
# Leverage_Ratio = 1 / (1 - (PB / (ROE/100))), # Ví dụ công thức đòn bẩy
# )
# # TẠO BỘ DỮ LIỆU NHÓM 2 CỐT LÕI
# nyse_group2_data <- nyse_processed %>%
# select(company, sector, Date_Buy, Buy_Year, Buy_Quarter, investment, Real_Return,
# Log_PE, PB, PS, ROE, ROA, EPS, NetProfitMargin, Current_Ratio, Leverage_Ratio, ESG)
# # Lưu bộ dữ liệu (giả định đã lưu)
# # save(nyse_group2_data, file = "nyse_group2_data.RData") if (!exists("nyse_group2_data")) {
nyse_group2_data <- nyse_raw %>%
select(-c("...1", "date_SELL_fix")) %>%
rename(Horizon_Days = `horizon (days)`, Nominal_Return = nominal_return,
Expected_Return_Yr = `expected_return (yearly)`, ESG = ESG_ranking,
PE = PE_ratio, EPS = EPS_ratio, PS = PS_ratio, PB = PB_ratio,
NetProfitMargin = NetProfitMargin_ratio, Current_Ratio = current_ratio,
ROA = roa_ratio, ROE = roe_ratio,
Date_Buy = date_BUY_fix, investment = investment) %>%
mutate(
sector = as.factor(sector),
investment = as.factor(investment),
Buy_Year = factor(year(Date_Buy)),
Buy_Quarter = factor(quarter(Date_Buy, with_year = TRUE)),
# Feature Engineering
Real_Return = Nominal_Return - inflation,
# Xử lý NA/Inf trước khi Log (giả định PE < 0 hoặc PE NA đã được xử lý ban đầu, ta chỉ lấy log cho PE > 0)
Log_PE = ifelse(PE > 0, log(PE), NA),
# Công thức đơn giản cho Đòn bẩy (ví dụ: Assets/Equity = 1 + Debt/Equity)
Leverage_Ratio = ifelse(ROE != 0 & PB != 0, abs(PB / (ROE/100)), NA)
) %>%
select(company, sector, Date_Buy, Buy_Year, Buy_Quarter, investment, Real_Return,
Log_PE, PB, PS, ROE, ROA, EPS, NetProfitMargin, Current_Ratio, Leverage_Ratio, ESG)
}
# 1. Kiểm tra kích thước (dim)
cat("Kích thước bộ dữ liệu Nhóm 2 (Dòng x Cột):\n")Kích thước bộ dữ liệu Nhóm 2 (Dòng x Cột):
[1] 405258 17
Kiểu dữ liệu của các biến chính:
tibble [405,258 × 6] (S3: tbl_df/tbl/data.frame)
$ Real_Return: num [1:405258] -1.997 0.524 0.194 0.142 0.503 ...
$ Log_PE : num [1:405258] 2.53 2.43 2.36 2.41 2.24 ...
$ ROE : num [1:405258] 26.69 5.54 25.78 11.35 8.91 ...
$ ESG : num [1:405258] 12 26.3 19.8 12.9 27.9 17.6 31.6 24.8 26.3 27.9 ...
$ sector : Factor w/ 5 levels "AUTO","BANK",..: 4 2 2 4 2 3 5 2 2 2 ...
$ investment : Factor w/ 2 levels "BAD","GOOD": 1 2 1 1 2 2 2 2 1 2 ...
Nhận xét: Bộ dữ liệu Nhóm 2 có 405258 quan sát và 17
biến. Các biến số cốt lõi (Real_Return,
Log_PE, ROE, ESG) đều có kiểu
numeric, trong khi các biến phân loại (sector,
investment) đã được chuẩn hóa sang kiểu
factor, tạo điều kiện thuận lợi cho các kiểm định và trực
quan hóa so sánh nhóm.
Sử dụng hàm summary() hoặc skimr::skim() để
có cái nhìn nhanh về phân bố của các biến số, đặc biệt là các biến tạo
sinh.
Tóm tắt phân bố sơ bộ (Summary):
Real_Return Log_PE ROE ESG Leverage_Ratio
Min. :-2.61 Min. :1 Min. :-99.5 Min. :12.0 Min. : 2
1st Qu.:-1.69 1st Qu.:2 1st Qu.: 8.8 1st Qu.:16.3 1st Qu.: 11
Median : 0.14 Median :3 Median : 16.1 Median :25.1 Median : 16
Mean :-0.51 Mean :3 Mean : 15.6 Mean :22.6 Mean : 46
3rd Qu.: 0.35 3rd Qu.:3 3rd Qu.: 26.0 3rd Qu.:27.9 3rd Qu.: 27
Max. : 9.05 Max. :7 Max. : 57.2 Max. :31.6 Max. :2800
NA's :39751 NA's :9158
Kiểm tra số lượng giá trị khuyết thiếu (NA):
nyse_group2_data %>%
summarise_all(list(n_NA = ~sum(is.na(.)))) %>%
pivot_longer(cols = everything(), names_to = "Variable", values_to = "NA_Count") %>%
filter(NA_Count > 0) %>%
arrange(desc(NA_Count)) %>%
kable(caption = "Bảng 1.2.1: Số lượng NA trong các biến tạo sinh")| Variable | NA_Count |
|---|---|
| Log_PE_n_NA | 39751 |
| Leverage_Ratio_n_NA | 9158 |
Nhận xét
1. Phân bố sơ bộ
Real_Return có giá trị Trung vị (Median) dương (≈ 0.14), cho thấy lợi suất thực tế có xu hướng nghiêng về phía tích cực. Tuy nhiên, giá trị Trung bình (Mean = -0.51) thấp hơn Median, thể hiện phân phối lệch trái – có thể tồn tại một số quan sát âm lớn kéo trung bình xuống thấp. Phạm vi biến thiên rất rộng (Min = -2.61, Max = 9.05) là dấu hiệu rõ ràng của outlier, cần xử lý ở bước tiền xử lý.
Log_PE có phân phối rất hẹp và lệch phải nhẹ (Mean ≈ 3, Median ≈ 3, Max = 0.7), nhưng có 39.751 giá trị khuyết thiếu (NA) – cần được xem xét và xử lý trước khi đưa vào phân tích mô hình.
ROE dao động rất lớn (Min = -99.5, Max = 57.2), phản ánh mức độ biến động cao trong khả năng sinh lời giữa các doanh nghiệp. Tuy nhiên, Mean (15.6) và Median (16.1) khá gần nhau → phân phối tương đối cân đối, nhưng vẫn cần kiểm tra các giá trị cực trị âm.
ESG có giá trị Mean = 22.6 và Median = 25.1, cho thấy phân phối hơi lệch trái, với phạm vi giá trị hẹp (12.0 – 31.6). Điều này phản ánh sự ổn định tương đối trong điểm ESG giữa các công ty.
Leverage_Ratio có Mean (46) lớn hơn rất nhiều so với Median (16), biểu hiện phân phối lệch phải mạnh (skewed right). Một số công ty có đòn bẩy tài chính cực cao (tới 2800), kéo trung bình lên rất lớn. Đồng thời, có 9.158 giá trị NA cần xử lý.
2. Giá trị khuyết thiếu (NA)
Log_PE có số lượng NA rất lớn (39.751),giá trị NA, xuất phát từ các trường hợp Tỷ số P/E không xác định hoặc không hợp lệ (PE \(\le\) 0), ảnh hưởng đáng kể đến độ tin cậy của các mô hình hồi quy hoặc phân tích tương quan.
Leverage_Ratio cũng có nhiều NA,do các trường hợp ROE \(\approx\) 0 hoặc PB \(\approx\) 0, hoặc mẫu số trong công thức đòn bẩy bằng 0.
3. Tổng kết xu hướng
Các biến tài chính cho thấy phân phối không chuẩn
(non-normal) với sự hiện diện rõ của outlier và giá trị
khuyết thiếu.
ROE và ESG có phân bố khá ổn định, trong khi Leverage_Ratio và Real_Return biến động mạnh, cần được chuẩn hóa hoặc winsorize_ xử lý ngoại lai trước khi đưa vào mô hình.
Nhìn chung, bộ dữ liệu phản ánh sự khác biệt đáng kể về cấu trúc tài chính và hiệu suất giữa các công ty, là cơ sở quan trọng cho các phân tích tiếp theo.
Để đảm bảo tính nhất quán cho các phân tích và kiểm định tiếp theo thì các quan sát có NA trong các biến tạo sinh cốt lõi cần được loại bỏ.
nyse_group2_clean <- nyse_group2_data %>%
drop_na(Real_Return, Log_PE, Leverage_Ratio)
# Tính toán tỷ lệ dữ liệu bị loại bỏ
na_removed_count <- nrow(nyse_group2_data) - nrow(nyse_group2_clean)
na_removed_ratio <- (na_removed_count / nrow(nyse_group2_data)) * 100
cat("Số quan sát bị loại bỏ do NA trong biến tạo sinh:", na_removed_count, "\n")Số quan sát bị loại bỏ do NA trong biến tạo sinh: 48909
Tỷ lệ dữ liệu bị loại bỏ: 12.07%
# Kiểm tra lại kích thước bộ dữ liệu cuối cùng
cat("\nKích thước bộ dữ liệu đã làm sạch cuối cùng (nyse_group2_clean) sau khi loại bỏ NA:\n")
Kích thước bộ dữ liệu đã làm sạch cuối cùng (nyse_group2_clean) sau khi loại bỏ NA:
[1] 356349 17
Nhận xét: Sau khi loại bỏ các quan sát có giá trị NA
trong các biến Real_Return, Log_PE, và
Leverage_Ratio, 48909 quan sát đã bị loại,
tương đương với 12.07% tổng số dữ liệu. Bộ dữ liệu cuối
cùng, nyse_group2_clean, có
356349 quan sát, sẵn sàng cho bước xử lý Outlier ở Mục
1.3.
Các giá trị ngoại lai (Outlier) có thể làm sai lệch nghiêm trọng các
thống kê mô tả (đặc biệt là Trung bình và Độ lệch chuẩn) và ảnh hưởng
đến kết quả của các kiểm định giả thuyết. Mục tiêu của phần này là nhận
diện và kiểm soát các giá trị cực đoan trong các biến định lượng cốt
lõi, đặc biệt là Real_Return, PE (trước khi
Log), và ROE.
Sử dụng phương pháp Interquartile Range (IQR) để xác định Outlier (các giá trị nằm ngoài khoảng \([Q_1 - 1.5 \times IQR, Q_3 + 1.5 \times IQR]\)).
# Hàm tính số lượng outlier
get_outlier_count <- function(data, var_name) {
x <- data[[var_name]]
Q1 <- quantile(x, 0.25, na.rm = TRUE)
Q3 <- quantile(x, 0.75, na.rm = TRUE)
IQR_val <- Q3 - Q1
lower_bound <- Q1 - 1.5 * IQR_val
upper_bound <- Q3 + 1.5 * IQR_val
outliers <- sum(x < lower_bound | x > upper_bound, na.rm = TRUE)
return(outliers)
}
# Áp dụng cho 3 biến chính (sử dụng biến gốc PE trước khi log)
vars_to_check <- c("Real_Return", "PE", "ROE")
outlier_counts <- data.frame(
Variable = vars_to_check,
Outlier_Count = sapply(vars_to_check, function(v) get_outlier_count(nyse_raw, v)), # Sử dụng nyse_raw để có PE gốc
Total_Count = nrow(nyse_raw)
)
outlier_counts <- outlier_counts %>%
mutate(Outlier_Ratio = (Outlier_Count / Total_Count) * 100)
# Chuyển PE_ratio về dạng nyse_group2_clean để thống kê
outlier_counts_clean <- data.frame(
Variable = c("Real_Return", "ROE"),
Outlier_Count = sapply(c("Real_Return", "ROE"), function(v) get_outlier_count(nyse_group2_clean, v)),
Total_Count = nrow(nyse_group2_clean)
) %>%
mutate(Outlier_Ratio = (Outlier_Count / Total_Count) * 100)
cat("Kết quả định lượng Outlier (sử dụng 1.5*IQR):\n")Kết quả định lượng Outlier (sử dụng 1.5*IQR):
knitr::kable(outlier_counts_clean, caption = "Bảng 1.3.1: Định lượng Outlier trong Dữ liệu đã làm sạch NA")| Variable | Outlier_Count | Total_Count | Outlier_Ratio | |
|---|---|---|---|---|
| Real_Return | Real_Return | 616 | 356349 | 0.173 |
| ROE | ROE | 7678 | 356349 | 2.155 |
Nhận xét:
Real_Return: Mặc dù đã loại bỏ NA, biến
này vẫn có tỷ lệ Outlier cao là 0.17%. Điều này phản
ánh sự biến động cực đoan của lợi suất trong thị trường chứng khoán.
ROE: Biến này cũng có tỷ lệ Outlier
đáng kể là 2.15%, chủ yếu là các trường hợp sinh lời
quá cao hoặc thua lỗ nghiêm trọng (ROE âm rất lớn).
# Trực quan hóa Outlier bằng Box Plot cho các biến trước khi Winsorizing
outlier_viz_data <- nyse_group2_clean %>%
select(Real_Return, ROE, Log_PE) %>%
pivot_longer(cols = everything(), names_to = "Variable", values_to = "Value")
ggplot(outlier_viz_data, aes(x = Variable, y = Value)) +
geom_boxplot(fill = "#1E90FF", color = "#1E90FF", alpha = 0.7, outlier.colour = "red", outlier.shape = 1) +
facet_wrap(~Variable, scales = "free_y") +
labs(
title = "Hình 1.3.1: Nhận diện Outlier trong các biến Cốt lõi (Trước xử lý)",
y = "Giá trị"
) +
theme_minimal() +
theme(plot.title = element_text(face = "bold", size = 12), axis.title.x = element_blank())Nhận xét Hình 1.3.1: Nhận diện Outlier trong các biến cốt lõi (Trước xử lý)
Biểu đồ Box Plot thể hiện đặc điểm phân phối và sự xuất hiện của các
giá trị ngoại lệ (outliers) trong ba biến tài chính chính:
Log_PE, Real_Return và ROE.
Biến Log_PE:
Phân bố của Log_PE lệch phải, với phần hộp (IQR) tập trung
quanh giá trị 2–3, thể hiện phần lớn các cổ phiếu có mức định giá hợp
lý. Tuy nhiên, có nhiều điểm ngoại lệ (các chấm đỏ) nằm phía trên 6,
phản ánh một số cổ phiếu có tỷ lệ định giá P/E rất cao so với phần lớn
thị trường. Điều này cho thấy sự tồn tại của các trường hợp bị định giá
cao bất thường, cần được kiểm tra thêm trong quá trình phân
tích.
Biến Real_Return:
Biểu đồ cho thấy sự phân tán rất lớn với nhiều outlier xuất hiện ở phía
trên (từ giá trị 3 đến trên 9). Phần hộp của Real_Return
hẹp và lệch nhẹ về phía âm, thể hiện rằng phần lớn lợi suất thực tế tập
trung quanh mức thấp, trong khi một số ít quan sát có lợi suất cao vượt
trội. Phân phối này bị lệch phải mạnh, chỉ ra sự hiện diện của các giá
trị cực đại ảnh hưởng đến trung bình mẫu. Việc xử lý hoặc hiệu chỉnh
biến này là cần thiết để đảm bảo tính chính xác của các kiểm định thống
kê.
Biến ROE:
Phân phối của ROE cho thấy nhiều outlier ở phía trên, vượt
ngưỡng 50–60. Phần hộp tập trung trong khoảng 10–30, phản ánh mức sinh
lời trung bình của phần lớn doanh nghiệp. Tuy nhiên, sự tồn tại của
nhiều giá trị cực đại làm kéo trung bình tăng đáng kể và có thể gây sai
lệch khi thực hiện hồi quy hoặc phân tích tương quan.
Tổng thể:
Cả ba biến đều thể hiện phân phối lệch phải và
chứa nhiều giá trị ngoại lệ, đặc biệt là
Real_Return và ROE. Điều này cho thấy cần thực
hiện các bước xử lý outlier winsorizing nhằm giảm ảnh
hưởng của các giá trị cực đoan và đảm bảo kết quả phân tích định lượng
có độ tin cậy cao.
Do tỷ lệ Outlier cao và tính chất lệch của dữ liệu tài chính, áp dụng kỹ thuật Winsorizing (hay còn gọi là Capping) ở ngưỡng 1% và 99%. Kỹ thuật này giữ nguyên thứ tự các quan sát nhưng giới hạn các giá trị cực đoan về ngưỡng cận trên và cận dưới, hiệu quả hơn việc loại bỏ hoàn toàn (Trimming).
# Hàm Winsorizing
winsorize <- function(x, lower = 0.01, upper = 0.99) {
quantiles <- quantile(x, c(lower, upper), na.rm = TRUE)
x[x < quantiles[1]] <- quantiles[1]
x[x > quantiles[2]] <- quantiles[2]
return(x)
}
# Áp dụng Winsorizing cho Real_Return và ROE
nyse_final_data <- nyse_group2_clean %>%
mutate(
Real_Return_Winsorized = winsorize(Real_Return, 0.01, 0.99),
ROE_Winsorized = winsorize(ROE, 0.01, 0.99),
Log_PE_Winsorized = winsorize(Log_PE, 0.01, 0.99) # Winsorize cả Log_PE để đảm bảo mô hình ổn định
)
cat("Đã tạo bộ dữ liệu cuối cùng 'nyse_final_data' với các biến Winsorized.\n")Đã tạo bộ dữ liệu cuối cùng 'nyse_final_data' với các biến Winsorized.
# So sánh Thống kê mô tả (Mean, SD, Skewness) trước và sau Winsorizing
comparison_stats <- nyse_final_data %>%
summarise(
Mean_Return_Raw = mean(Real_Return, na.rm = TRUE),
Mean_Return_Win = mean(Real_Return_Winsorized, na.rm = TRUE),
SD_Return_Raw = sd(Real_Return, na.rm = TRUE),
SD_Return_Win = sd(Real_Return_Winsorized, na.rm = TRUE),
Skew_Return_Raw = moments::skewness(Real_Return, na.rm = TRUE),
Skew_Return_Win = moments::skewness(Real_Return_Winsorized, na.rm = TRUE),
Mean_ROE_Raw = mean(ROE, na.rm = TRUE),
Mean_ROE_Win = mean(ROE_Winsorized, na.rm = TRUE),
Skew_ROE_Raw = moments::skewness(ROE, na.rm = TRUE),
Skew_ROE_Win = moments::skewness(ROE_Winsorized, na.rm = TRUE)
) %>%
tidyr::pivot_longer(cols = everything(), names_to = "Statistic", values_to = "Value") %>%
separate(Statistic, into = c("Statistic_Type", "Variable", "Adjustment"), sep = "_") %>%
mutate(Adjustment = replace_na(Adjustment, "Raw")) %>%
pivot_wider(names_from = Adjustment, values_from = Value)
knitr::kable(comparison_stats, caption = "Bảng 1.3.2: So sánh Thống kê trước và sau Winsorizing")| Statistic_Type | Variable | Raw | Win |
|---|---|---|---|
| Mean | Return | -0.492 | -0.502 |
| SD | Return | 1.079 | 1.047 |
| Skew | Return | -0.048 | -0.327 |
| Mean | ROE | 19.773 | 19.772 |
| Skew | ROE | 0.774 | 0.763 |
Nhận xét Bảng 1.3.2: So sánh thống kê trước và sau Winsorizing
Bảng 1.3.2 trình bày sự thay đổi của các chỉ tiêu thống kê mô tả
(Mean, SD, Skew) của hai biến tài
chính chính là Return (lợi suất thực tế) và
ROE (tỷ suất sinh lời trên vốn chủ sở hữu) trước và sau khi
áp dụng phương pháp Winsorizing.
Biến Return:
Giá trị trung bình (Mean) thay đổi không đáng kể, từ -0.492 xuống -0.502, cho thấy việc Winsorizing không làm thay đổi xu hướng lợi suất chung của mẫu dữ liệu. Tuy nhiên, độ lệch chuẩn (SD) giảm nhẹ từ 1.079 xuống 1.047, thể hiện mức độ phân tán dữ liệu giảm sau khi loại bỏ ảnh hưởng của các giá trị cực đoan.
Đặc biệt, hệ số lệch phân phối (Skew) thay đổi từ -0.048 sang -0.327, phản ánh rằng phân phối lợi suất trở nên cân đối hơn và ít bị ảnh hưởng bởi các giá trị lợi suất cao bất thường ở phía trên. Điều này giúp dữ liệu gần hơn với giả định phân phối chuẩn, hỗ trợ cho các kiểm định thống kê và mô hình hồi quy tuyến tính.
Biến ROE:
Giá trị trung bình (Mean) gần như không thay đổi (19.773 → 19.772), cho thấy phương pháp Winsorizing chỉ tác động đến phần đuôi phân phối chứ không ảnh hưởng đến xu hướng trung tâm.
Hệ số lệch phân phối (Skew) giảm nhẹ từ 0.774 xuống 0.763, nghĩa là độ lệch phải của ROE đã giảm, giúp phân phối của biến trở nên ổn định hơn.
# So sánh Box Plot của Real_Return trước và sau Winsorizing
viz_data_final <- nyse_final_data %>%
select(Real_Return, Real_Return_Winsorized) %>%
pivot_longer(cols = everything(), names_to = "Version", values_to = "Value") %>%
mutate(Version = factor(Version, levels = c("Real_Return", "Real_Return_Winsorized"),
labels = c("1. Ban đầu (Raw)", "2. Đã Winsorized (1%-99%)")))
ggplot(viz_data_final, aes(x = Version, y = Value, fill = Version)) +
geom_boxplot(outlier.shape = NA) + # Ẩn outlier để tập trung vào thân phân bố
scale_fill_manual(values = c("1. Ban đầu (Raw)" = "#FF7F50", "2. Đã Winsorized (1%-99%)" = "#1E90FF")) +
labs(
title = "Hình 1.3.2: Box Plot so sánh Lợi suất Thực tế (Real_Return) trước và sau Winsorizing",
y = "Lợi suất Thực tế",
fill = "Phiên bản Dữ liệu"
) +
theme_minimal() +
theme(plot.title = element_text(face = "bold", size = 12), axis.title.x = element_blank(), legend.position = "bottom")Nhận xét Hình 1.3.2: So sánh Lợi suất Thực tế (Real_Return) trước và sau Winsorizing
Biểu đồ cho thấy sự khác biệt rõ rệt giữa dữ liệu trước và sau khi xử lý ngoại lệ, cụ thể:
Ở phiên bản ban đầu (Raw), lợi suất thực tế
(Real_Return) có phạm vi dao động rất rộng và xuất hiện
nhiều giá trị cao bất thường, thể hiện sự phân phối lệch phải và biến
động lớn.
Sau khi Winsorizing (1%–99%), phạm vi giá trị được thu hẹp lại, dữ liệu trở nên ổn định và cân đối hơn, trong khi vị trí trung tâm của phân phối hầu như không thay đổi.
→ Điều này chứng tỏ quá trình Winsorizing đã loại bỏ ảnh hưởng của các giá trị cực đoan mà vẫn giữ nguyên đặc trưng chung của dữ liệu, giúp kết quả phân tích thống kê sau này đáng tin cậy hơn.
Tổng kết Mục 1.3: Quá trình xử lý Outlier đã được
thực hiện thành công. Bộ dữ liệu
nyse_final_data với các biến Winsorized
(Real_Return_Winsorized, ROE_Winsorized,
Log_PE_Winsorized) sẽ được sử dụng cho toàn bộ các phân
tích thống kê và trực quan hóa, đảm bảo các kết quả có tính tin cậy cao
hơn.
vars_desc_fixed <- c("Real_Return_Winsorized", "Log_PE_Winsorized", "ROE_Winsorized", "Leverage_Ratio", "ESG")
# Tạo một hàm thống kê tùy chỉnh để lấy tất cả các chỉ số cần thiết
get_desc_stats <- function(df, vars) {
df_stats <- data.frame(Variable = vars)
for (var in vars) {
x <- df[[var]]
# Đảm bảo tính toán trên dữ liệu không có NA nếu có
x <- x[!is.na(x)]
n_obs <- length(x)
stats_row <- data.frame(
Variable = var,
N = n_obs,
Mean = mean(x),
Median = median(x),
SD = sd(x),
SE = sd(x) / sqrt(n_obs),
Min = min(x),
Q1 = quantile(x, 0.25),
Q3 = quantile(x, 0.75),
Max = max(x)
)
# Ghép kết quả
if (var == vars[1]) {
result_df <- stats_row
} else {
result_df <- rbind(result_df, stats_row)
}
}
return(result_df)
}
# Áp dụng hàm thống kê đã sửa lỗi
desc_table_fixed <- get_desc_stats(nyse_final_data, vars_desc_fixed)
desc_table_fixed %>%
knitr::kable(caption = "Bảng 1.2.1: Thống kê Mô tả các Biến Chính")| Variable | N | Mean | Median | SD | SE | Min | Q1 | Q3 | Max | |
|---|---|---|---|---|---|---|---|---|---|---|
| 25% | Real_Return_Winsorized | 356349 | -0.502 | 0.143 | 1.047 | 0.002 | -2.11 | -1.68 | 0.348 | 1.16 |
| 25%1 | Log_PE_Winsorized | 356349 | 2.896 | 2.717 | 0.833 | 0.001 | 1.47 | 2.40 | 3.224 | 6.40 |
| 25%2 | ROE_Winsorized | 356349 | 19.772 | 18.660 | 11.001 | 0.018 | 1.19 | 11.66 | 26.400 | 55.99 |
| 25%3 | Leverage_Ratio | 356349 | 38.284 | 14.887 | 155.899 | 0.261 | 2.83 | 10.79 | 24.864 | 2800.00 |
| 25%4 | ESG | 356349 | 21.815 | 22.800 | 6.349 | 0.011 | 12.00 | 14.80 | 27.300 | 31.60 |
Nhận xét về Thống kê Mô tả các Biến Chính
1. Lợi suất Thực tế
(Real_Return_Winsorized):
Mean =
-0.502) và Lợi suất trung vị (Median =
0.143). Giá trị Trung bình âm trong khi Trung vị dương
mạnh mẽ (Median > 0) cho thấy phân bố lệch trái
âm nghiêm trọng.SD = \(1.047\)) cao hơn 1, cho thấy lợi suất thực
tế có mức độ biến động lớn bất chấp đã được Winsorizing, phản ánh rủi ro
cao của các khoản đầu tư ngẫu nhiên này.2. Hiệu suất Vốn (ROE_Winsorized):
Mean =
\(19.772\%\)) cao hơn ROE trung vị
(Median = \(18.660\%\)),
cho thấy phân bố lệch phải dương nhẹ. Điều này ngụ ý có
một số lượng giao dịch vào các công ty có hiệu suất sử dụng vốn chủ sở
hữu cao một cách ngoại lệ (gần ngưỡng Max = \(55.99\%\)).3. Định giá (Log_PE_Winsorized):
Mean
= \(2.896\)) và Trung vị
(Median = \(2.717\)) có sự
khác biệt rõ rệt (Mean > Median), khẳng định phân bố vẫn còn
lệch phải dương ngay cả sau khi chuyển đổi Logarit và
Winsorizing.4. Đòn bẩy (Leverage_Ratio):
Mean = 38.284) lớn hơn
gấp 2.5 lần so với Trung vị (Median =
14.887), và Độ lệch chuẩn (SD =
155.899) là cực kỳ cao.5. Yếu tố ESG (ESG):
Mean = \(21.815\)) thấp hơn Trung vị
(Median = \(22.800\)), cho
thấy phân bố hơi lệch trái âm. Điều này ngụ ý rằng đa
số các giao dịch tập trung vào các công ty có xếp hạng ESG tương đối
cao.Định lượng hình dạng phân bố và độ biến thiên tương đối.
vars_shape_fixed <- c("Real_Return_Winsorized", "Log_PE_Winsorized", "ROE_Winsorized", "Leverage_Ratio")
# Hàm tính toán chỉ số hình dạng và biến thiên
get_desc_stats_shape <- function(df, vars) {
# Khởi tạo data frame kết quả
result_df <- data.frame(Variable = vars)
for (var in vars) {
x <- df[[var]]
x <- x[!is.na(x)]
# Tính toán các chỉ số
mean_val <- mean(x)
sd_val <- sd(x)
stats_row <- data.frame(
Variable = var,
CV = sd_val / mean_val, # Coefficient of Variation
Skewness = moments::skewness(x),
Kurtosis = moments::kurtosis(x)
)
# Ghép kết quả
if (var == vars[1]) {
result_df <- stats_row
} else {
result_df <- rbind(result_df, stats_row)
}
}
return(result_df)
}
# Áp dụng hàm thống kê
shape_table_fixed <- get_desc_stats_shape(nyse_final_data, vars_shape_fixed)
shape_table_fixed %>%
knitr::kable(caption = "Bảng 1.2.2: Độ Lệch, Độ Nhọn và Hệ số Biến thiên")| Variable | CV | Skewness | Kurtosis |
|---|---|---|---|
| Real_Return_Winsorized | -2.085 | -0.327 | 1.34 |
| Log_PE_Winsorized | 0.288 | 1.596 | 7.02 |
| ROE_Winsorized | 0.556 | 0.763 | 3.74 |
| Leverage_Ratio | 4.072 | 14.141 | 238.06 |
Nhận xét về Độ Lệch, Độ Nhọn và Hệ số Biến thiên
1. Lợi suất Thực tế
(Real_Return_Winsorized):
Skewness = -0.327): Hệ số này
âm, khẳng định phân bố lệch trái (Left-skewed). Điều
này xác nhận nhận xét ở Bảng 2.1.1: dù đã Winsorizing, sự xuất hiện của
các khoản lỗ lớn vẫn kéo đuôi phân bố sang trái.Kurtosis = 1.34): Hệ số này
nhỏ hơn 3 (phân bố chuẩn là 3), cho thấy phân bố
Platykurtic (phẳng hơn phân bố chuẩn). Điều này ngụ ý
rằng, mặc dù có độ lệch, lợi suất không có đuôi dày (Fat Tails) nghiêm
trọng sau khi xử lý Outlier, với hầu hết các giá trị tập trung gần giá
trị trung tâm.CV = -2.085): Giá
trị CV âm do Mean âm (Mean = -0.502) và SD dương. Giá trị tuyệt đối của
CV lớn (\(\approx 2\)), cho thấy độ
biến động của lợi suất là rất cao so với giá trị trung
bình của nó.2. Định giá (Log_PE_Winsorized):
Skewness = 1.596): Hệ số
dương và lớn hơn 1, cho thấy phân bố lệch phải mạnh.
Điều này khẳng định việc chuyển đổi Logarit chưa loại bỏ hết sự không
đối xứng, và có một số lượng đáng kể giao dịch có P/E (Log) cực
cao.Kurtosis = 7.02): Hệ số này
cao hơn 3 (Leptokurtic). Phân bố có đỉnh nhọn hơn và
đuôi dày hơn so với phân bố chuẩn, cho thấy có một tỷ
lệ lớn các giá trị định giá tập trung rất sát mức trung bình và một số
lượng nhỏ giá trị cực kỳ cao.3. Đòn bẩy (Leverage_Ratio):
Skewness = 14.141) và Độ nhọn
(Kurtosis = 238.06): Cả hai chỉ số đều đạt mức cực
kỳ cao. Điều này là bằng chứng định lượng mạnh nhất cho thấy sự phân bố
này là siêu lệch phải (Hyper-positive skew) và
siêu nhọn (Hyper-kurtotic).# Kiểm định Chuẩn tắc cho Real_Return (Shapiro-Wilk)
# Lấy mẫu ngẫu nhiên do kích thước mẫu quá lớn (n > 5000)
sample_size <- 5000
set.seed(42)
sample_real_return <- nyse_final_data$Real_Return_Winsorized %>%
sample(size = sample_size, replace = FALSE)
# Tạm thời đặt scipen = 0 để p-value cực nhỏ hiển thị ở dạng khoa học
current_scipen <- options(scipen = 0)
shapiro_test <- shapiro.test(sample_real_return)
cat("Kiểm định Shapiro-Wilk cho Real_Return (Mẫu n=5000):\n")Kiểm định Shapiro-Wilk cho Real_Return (Mẫu n=5000):
# Sử dụng broom::tidy() để định dạng kết quả và làm tròn p.value
test_output <- broom::tidy(shapiro_test) %>%
mutate(
statistic = format(statistic, digits = 3),
p.value = format(p.value, scientific = TRUE, digits = 3) # Định dạng khoa học cho p-value
)
print(test_output)# A tibble: 1 × 3
statistic p.value method
<chr> <chr> <chr>
1 0.816 4.95e-60 Shapiro-Wilk normality test
options(scipen = current_scipen$scipen) # Khôi phục scipen ban đầu
# Phân bố tần số của investment
cat("\nPhân bố tần số của Kết quả Đầu tư (investment):\n")
Phân bố tần số của Kết quả Đầu tư (investment):
nyse_final_data %>%
# Sử dụng table và prop.table để tính toán chính xác
count(investment) %>%
mutate(
Percentage = (n / sum(n)) * 100
) %>%
knitr::kable(
col.names = c("Kết quả Đầu tư", "Số lượng (Count)", "Tỷ lệ (%)"),
digits = c(0, 0, 2), # Đảm bảo Count là số nguyên và Percentage làm tròn 2 chữ số
caption = "Bảng 1.2.3: Phân bố Kết quả Đầu tư (GOOD/BAD)"
)| Kết quả Đầu tư | Số lượng (Count) | Tỷ lệ (%) |
|---|---|---|
| BAD | 229328 | 64.3 |
| GOOD | 127021 | 35.6 |
Nhận xét về Kiểm định Chuẩn tắc và Phân bố Nhóm
(1). Kiểm định Tính chuẩn tắc (Shapiro-Wilk Test)
| Statistic | p.value |
|---|---|
| W | \(\approx 0.816\) |
| p-value | \(\approx 4.95 \times 10^{-60}\) |
Kết luận Định lượng: Giá trị \(p\)-value cực kỳ nhỏ (\(\approx 4.95 \times 10^{-60}\)) thấp hơn ngưỡng ý nghĩa \(\alpha = 0.05\).
Kết luận: Giả thuyết \(H_0\) (phân bố chuẩn) bị bác
bỏ. Lợi suất thực tế (Real_Return_Winsorized) có
phân bố không chuẩn tắc (Non-normal).
Ý nghĩa: Cần sử dụng các kiểm định tham số mạnh mẽ (như \(t\)-test/ANOVA) vốn vẫn khả thi với cỡ mẫu lớn (\(N=356,349\)) để so sánh nhóm.
(2). Phân bố tần số của Kết quả Đầu tư
(investment)
| Kết quả Đầu tư | Số lượng (Count) | Tỷ lệ (%) |
|---|---|---|
| BAD | 229328 | 64.3 |
| GOOD | 127021 | 35.7 |
Kết luận Định lượng: Các giao dịch thuộc nhóm
BAD (Thua lỗ/Lợi suất thấp) chiếm đa số
với tỷ lệ \(64.3\%\)
tổng số quan sát. Ngược lại, nhóm GOOD
(Sinh lời/Lợi suất cao) chỉ chiếm \(35.7\%\).
Ý nghĩa: Kết quả này định lượng hóa rằng, ngay cả sau khi kiểm soát Outlier, một khoản đầu tư ngẫu nhiên vào cổ phiếu NYSE có xác suất cao hơn 64% để rơi vào nhóm hiệu suất thấp. Điều này nhấn mạnh rằng việc tạo ra lợi nhuận cao đòi hỏi chiến lược và không phải là kết quả ngẫu nhiên.
Tính toán Ma trận Tương quan Pearson giữa các biến định lượng chính.
# Ma trận Tương quan Pearson
vars_corr <- c("Real_Return_Winsorized", "Log_PE_Winsorized", "ROE_Winsorized", "Leverage_Ratio", "ESG")
corr_matrix <- nyse_final_data %>%
select(all_of(vars_corr)) %>%
cor(use = "pairwise.complete.obs")
cat("Ma trận Tương quan (Pearson):\n")Ma trận Tương quan (Pearson):
corr_matrix %>%
knitr::kable(digits = 3, caption = "Bảng 1.2.4: Ma trận Tương quan giữa các Chỉ số Chính")| Real_Return_Winsorized | Log_PE_Winsorized | ROE_Winsorized | Leverage_Ratio | ESG | |
|---|---|---|---|---|---|
| Real_Return_Winsorized | 1.000 | -0.056 | -0.090 | -0.048 | -0.001 |
| Log_PE_Winsorized | -0.056 | 1.000 | -0.224 | 0.398 | 0.150 |
| ROE_Winsorized | -0.090 | -0.224 | 1.000 | -0.193 | -0.427 |
| Leverage_Ratio | -0.048 | 0.398 | -0.193 | 1.000 | 0.104 |
| ESG | -0.001 | 0.150 | -0.427 | 0.104 | 1.000 |
Nhận xét về Ma trận Tương quan giữa các Chỉ số Chínhmm
| Variable | Real_Return_Winsorized | Log_PE_Winsorized | ROE_Winsorized | Leverage_Ratio | ESG |
|---|---|---|---|---|---|
| Real_Return_Winsorized | \(1.000\) | \(-0.056\) | \(-0.090\) | \(-0.048\) | \(-0.001\) |
| Log_PE_Winsorized | \(-0.056\) | \(1.000\) | \(-0.224\) | \(0.398\) | \(0.150\) |
| ROE_Winsorized | \(-0.090\) | \(-0.224\) | \(1.000\) | \(-0.193\) | \(-0.427\) |
| Leverage_Ratio | \(-0.048\) | \(0.398\) | \(-0.193\) | \(1.000\) | \(0.104\) |
| ESG | \(-0.001\) | \(0.150\) | \(-0.427\) | \(0.104\) | \(1.000\) |
1. Mối quan hệ với Lợi suất Thực tế
(Real_Return_Winsorized):
Log_PE_Winsorized, ROE_Winsorized,
Leverage_Ratio) đều cho thấy mối tương quan rất
yếu với lợi suất thực tế, với hệ số tương quan (\(r\)) nằm trong khoảng từ \(-0.090\) đến \(-0.048\).2. Mối quan hệ giữa các Chỉ số Độc lập (Chỉ số Chất lượng/Định giá/Đòn bẩy):
Kết luận:
Ma trận tương quan này cung cấp bằng chứng định lượng quan trọng: các chỉ số tài chính và phi tài chính cơ bản có mối liên hệ tuyến tính cực kỳ yếu, gần như bằng không, với hiệu suất đầu tư thực tế ngẫu nhiên. Điều này củng cố các lý thuyết thị trường hiệu quả, trong đó lợi suất là ngẫu nhiên và khó dự đoán, đồng thời cho thấy lợi suất được điều khiển bởi các yếu tố bên ngoài mô hình (như hành vi nhà đầu tư, vĩ mô, hoặc sự kiện bất ngờ).
Kiểm định giả thuyết \(H_0: \rho = 0\) cho các cặp tương quan quan trọng.
current_scipen <- options(scipen = 0)
# 1. Tương quan giữa Real_Return và ROE
test_corr_return_roe <- cor.test(nyse_final_data$Real_Return_Winsorized, nyse_final_data$ROE_Winsorized)
cat("1. Tương quan giữa Real_Return và ROE:\n")1. Tương quan giữa Real_Return và ROE:
broom::tidy(test_corr_return_roe) %>%
mutate(
p.value = format(p.value, scientific = TRUE, digits = 3),
statistic = round(statistic, 2),
estimate = round(estimate, 4)
) %>%
print()# A tibble: 1 × 8
estimate statistic p.value parameter conf.low conf.high method alternative
<dbl> <dbl> <chr> <int> <dbl> <dbl> <chr> <chr>
1 -0.0904 -54.2 0e+00 356347 -0.0936 -0.0871 Pearson's… two.sided
# 2. Tương quan giữa Real_Return và Log_PE
test_corr_return_logpe <- cor.test(nyse_final_data$Real_Return_Winsorized, nyse_final_data$Log_PE_Winsorized)
cat("\n2. Tương quan giữa Real_Return và Log_PE:\n")
2. Tương quan giữa Real_Return và Log_PE:
broom::tidy(test_corr_return_logpe) %>%
mutate(
p.value = format(p.value, scientific = TRUE, digits = 3),
statistic = round(statistic, 2),
estimate = round(estimate, 4)
) %>%
print()# A tibble: 1 × 8
estimate statistic p.value parameter conf.low conf.high method alternative
<dbl> <dbl> <chr> <int> <dbl> <dbl> <chr> <chr>
1 -0.056 -33.5 2.34e-245 356347 -0.0593 -0.0527 Pearson… two.sided
Nhận xét về Kiểm định Tính ý nghĩa của Hệ số Tương quan
1. Tương quan giữa Real_Return_Winsorized và
ROE_Winsorized
| estimate (\(\rho\)) | statistic (\(t\)) | p.value | conf.low | conf.high |
|---|---|---|---|---|
| -0.0904 | -54.2 | \(\approx 0\) | -0.0936 | -0.0871 |
2. Tương quan giữa Real_Return_Winsorized và
Log_PE_Winsorized
| estimate (\(\rho\)) | statistic (\(t\)) | p.value | conf.low | conf.high |
|---|---|---|---|---|
| -0.0560 | -33.5 | \(\approx 0\) | -0.0593 | -0.0527 |
Kết luận:
Kiểm định tương quan xác nhận lại nhận xét từ Bảng 2.2.1: Các mối
quan hệ tuyến tính giữa các chỉ số tài chính cốt lõi (ROE,
Log_PE) và lợi suất thực tế (Real_Return) đều
là rất yếu (\(|\rho| \le
0.09\)). Mặc dù chúng có ý nghĩa thống kê (do \(N\) rất lớn), nhưng ý nghĩa kinh tế và khả
năng dự báo của chúng là không đáng kể.
# Trung bình và SD của Real_Return theo Sector
nyse_final_data %>%
group_by(sector) %>%
summarise(
N = n(),
Mean_Return = mean(Real_Return_Winsorized, na.rm = TRUE),
SD_Return = sd(Real_Return_Winsorized, na.rm = TRUE),
Median_Return = median(Real_Return_Winsorized, na.rm = TRUE)
) %>%
arrange(desc(Mean_Return)) %>%
knitr::kable(caption = "Bảng 1.2.5: Thống kê Lợi suất thực tế theo Ngành nghề")| sector | N | Mean_Return | SD_Return | Median_Return |
|---|---|---|---|---|
| TECH | 89107 | -0.441 | 1.09 | 0.169 |
| AUTO | 53098 | -0.473 | 1.02 | 0.137 |
| RETAIL | 92346 | -0.510 | 1.01 | 0.135 |
| FMCG | 49273 | -0.546 | 1.04 | 0.156 |
| BANK | 72525 | -0.559 | 1.05 | 0.103 |
Nhận xét về Thống kê Lợi suất thực tế theo Ngành nghề
Mean_Return) âm (phản ánh
tác động của các khoản lỗ lớn), thứ hạng lợi suất trung vị
(Median_Return) cho thấy sự khác biệt đáng kể:
SD_Return) cao hơn, phù hợp với nguyên lý tài chính
về sự đánh đổi giữa rủi ro và lợi nhuận.# Median của Log_PE và ROE cho nhóm GOOD/BAD
nyse_final_data %>%
group_by(investment) %>%
summarise(
N = n(),
Median_LogPE = median(Log_PE_Winsorized, na.rm = TRUE),
Median_ROE = median(ROE_Winsorized, na.rm = TRUE),
Mean_Leverage = mean(Leverage_Ratio, na.rm = TRUE)
) %>%
knitr::kable(caption = "Bảng 1.2.6: Thống kê Chỉ số Định giá/Hiệu suất theo Kết quả Đầu tư")| investment | N | Median_LogPE | Median_ROE | Mean_Leverage |
|---|---|---|---|---|
| BAD | 229328 | 2.69 | 19.4 | 41.5 |
| GOOD | 127021 | 2.74 | 17.4 | 32.5 |
Nhận xét về Thống kê Chỉ số Định giá/Hiệu suất theo Kết quả Đầu tư
Median_LogPE):
Median_LogPE = \(2.74\))
so với nhóm BAD (Median_LogPE = \(2.69\)).Median_ROE):
Median_ROE = \(19.4\%\))
so với nhóm GOOD (Median_ROE = \(17.4\%\)).BAD) lại được thực hiện vào các công ty có hiệu suất vốn
chủ sở hữu cao hơn (ROE cao hơn). Điều này có thể được giải thích bằng
Giả thuyết Thị trường Hiệu quả: ROE cao là thông tin công khai và đã
được phản ánh vào giá, do đó, các yếu tố khác (ví dụ: định giá quá cao,
rủi ro vĩ mô) đã chi phối lợi suất thực tế.Mean_Leverage):
Mean_Leverage = \(41.5\))
so với nhóm GOOD (Mean_Leverage = \(32.5\)).# Mean, SD, Median của ESG theo Sector
nyse_final_data %>%
group_by(sector) %>%
summarise(
N = n(),
Mean_ESG = mean(ESG, na.rm = TRUE),
Median_ESG = median(ESG, na.rm = TRUE),
SD_ESG = sd(ESG, na.rm = TRUE)
) %>%
arrange(desc(Mean_ESG)) %>%
knitr::kable(caption = "Bảng 1.2.7: Thống kê Xếp hạng ESG theo Ngành nghề")| sector | N | Mean_ESG | Median_ESG | SD_ESG |
|---|---|---|---|---|
| AUTO | 53098 | 25.7 | 29.7 | 6.20 |
| BANK | 72525 | 25.4 | 26.3 | 3.19 |
| FMCG | 49273 | 22.6 | 25.1 | 3.50 |
| TECH | 89107 | 20.7 | 16.5 | 7.00 |
| RETAIL | 92346 | 17.4 | 14.5 | 5.65 |
Nhận xét về Thống kê Xếp hạng ESG theo Ngành nghề
SD_ESG = \(7.00\)) cao nhất, cho thấy sự không đồng
nhất về tiêu chuẩn ESG trong các công ty thuộc nhóm ngành này. Ngược
lại, ngành BANK có độ biến động thấp nhất
(SD_ESG = \(3.19\)).# Density Plot cho 4 biến chính
viz_data_density <- nyse_final_data %>%
select(Real_Return_Winsorized, Log_PE_Winsorized, ROE_Winsorized, Leverage_Ratio) %>%
pivot_longer(cols = everything(), names_to = "Variable", values_to = "Value") %>%
mutate(Variable = factor(Variable, levels = c("Real_Return_Winsorized", "Log_PE_Winsorized", "ROE_Winsorized", "Leverage_Ratio"),
labels = c("Lợi suất Thực tế (Winsorized)", "Log(PE) (Winsorized)", "ROE (Winsorized)", "Tỷ lệ Đòn bẩy")))
ggplot(viz_data_density, aes(x = Value, fill = Variable)) +
geom_density(alpha = 0.6) +
facet_wrap(~Variable, scales = "free", ncol = 2) +
labs(
title = "Hình 1.3.1: Phân bố Mật độ của các Chỉ số Định lượng Chính",
x = "Giá trị",
y = "Mật độ"
) +
theme_minimal() +
theme(legend.position = "none", plot.title = element_text(face = "bold", size = 12))Nhận xét về Phân bố Mật độ của các Chỉ số Định lượng Chính
1. Lợi suất Thực tế
(Real_Return_Winsorized):
2. Định giá (Log(PE) Winsorized):
3. Hiệu suất Vốn (ROE Winsorized):
4. Tỷ lệ Đòn bẩy (Leverage Ratio):
# Bar Chart cho investment
nyse_final_data %>%
ggplot(aes(x = investment, fill = investment)) +
geom_bar() +
geom_text(stat = 'count', aes(label = after_stat(count)), vjust = -0.5) +
labs(
title = "Hình 1.3.2: Phân bố Kết quả Đầu tư (GOOD/BAD)",
x = "Kết quả Đầu tư",
y = "Số lượng Giao dịch"
) +
scale_fill_manual(values = c("GOOD" = "#28a745", "BAD" = "#dc3545")) +
theme_minimal() +
theme(legend.position = "none", plot.title = element_text(face = "bold", size = 10))Nhận xét về Phân bố Kết quả Đầu tư (GOOD/BAD)
Tổng kết
Xác suất để một khoản đầu tư ngẫu nhiên vào NYSE rơi vào nhóm hiệu suất thấp (BAD) là \(1.8\) lần cao hơn so với rơi vào nhóm hiệu suất cao (GOOD).
**Liên kết với Lợi suất:** Phân bố này phản ánh hình dạng lưỡng cực của `Real_Return_Winsorized` trong hình 1.3.1, nơi mật độ tập trung cao ở vùng lợi suất âm, tương ứng với số lượng giao dịch BAD vượt trội.
# Heatmap của Ma trận Tương quan
corr_long <- reshape2::melt(corr_matrix)
ggplot(corr_long, aes(x = Var1, y = Var2, fill = value)) +
geom_tile(color = "white") +
scale_fill_gradient2(low = "blue", high = "red", mid = "white", midpoint = 0, limit = c(-1, 1), space = "Lab", name = "Hệ số Tương quan") +
geom_text(aes(label = round(value, 2)), color = "black", size = 3) +
labs(
title = "Hình 1.3.3: Heatmap Ma trận Tương quan giữa các Chỉ số Chính",
x = "Biến",
y = "Biến"
) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1), plot.title = element_text(face = "bold", size = 12))Nhận xét
1. Mối quan hệ với Lợi suất
(Real_Return_Winsorized) - Hàng đầu tiên:
Real_Return_Winsorized chỉ hiển thị các ô màu
trắng/rất nhạt (hoặc xanh tím nhạt), xác nhận giá trị
tương quan gần bằng 0 (từ \(-0.09\) đến
\(-0.001\)).ROE_Winsorized (\(-0.09\))
có màu xanh tím nhạt nhất, trong khi ô ESG (\(-0.001\)) là màu trắng hoàn toàn (0), trực
quan hóa rằng hiệu suất đầu tư không có mối liên hệ tuyến tính
đáng kể với bất kỳ chỉ số cơ bản nào trong mô hình.2. Mối quan hệ Nội tại giữa các Chỉ số Độc lập:
# Violin Plot Lợi suất theo Sector
ggplot(nyse_final_data, aes(x = sector, y = Real_Return_Winsorized, fill = sector)) +
geom_violin(alpha = 0.7) +
geom_boxplot(width = 0.1, color = "black", alpha = 0.8, outlier.shape = NA) + # Thêm Box Plot vào trong Violin
labs(
title = "Hình 1.3.5: So sánh Phân bố Lợi suất Thực tế giữa các Ngành (Violin Plot)",
x = "Ngành nghề",
y = "Lợi suất Thực tế (Winsorized)"
) +
theme_minimal() +
theme(legend.position = "none", plot.title = element_text(face = "bold", size = 12))Nhận xét
1. Tổng quan (Sự Lệch Đồng Nhất):
2. So sánh Đặc điểm Phân bố:
3. Kết luận về Sự khác biệt Nhóm:
# Grouped Bar Chart So sánh Mean ROE và Log_PE theo Sector
sector_indicators_mean <- nyse_final_data %>%
group_by(sector) %>%
summarise(
Mean_ROE = mean(ROE_Winsorized, na.rm = TRUE),
Mean_LogPE = mean(Log_PE_Winsorized, na.rm = TRUE)
) %>%
pivot_longer(cols = starts_with("Mean"), names_to = "Indicator", values_to = "Mean_Value")
ggplot(sector_indicators_mean, aes(x = sector, y = Mean_Value, fill = Indicator)) +
geom_bar(stat = "identity", position = position_dodge(width = 0.8), width = 0.7) +
labs(
title = "Hình 1.3.6: So sánh Trung bình ROE và Log(PE) giữa các Ngành",
x = "Ngành nghề",
y = "Giá trị Trung bình (Winsorized)",
fill = "Chỉ số"
) +
scale_fill_manual(values = c("Mean_ROE" = "#007bff", "Mean_LogPE" = "#ffc107")) +
theme_minimal() +
theme(plot.title = element_text(face = "bold", size = 12))Nhận xét So sánh Trung bình ROE và Log(PE) giữa các Ngành
Biểu đồ này so sánh hai chỉ số (ROE - cột Xanh, Log(PE) - cột Vàng)
giữa các ngành. Vì Log(PE) là giá trị Logarit (từ \(2.5\) đến \(3.5\)) và ROE là phần trăm (từ
\(10\) đến \(30\)), hai cột được so sánh về giá trị
tuyệt đối trên cùng một trục Y.
1. Hiệu suất Vốn (Mean_ROE - Cột
Xanh):
2. Định giá (Mean_LogPE - Cột
Vàng):
3. Phân tích Tương quan và Mâu thuẫn Nội tại:
Median_Return) cao nhất. Điều này gợi ý rằng,
trong mẫu dữ liệu này, việc đầu tư vào các công ty có định giá cao hơn
lại có lợi hơn, mâu thuẫn với quan điểm đầu tư giá trị truyền
thống.# Box Plot Log_PE theo investment
ggplot(nyse_final_data, aes(x = investment, y = Log_PE_Winsorized, fill = investment)) +
geom_boxplot(notch = TRUE) +
labs(
title = "Hình 1.3.7: So sánh Log(PE) giữa nhóm Đầu tư GOOD và BAD",
x = "Kết quả Đầu tư",
y = "Log(PE) (Winsorized)"
) +
scale_fill_manual(values = c("GOOD" = "#28a745", "BAD" = "#dc3545")) +
theme_minimal() +
theme(legend.position = "none", plot.title = element_text(face = "bold", size = 12))Nhận xét So sánh Log(PE) giữa nhóm Đầu tư GOOD và BAD
1. So sánh Trung vị (Median):
2. So sánh Độ phân tán (IQR):
3. So sánh Đuôi Phân bố và Outlier:
# Mosaic Plot (Cần thư viện vcd nếu muốn đẹp hơn, nhưng stats::mosaicplot là đủ)
mosaicplot(sector ~ investment, data = nyse_final_data,
main = "Hình 1.3.8: Phân bố Tỷ lệ Kết quả Đầu tư theo Ngành nghề (Mosaic Plot)",
xlab = "Ngành nghề (Sector)",
ylab = "Kết quả Đầu tư (Investment)",
color = c("#dc3545", "#28a745"),
las = 2)Nhận xét về Phân bố Tỷ lệ Kết quả Đầu tư theo Ngành nghề (Mosaic Plot)
1. Sự Khác biệt về Quy mô Ngành (Chiều rộng Cột):
2. Phân tích Tỷ lệ Thành công (Tỷ lệ Cột Xanh so với Cột Đỏ):
GOOD) lớn nhất (ước tính \(\approx 45\%\) - \(47\%\)). Điều này trực quan hóa rằng, ngành
Công nghệ và Hàng tiêu dùng nhanh có xác suất thành công (tỷ lệ GOOD)
cao hơn đáng kể so với các ngành khác.BAD) lớn nhất
(ước tính \(\approx 70\%\) - \(75\%\)).3. Liên kết với Bảng 1.2.1:
Median_Return) cao nhất.
Lợi suất Trung vị cao hơn chuyển thành tỷ lệ giao dịch GOOD
cao hơn.GOOD thấp nhất.Phát hiện Chính: Mosaic Plot chứng minh có sự
phụ thuộc giữa biến sector và biến
investment. Phát hiện này cung cấp cơ sở vững chắc để thực
hiện Kiểm định ANOVA, nhằm xác định liệu sự khác biệt
về Lợi suất Trung bình giữa các ngành có thực sự có ý nghĩa thống kê hay
không.
# Box Plot ESG theo Sector
ggplot(nyse_final_data, aes(x = sector, y = ESG, fill = sector)) +
geom_boxplot(notch = TRUE) +
labs(
title = "Hình 1.3.9: So sánh Xếp hạng ESG giữa các Ngành nghề",
x = "Ngành nghề",
y = "Xếp hạng ESG"
) +
theme_minimal() +
theme(legend.position = "none", plot.title = element_text(face = "bold", size = 12))Nhận xét So sánh Xếp hạng ESG giữa các Ngành nghề
1. Xếp hạng ESG Trung vị (Median - Đường Kẻ Ngang):
2. Độ Phân tán và Tính Đồng nhất (Kích thước Hộp):
3. Kết luận về Tác động Lên Lợi suất:
# Line Plot Mean Real_Return theo Buy_Year
nyse_final_data %>%
group_by(Buy_Year) %>%
summarise(Mean_Return = mean(Real_Return_Winsorized, na.rm = TRUE)) %>%
ggplot(aes(x = Buy_Year, y = Mean_Return, group = 1)) +
geom_line(color = "blue", linewidth = 1) +
geom_point(color = "red", size = 2) +
geom_hline(yintercept = 0, linetype = "dashed", color = "grey50") +
labs(
title = "Hình 1.3.10: Xu hướng Lợi suất Thực tế Trung bình qua các Năm",
x = "Năm Mua",
y = "Lợi suất Thực tế Trung bình (Winsorized)"
) +
theme_minimal() +
theme(plot.title = element_text(face = "bold", size = 12))Nhận xét về Xu hướng Lợi suất Thực tế Trung bình qua các Năm
Biểu đồ này thể hiện xu hướng lợi suất thực tế trung bình (đã Winsorized) theo năm giao dịch mua, trong giai đoạn 2013-2018.
1. Pha Tăng trưởng (2013 - 2015):
2. Pha Suy giảm (2016 - 2017):
3. Pha Hồi phục Nhẹ (2018):
4. Kết luận về Tính Thời vụ:
# Trực quan 20: Bar Chart so sánh Mean ROE và ROA theo Buy_Year
nyse_final_data %>%
group_by(Buy_Year) %>%
summarise(
Mean_ROE = mean(ROE_Winsorized, na.rm = TRUE),
Mean_ROA = mean(ROA, na.rm = TRUE)
) %>%
pivot_longer(cols = starts_with("Mean"), names_to = "Indicator", values_to = "Mean_Value") %>%
ggplot(aes(x = Buy_Year, y = Mean_Value, fill = Indicator)) +
geom_bar(stat = "identity", position = position_dodge(width = 0.8), width = 0.7) +
labs(
title = "Hình 1.3.11: So sánh Trung bình ROE và ROA theo Năm Giao dịch",
x = "Năm Mua",
y = "Giá trị Trung bình",
fill = "Chỉ số"
) +
scale_fill_manual(values = c("Mean_ROA" = "#6c757d", "Mean_ROE" = "#20c997")) +
theme_minimal() +
theme(plot.title = element_text(face = "bold", size = 12))Nhận xét So sánh Trung bình ROE và ROA theo Năm Giao dịch
1. Mối quan hệ Nội tại giữa ROE và ROA:
Mean_ROE (Màu xanh, ước tính từ \(17.5\) đến \(21\)) luôn cao hơn đáng kể so với cột
Mean_ROA (Màu xám, ước tính từ \(6\) đến \(7.5\)).2. Phân tích Xu hướng Hiệu suất Qua các Năm:
3. Kết luận
# Density Plot Log_PE theo Investment Outcome
ggplot(nyse_final_data, aes(x = Log_PE_Winsorized, fill = investment)) +
geom_density(alpha = 0.6) +
labs(
title = "Hình 1.3.12: Phân bố Log(PE) theo Kết quả Đầu tư (GOOD/BAD)",
x = "Log(PE) (Winsorized)",
y = "Mật độ",
fill = "Kết quả"
) +
scale_fill_manual(values = c("GOOD" = "#28a745", "BAD" = "#dc3545")) +
theme_minimal() +
theme(plot.title = element_text(face = "bold", size = 12))# Density Plot ROE theo Investment Outcome
ggplot(nyse_final_data, aes(x = ROE_Winsorized, fill = investment)) +
geom_density(alpha = 0.6) +
labs(
title = "Hình 1.3.13: Phân bố ROE theo Kết quả Đầu tư (GOOD/BAD)",
x = "ROE (Winsorized)",
y = "Mật độ",
fill = "Kết quả"
) +
scale_fill_manual(values = c("GOOD" = "#28a745", "BAD" = "#dc3545")) +
theme_minimal() +
theme(plot.title = element_text(face = "bold", size = 12))# Tỷ lệ GOOD/BAD theo Năm (Buy_Year)
yearly_investment_ratio <- nyse_final_data %>%
group_by(Buy_Year) %>%
count(investment) %>%
mutate(Proportion = n / sum(n))
ggplot(yearly_investment_ratio, aes(x = Buy_Year, y = Proportion, fill = investment)) +
geom_bar(stat = "identity", position = "stack") +
labs(
title = "Hình 1.3.14: Tỷ lệ Kết quả Đầu tư (GOOD/BAD) theo Năm",
x = "Năm Mua",
y = "Tỷ lệ Phần trăm",
fill = "Kết quả"
) +
scale_fill_manual(values = c("GOOD" = "#28a745", "BAD" = "#dc3545")) +
scale_y_continuous(labels = scales::percent) +
theme_minimal() +
theme(plot.title = element_text(face = "bold", size = 12))# Scatter Plot ROE vs Log_PE (Tương quan Nội tại)
ggplot(nyse_final_data, aes(x = Log_PE_Winsorized, y = ROE_Winsorized)) +
geom_point(alpha = 0.05, color = "#007bff") +
geom_smooth(method = "lm", color = "red", se = FALSE) + # Dùng lm vì cor là tuyến tính
labs(
title = "Hình 1.3.15: Mối quan hệ giữa Định giá (Log(PE)) và Hiệu suất (ROE)",
x = "Log(PE) (Winsorized)",
y = "ROE (Winsorized)"
) +
theme_minimal() +
theme(plot.title = element_text(face = "bold", size = 12))Nhận xét về Phân bố Log(PE) theo Kết quả Đầu tư (GOOD/BAD)
Nhận xét về Phân bố ROE theo Kết quả Đầu tư (GOOD/BAD)
Nhận xét về Tỷ lệ Kết quả Đầu tư (GOOD/BAD) theo Năm
Nhận xét về Mối quan hệ Định giá (Log(PE)) và Hiệu suất (ROE)
Mục tiêu là kiểm định sự khác biệt về Lợi suất thực tế Trung bình
(Real_Return_Winsorized) giữa hai nhóm
investment (GOOD/BAD).
Cần kiểm tra Giả định Phương sai Đồng nhất
(Levene's Test) trước khi thực hiện \(t\)-test.
# Kiểm định Levene's Test (Phương sai Đồng nhất)
# Dùng bartlett.test do cỡ mẫu lớn
levene_test_result <- stats::bartlett.test(Real_Return_Winsorized ~ investment, data = nyse_final_data)
cat("Kiểm định Bartlett (Phương sai Đồng nhất):\n")Kiểm định Bartlett (Phương sai Đồng nhất):
# A tibble: 1 × 4
statistic p.value parameter method
<dbl> <dbl> <dbl> <chr>
1 199571. 0 1 Bartlett test of homogeneity of variances
# Kiểm định T-test Độc lập (Chỉ sử dụng T-test vì N lớn)
# var.equal = FALSE (Welch's T-test) nếu phương sai không đồng nhất
t_test_result <- t.test(Real_Return_Winsorized ~ investment, data = nyse_final_data, var.equal = FALSE)
cat("\nKiểm định T-test Độc lập (Lợi suất ~ investment):\n")
Kiểm định T-test Độc lập (Lợi suất ~ investment):
# A tibble: 1 × 10
estimate estimate1 estimate2 statistic p.value parameter conf.low conf.high
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 -1.44 -1.02 0.426 -678. 0 280623. -1.45 -1.44
# ℹ 2 more variables: method <chr>, alternative <chr>
**Nhận xét Kiểm định T-test cho Lợi suất (GOOD vs BAD)
Kiểm định Bartlett (Phương sai Đồng nhất)
| statistic | p.value |
|---|---|
| \(\approx 199,571\) | \(\approx 0\) |
var.equal = FALSE) là hoàn toàn chính xác
và cần thiết để kiểm soát sự không đồng nhất về phương sai này.Kiểm định T-test Độc lập (Welch’s T-test)
| estimate (Difference) | estimate1 (\(\mu_{\text{BAD}}\)) | estimate2 (\(\mu_{\text{GOOD}}\)) | statistic (\(t\)) | p.value | conf.low | conf.high |
|---|---|---|---|---|---|---|
| -1.44 | -1.02 | 0.426 | -678 | \(\approx 0\) | -1.45 | -1.44 |
Ý nghĩa Tài chính:
investment (GOOD/BAD) đã phân tách thành công hai quần thể
với đặc điểm lợi suất khác biệt rõ rệt.Mục tiêu là kiểm định sự khác biệt về Lợi suất thực tế Trung bình
giữa các nhóm ngành (sector).
# Tạm thời đặt scipen = 0 để p-value cực nhỏ hiển thị ở dạng khoa học
current_scipen <- options(scipen = 0)
# Kiểm định Bartlett (Phương sai Đồng nhất) cho Sector
levene_test_sector <- stats::bartlett.test(Real_Return_Winsorized ~ sector, data = nyse_final_data)
cat("Kiểm định Bartlett (Phương sai Đồng nhất) cho Sector:\n")Kiểm định Bartlett (Phương sai Đồng nhất) cho Sector:
broom::tidy(levene_test_sector) %>%
mutate(
statistic = round(statistic, 0),
p.value = format(p.value, scientific = TRUE, digits = 3)
) %>%
print()# A tibble: 1 × 4
statistic p.value parameter method
<dbl> <chr> <dbl> <chr>
1 576 2.61e-123 4 Bartlett test of homogeneity of variances
# Kiểm định ANOVA một chiều (aov)
anova_result <- aov(Real_Return_Winsorized ~ sector, data = nyse_final_data)
cat("\nKiểm định ANOVA một chiều (Lợi suất ~ sector):\n")
Kiểm định ANOVA một chiều (Lợi suất ~ sector):
broom::tidy(anova_result) %>%
mutate(
sumsq = round(sumsq, 0),
meansq = round(meansq, 2),
statistic = round(statistic, 0),
p.value = format(p.value, scientific = TRUE, digits = 3)
) %>%
knitr::kable(caption = "Kết quả Kiểm định ANOVA một chiều (Lợi suất ~ sector)")| term | df | sumsq | meansq | statistic | p.value |
|---|---|---|---|---|---|
| sector | 4 | 710 | 177.43 | 162 | 6.29e-139 |
| Residuals | 356344 | 389936 | 1.09 | NA | NA |
Nhận xét Kiểm định ANOVA cho Lợi suất theo Sector
1. Kiểm định Bartlett (Phương sai Đồng nhất) cho Sector
| statistic | p.value |
|---|---|
| \(576\) | \(\approx 0\) |
2. Kiểm định ANOVA một chiều
| term | df | sumsq | meansq | statistic (\(F\)) | p.value |
|---|---|---|---|---|---|
| sector | 4 | 710 | 177.43 | \(\approx 162\) | \(\approx 0\) |
| Residuals | 356344 | 389936 | 1.09 | NA | NA |
Ý nghĩa của phân tích Post-hoc Tukey’s HSD
Phân tích Post-hoc Tukey’s HSD được thực hiện sau khi kiểm định ANOVA cho kết quả có ý nghĩa thống kê (p < 0.05). Mục tiêu của bước này là xác định cụ thể cặp nhóm (ngành) nào khác biệt đáng kể về giá trị trung bình của lợi suất thực tế.
Kết quả của Tukey’s HSD cho biết: - Nếu p-value < 0.05 →
hai ngành có sự khác biệt có ý nghĩa thống kê về lợi
suất trung bình.
- Nếu p-value ≥ 0.05 → hai ngành không có sự khác biệt
rõ rệt.
Phân tích này giúp làm rõ kết quả của ANOVA, chỉ ra nhóm ngành nào có hiệu suất đầu tư cao hơn hoặc thấp hơn so với các nhóm còn lại, đồng thời đảm bảo độ tin cậy bằng cách kiểm soát sai số thống kê khi so sánh nhiều cặp giá trị.
# Phony tích Post-hoc Tukey's HSD (Sử dụng kết quả ANOVA)
# Đảm bảo ANOVA đã chạy thành công trước đó
if (exists("anova_result")) {
tukey_hsd_result <- TukeyHSD(anova_result)
cat("\nKiểm định Post-hoc Tukey's HSD (So sánh cặp Ngành nghề):\n")
print(broom::tidy(tukey_hsd_result))
}
Kiểm định Post-hoc Tukey's HSD (So sánh cặp Ngành nghề):
# A tibble: 10 × 7
term contrast null.value estimate conf.low conf.high adj.p.value
<chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 sector BANK-AUTO 0 -0.0859 -0.102 -0.0696 0
2 sector FMCG-AUTO 0 -0.0732 -0.0910 -0.0553 1.33e-14
3 sector RETAIL-AUTO 0 -0.0377 -0.0532 -0.0221 3.81e-10
4 sector TECH-AUTO 0 0.0316 0.0160 0.0473 3.51e- 7
5 sector FMCG-BANK 0 0.0127 -0.00392 0.0294 2.26e- 1
6 sector RETAIL-BANK 0 0.0482 0.0341 0.0624 5.24e-14
7 sector TECH-BANK 0 0.118 0.103 0.132 0
8 sector RETAIL-FMCG 0 0.0355 0.0196 0.0514 1.19e- 8
9 sector TECH-FMCG 0 0.105 0.0888 0.121 0
10 sector TECH-RETAIL 0 0.0693 0.0559 0.0827 0
Nhận xét Phân tích Post-hoc Tukey’s HSD
Kiểm định Tukey’s HSD so sánh sự khác biệt của Lợi suất Trung bình
(Real_Return_Winsorized) giữa tất cả các cặp ngành nghề.
\(p\)-value điều chỉnh
(adj.p.value) dưới \(0.05\) cho thấy sự khác biệt có ý nghĩa
thống kê.
1. Các Cặp khác biệt Có Ý nghĩa Thống kê (adj.p.value \(\ll 0.05\)):
| Contrast | estimate (Difference) | adj.p.value | Ý nghĩa (Difference) |
|---|---|---|---|
| TECH - BANK | \(0.1175\) | \(\approx 0\) | TECH > BANK (Sự khác biệt lớn nhất) |
| TECH - FMCG | \(0.1048\) | \(\approx 0\) | TECH > FMCG |
| TECH - RETAIL | \(0.0693\) | \(\approx 0\) | TECH > RETAIL |
| BANK - AUTO | \(-0.0859\) | \(\approx 0\) | BANK < AUTO |
| FMCG - AUTO | \(-0.0732\) | \(\approx 0\) | FMCG < AUTO |
| RETAIL - BANK | \(0.0482\) | \(\approx 0\) | RETAIL > BANK |
adj.p.value \(\approx 0.226\)), tất cả 9/10 cặp
ngành đều cho thấy sự khác biệt có ý nghĩa thống kê về Lợi suất
Trung bình (\(p < 0.001\)). Điều này
xác nhận lại sự khác biệt đã thấy trong Violin Plot (Hình 3.3.1).2. Định lượng Sự Khác biệt (Xây dựng Thứ hạng Lợi suất):
3. Phân tích Chiều sâu cho Ngoại lệ (FMCG vs BANK):
adj.p.value \(= 0.226\)).Thứ hạng Lợi suất Trung bình (Dựa trên Tukey’s HSD): \[\text{BANK} \approx \text{FMCG} < \text{RETAIL} \approx \text{AUTO} < \text{TECH}\]
Câu chuyện dữ liệu được xây dựng trên ba luận điểm chính rút ra từ các bằng chứng định lượng: (1) Sự Ngắt Kết Nối Giữa Cơ bản và Lợi suất, (2) Nghịch lý ROE, và (3) Sức mạnh Tuyệt đối của Yếu tố Hệ thống (Thời gian/Ngành).
Luận điểm I: Sự Ngắt Kết Nối Giữa Hiệu suất Cơ bản và Lợi suất Thực tế
Log_PE, ROE, Leverage) có
mối tương quan cực kỳ yếu (hệ số \(|\rho| \le 0.09\)) với
Real_Return_Winsorized.Luận điểm II: Nghịch lý ROE - Bằng chứng về Định giá Quá Cao
Luận điểm III: Sức mạnh Tuyệt đối của Yếu tố Hệ thống (Ngành và Thời gian)
sector ảnh hưởng có ý nghĩa thống kê đến Lợi suất Trung
bình. Phân tích Tukey’s HSD cho thấy TECH có lợi suất
vượt trội rõ rệt (Difference \(0.1175\)
so với BANK).GOOD/BAD) bị chi phối bởi năm mua:
Năm \(\text{2017}\) có tỷ lệ \(\text{BAD}\) lên tới \(\approx 95\%\), mặc dù ROE/ROA đang tăng
(Hình 1.3.11).Chất lượng Dữ liệu: Bộ dữ liệu NYSE có chất lượng cao (Không NA, không trùng lặp), nhưng các biến lợi suất và đòn bẩy cực kỳ lệch (Skewness \(> 14\) cho Đòn bẩy), buộc phải sử dụng Winsorizing và diễn giải bằng Trung vị.
Mối quan hệ: Các chỉ số tài chính/ESG có mối tương quan yếu không đáng kể (\(|\rho| \le 0.09\)) với lợi suất thực tế. ROE và ESG có mối tương quan âm trung bình (\(\rho = -0.427\)), cho thấy sự đánh đổi giữa hiệu suất vốn và tuân thủ ESG.
Phân Cực: Lợi suất được phân cực thành hai nhóm: \(\text{BAD}\) (Trung bình \(\approx -1.02\)) và \(\text{GOOD}\) (Trung bình \(\approx 0.426\)), khác biệt nhau có ý nghĩa thống kê (\(p \approx 0\)).
Tác động của Nhóm:
Tính Thời vụ: Tỷ lệ giao dịch thua lỗ (BAD) bị chi phối bởi năm mua (Ví dụ: \(95\%\) giao dịch thất bại trong năm 2017), cho thấy Rủi ro Hệ thống là yếu tố quyết định hàng đầu.
Hạn chế Dữ liệu:
Bộ dữ liệu được sử dụng trong nghiên cứu là giả lập ngẫu nhiên (random investments), nên có thể chưa phản ánh hoàn toàn hành vi và chiến lược đầu tư thực tế của các nhà đầu tư chuyên nghiệp.
Ngoài ra, dữ liệu chỉ kéo dài đến năm 2018, nên chưa bao gồm các biến động thị trường lớn trong giai đoạn sau (như khủng hoảng COVID-19 hoặc xu hướng ESG tăng mạnh sau 2020).
Điều này có thể ảnh hưởng đến khả năng khái quát hóa kết quả cho bối cảnh thị trường hiện tại.
Hạn chế Phương pháp:
Phân tích chỉ dừng ở thống kê mô tả, tương quan và kiểm định
so sánh nhóm (ANOVA, Tukey HSD), nên mới dừng ở mức
phát hiện sự khác biệt chứ chưa đi sâu vào đo
lường mức độ ảnh hưởng định lượng của từng biến tài chính (ví
dụ: thông qua mô hình hồi quy).
Do đó, nghiên cứu chưa xác định được mối quan hệ nhân –
quả giữa các chỉ số tài chính (như ROE, Log_PE, Leverage_Ratio,
ESG) và lợi suất đầu tư thực tế.
Hạn chế về Phạm vi và Tổng quát hóa:
Mẫu nghiên cứu chỉ bao gồm một số nhóm ngành tiêu biểu (AUTO, BANK, FMCG, RETAIL, TECH) niêm yết trên thị trường NYSE, nên không đại diện cho toàn bộ ngành nghề hoặc các thị trường khác.
Kết quả vì thế mang tính tham khảo và cần được kiểm chứng thêm bằng các nghiên cứu mở rộng quy mô dữ liệu và thời gian, hoặc so sánh giữa các sàn khác nhau (NASDAQ, LSE, v.v.) để tăng tính khái quát.
Từ kết quả hiện có, có thể rút ra một số hướng đề xuất sau:
Mở rộng mô hình nghiên cứu:
Ứng dụng cho quản trị doanh nghiệp:
Hàm ý cho nhà đầu tư:
Tóm lại, bộ dữ liệu này là nền tảng tốt để phát triển các mô hình định lượng, giúp đánh giá hiệu quả tài chính và chiến lược đầu tư trong ngành năng lượng.
Mục tiêu chính của toàn bộ Phân tích Dữ liệu Tài chính và Thị trường của mã chứng khoán GAS là cung cấp một cái nhìn toàn diện và định lượng về Sức khỏe tài chính, Hiệu suất hoạt động và Phản ứng của thị trường đối với Tổng Công ty Khí Việt Nam (GAS).
Cụ thể, đối với Nhóm biến Hiệu suất & Tăng trưởng (Nhóm 1), mục tiêu tập trung vào:
Đánh giá năng lực sinh lời: Phân tích nguồn gốc của khả năng sinh lời (ROE, ROA), xác định vai trò của Biên lợi nhuận, Vòng quay tài sản và Đòn bẩy tài chính thông qua mô hình Du Pont.
Đo lường tính chu kỳ và bền vững: Phân tích tốc độ tăng trưởng và sự biến động (YoY, Rolling Correlation) của Doanh thu, Lợi nhuận và EPS để đánh giá mức độ ổn định của hiệu suất hoạt động qua các chu kỳ kinh tế và giá dầu/khí.
Xác định mối liên hệ cơ bản: Kiểm định mối quan hệ giữa các chỉ số hiệu suất nội tại (như EPS) và Giá trị thị trường (Giá cổ phiếu) để hiểu rõ cơ sở định giá của nhà đầu tư.
Bộ dữ liệu được xây dựng từ các nguồn thông tin công khai và chính thức của Tổng Công ty Khí Việt Nam (GAS).
Dữ liệu tài chính: Được trích xuất từ các Báo cáo tài chính hợp nhất đã được kiểm toán hàng năm của GAS, bao gồm Bảng Cân đối Kế toán, Bảng Kết quả hoạt động kinh doanh và Bảng Lưu chuyển tiền tệ, tại ngày chốt sổ 31/12 hàng năm.
Dữ liệu thị trường: Thu thập từ các nguồn dữ liệu thị trường uy tín (ví dụ: Sở Giao dịch Chứng khoán, Bloomberg) về giá đóng cửa và số lượng cổ phiếu lưu hành tại ngày 31/12 hàng năm.
Đơn vị quan sát: Dữ liệu được tổng hợp theo năm.
Phạm vi thời gian: Giai đoạn 11 năm, từ 2014 đến 2024.
Bộ dữ liệu tổng thể (GAS_data_final) bao gồm 19 biến,
được phân loại thành 3 nhóm chức năng chính như sau.
(A). Biến Định danh
| Tên Biến | Mô tả | Loại dữ liệu |
|---|---|---|
| Nam | Năm quan sát (2014-2024) | Numeric |
(B). Biến Tài chính cơ bản và Thị trường
| Tên Biến | Mô tả | Nguồn gốc |
|---|---|---|
| DoanhThu | Doanh thu thuần hàng năm | Bảng KQKD |
| LoiNhuanSauThue | Lợi nhuận sau thuế của cổ đông công ty mẹ | Bảng KQKD |
| TongTaiSan | Tổng cộng tài sản cuối kỳ | Bảng CĐKT |
| VonChuSoHuu | Tổng vốn chủ sở hữu cuối kỳ | Bảng CĐKT |
| NoPhaiTra | Tổng nợ phải trả cuối kỳ | Bảng CĐKT |
| CFO | Dòng tiền thuần từ hoạt động kinh doanh | Bảng LCTT |
| EPS | Lợi nhuận trên mỗi cổ phiếu | Bảng KQKD |
| Gia_DongCua_CuoiNam | Giá đóng cửa cổ phiếu GAS tại 31/12 | Dữ liệu thị trường |
| SL_CoPhieu_LuuHanh | Số lượng cổ phiếu đang lưu hành | Dữ liệu thị trường |
(C). Biến Phái sinh
Các biến này được tính toán để phục vụ trực tiếp cho việc đánh giá hiệu suất, cấu trúc vốn và định giá.
| Tên Biến | Công thức Tính toán | Mục đích Phân tích |
|---|---|---|
| ROE_Nam | \(\text{LNST} / \text{VCSH}\) | Tỷ suất sinh lời cho cổ đông |
| ROA_Nam | \(\text{LNST} / \text{Tổng Tài sản}\) | Tỷ suất sinh lời từ tài sản |
| BienLoiNhuanRong_Nam | \(\text{LNST} / \text{DoanhThu}\) | Hiệu quả kiểm soát chi phí |
| TySoNo_Tren_VCSH | \(\text{Nợ Phải Trả} / \text{VCSH}\) | Thước đo đòn bẩy tài chính |
| DoanhThu_TangTruong_YoY | \(\%\Delta \text{Doanh Thu}\) | Tốc độ tăng trưởng quy mô |
| LoiNhuan_TangTruong_YoY | \(\%\Delta \text{LNST}\) | Tốc độ tăng trưởng lợi nhuận |
| TyLe_CFO_Tren_LNST | \(\text{CFO} / \text{LNST}\) | Chất lượng lợi nhuận (khả năng chuyển thành tiền mặt) |
| VonHoa_TyVND | \(\text{Giá Đóng Cửa} \times \text{SL Cổ Phiếu}\) | Quy mô thị trường |
| P_E_CuoiNam | \(\text{Giá Đóng Cửa} / \text{EPS}\) | Hệ số định giá |
Lưu ý: Mục 2.3 sẽ tập trung khai thác các biến trong Nhóm B và C có liên quan đến Hiệu suất & Tăng trưởng.
# Tải thư viện
library(readxl)
library(dplyr)
library(stringr)
# Đọc file Excel
bctc_path <- "C:/Users/Admin/Documents/NGÔN NGỮ R/PV GAS.xlsx"
bckt_raw <- read_excel(bctc_path, sheet = 1) # Bảng Cân đối kế toán
kqkd_raw <- read_excel(bctc_path, sheet = 2) # Bảng Kết quả kinh doanh
# Chuẩn hóa tên cột
if ("TÀI SẢN" %in% names(bckt_raw)) bckt_raw <- bckt_raw %>% rename(ChiTieu = `TÀI SẢN`)
if ("CHỈ TIÊU" %in% names(kqkd_raw)) kqkd_raw <- kqkd_raw %>% rename(ChiTieu = `CHỈ TIÊU`)
# Thêm hàm chuẩn hóa không dấu
normalize_vn <- function(x) {
x %>%
stringi::stri_trans_general("Latin-ASCII") %>%
stringr::str_to_lower() %>%
stringr::str_squish()}
print("Đã chuẩn hóa tên cột thành 'ChiTieu'.")[1] "Đã chuẩn hóa tên cột thành 'ChiTieu'."
Kết quả: Dữ liệu sau khi đưa vào ta thu được hai bảng dữ liệu đã được
làm sạch và chuẩn hoá tên cột, cụ thể “TÀI SẢN”, “CHỈ TIÊU” đã được
chuyển thành ChiTieu
library(dplyr); library(stringr); library(lubridate); library(tidyr)
# Lấy vector năm mục tiêu
year_cols_names <- names(kqkd_raw)[str_detect(names(kqkd_raw), "^\\d{2}/\\d{2}/\\d{4}$")]
nam_vec <- as.numeric(str_sub(year_cols_names, -4)) # 2014, 2015, ...
extract_row_data <- function(df, chi_tieu_patterns, scale_factor = 1e9) {
df <- df %>% mutate(ChiTieu_norm = normalize_vn(ChiTieu))
date_cols <- names(df)[stringr::str_detect(names(df), "^\\d{2}/\\d{2}/\\d{4}$")]
found <- NULL
for (pat in chi_tieu_patterns) {
pat_norm <- normalize_vn(pat)
cand <- df %>% dplyr::filter(stringr::str_detect(ChiTieu_norm, pat_norm))
if (nrow(cand) >= 1) { found <- cand; break }
}
if (is.null(found)) {
warning(sprintf("Không tìm thấy chỉ tiêu: %s", paste(chi_tieu_patterns, collapse = " | ")))
return(rep(NA_real_, length(nam_vec)))
}
if (nrow(found) > 1) {
warning(sprintf("Có >1 dòng khớp: %s. Lấy dòng đầu tiên.", paste(chi_tieu_patterns, collapse = " | ")))
found <- found %>% dplyr::slice(1)
}
tmp <- found %>%
dplyr::select(dplyr::all_of(date_cols)) %>%
tidyr::pivot_longer(everything(), names_to = "Ngay", values_to = "val") %>%
dplyr::mutate(
Nam = lubridate::year(lubridate::dmy(Ngay)),
val_chr = as.character(val),
val_num = suppressWarnings(as.numeric(stringr::str_remove_all(val_chr, "[\\.,]")))
) %>%
dplyr::arrange(Nam) %>%
dplyr::mutate(val_scaled = val_num / scale_factor)
tibble::tibble(Nam = nam_vec) %>%
dplyr::left_join(tmp %>% dplyr::select(Nam, val_scaled), by = "Nam") %>%
dplyr::pull(val_scaled)}
print("Đã định nghĩa hàm 'extract_row_data'.")[1] "Đã định nghĩa hàm 'extract_row_data'."
# Khởi tạo khung dữ liệu chuẩn
GAS_data_final <- data.frame(Nam = nam_vec)
scale_vnd_to_ty <- 1e9 # Chia cho 1 Tỷ
# Đọc LCTT (sheet 3)
lctt_raw <- try(read_excel(bctc_path, sheet = 3), silent = TRUE)
# Kiểm tra nếu đọc thành công
if (!inherits(lctt_raw, "try-error")) {
# Chuẩn hóa tên cột
if ("LƯU CHUYỂN TIỀN TỆ" %in% names(lctt_raw))
lctt_raw <- lctt_raw %>% rename(ChiTieu = `LƯU CHUYỂN TIỀN TỆ`)
else if (!"ChiTieu" %in% names(lctt_raw))
lctt_raw <- lctt_raw %>% rename(ChiTieu = names(lctt_raw)[1])
# A. Trích xuất CFO (SỬ DỤNG LCTTT_RAW ĐÃ CHUẨN HÓA)
GAS_data_final$CFO <- extract_row_data(lctt_raw,
c("lưu chuyển tiền thuần từ hoạt động kinh doanh",
"luu chuyen tien thuan tu hoat dong kinh doanh"),
scale_factor = scale_vnd_to_ty)
} else {
warning("Không đọc được sheet 3 (LCTT). Cột CFO sẽ là NA.")
GAS_data_final$CFO <- NA_real_}
# A. Trích xuất nhóm 1 (Tài chính cơ bản)
# 1. Từ Bảng KQKD (Đơn vị: Tỷ VND)
GAS_data_final$DoanhThu <- extract_row_data(
kqkd_raw,
c("doanh thu thuần về bán hàng và cung cấp dịch vụ",
"doanh thu thuần"),
scale_factor = scale_vnd_to_ty # Giữ nguyên scale_factor
)
GAS_data_final$LoiNhuanSauThue <- extract_row_data(
kqkd_raw,
c("lợi nhuận sau thuế thu nhập doanh nghiệp",
"lợi nhuận sau thuế của cổ đông công ty mẹ",
"lợi nhuận sau thuế"),
scale_factor = scale_vnd_to_ty # Giữ nguyên scale_factor
)
# 2. Từ Bảng Cân đối Kế toán (Đơn vị: Tỷ VND)
GAS_data_final$TongTaiSan <- extract_row_data(
bckt_raw,
c("tổng cộng tài sản", "tong cong tai san"),
scale_factor = scale_vnd_to_ty # Giữ nguyên scale_factor
)
GAS_data_final$VonChuSoHuu <- extract_row_data(
bckt_raw,
c("vốn chủ sở hữu", "von chu so huu", "d. von chu so huu"),
scale_factor = scale_vnd_to_ty # Giữ nguyên scale_factor
)
GAS_data_final$NoPhaiTra <- extract_row_data(
bckt_raw,
c("nợ phải trả", "no phai tra"),
scale_factor = scale_vnd_to_ty # Giữ nguyên scale_factor
)
# B. Trích xuất nhóm 2
# 1. Trích xuất EPS (Đơn vị: VND/cp - không scale)
GAS_data_final$EPS <- extract_row_data(
kqkd_raw,
c("lãi cơ bản trên cổ phiếu", "eps"),
scale_factor = 1
)
# 2. Bỏ qua khối code CFO bị lỗi lặp lại ở đây
# 3. Giá
GAS_data_final$Gia_DongCua_CuoiNam <- c(34154, 18129, 33089, 56311, 52232, 58210, 56436, 64672, 70096, 64830, 64160)
# 4. Tính toán SLCP
GAS_data_final$SL_CoPhieu_LuuHanh <- round((GAS_data_final$LoiNhuanSauThue * 1e9) / GAS_data_final$EPS)
# C. Tính toán các biến Phái sinh
data <- GAS_data_final
data$ROE_Nam <- (data$LoiNhuanSauThue / data$VonChuSoHuu) * 100
data$ROA_Nam <- (data$LoiNhuanSauThue / data$TongTaiSan) * 100
data <- data %>%
dplyr::mutate(
BienLoiNhuanRong_Nam = (LoiNhuanSauThue / DoanhThu) * 100,
FL_Nam = TongTaiSan / VonChuSoHuu,
TAT_Nam = DoanhThu / TongTaiSan,
DoanhThu_TangTruong_YoY = (DoanhThu / dplyr::lag(DoanhThu) - 1) * 100,
LoiNhuan_TangTruong_YoY = (LoiNhuanSauThue / dplyr::lag(LoiNhuanSauThue) - 1) * 100,
TySoNo_Tren_VCSH = NoPhaiTra / VonChuSoHuu,
# SỬA LỖI: Dùng ifelse để xử lý NA/Inf nếu CFO/LNST là NA/0
TyLe_CFO_Tren_LNST = ifelse(LoiNhuanSauThue != 0, CFO / LoiNhuanSauThue, NA_real_),
VonHoa_TyVND = (Gia_DongCua_CuoiNam * SL_CoPhieu_LuuHanh) / 1e9,
flag_roa_abnormal = dplyr::case_when(ROA_Nam > 100 ~ TRUE, TRUE ~ FALSE)
)
data$DoanhThu_TangTruong_YoY[is.na(data$DoanhThu_TangTruong_YoY)] <- 0
data$LoiNhuan_TangTruong_YoY[is.na(data$LoiNhuan_TangTruong_YoY)] <- 0
GAS_data_final <- data %>% dplyr::filter(flag_roa_abnormal == FALSE)
print("Đã trích xuất, chuẩn hóa và tạo tất cả 17 biến tài chính phái sinh và cơ bản.")[1] "Đã trích xuất, chuẩn hóa và tạo tất cả 17 biến tài chính phái sinh và cơ bản."
Nam CFO DoanhThu LoiNhuanSauThue TongTaiSan VonChuSoHuu NoPhaiTra EPS
1 2014 16701 73393 14370 53791 37679 16112 7140
2 2015 9127 64300 8832 56715 42889 13826 4400
3 2016 4942 59076 7172 56754 40844 15910 6748
4 2017 14386 64522 9938 61889 43272 18618 4994
5 2018 12422 75612 11709 62614 46867 15747 5911
6 2020 7331 64135 797 63208 49500 13709 4028
Gia_DongCua_CuoiNam SL_CoPhieu_LuuHanh ROE_Nam ROA_Nam BienLoiNhuanRong_Nam
1 34154 2012580185 38.14 26.71 19.58
2 18129 2007301345 20.59 15.57 13.74
3 33089 1062894151 17.56 12.64 12.14
4 56311 1989946445 22.97 16.06 15.40
5 52232 1980809589 24.98 18.70 15.49
6 56436 197909415 1.61 1.26 1.24
FL_Nam TAT_Nam DoanhThu_TangTruong_YoY LoiNhuan_TangTruong_YoY
1 1.43 1.36 0.00 0.0
2 1.32 1.13 -12.39 -38.5
3 1.39 1.04 -8.12 -18.8
4 1.43 1.04 9.22 38.6
5 1.34 1.21 17.19 17.8
6 1.28 1.01 -14.49 -93.4
TySoNo_Tren_VCSH TyLe_CFO_Tren_LNST VonHoa_TyVND flag_roa_abnormal
1 0.428 1.162 68738 FALSE
2 0.322 1.033 36390 FALSE
3 0.390 0.689 35170 FALSE
4 0.430 1.448 112056 FALSE
5 0.336 1.061 103462 FALSE
6 0.277 9.196 11169 FALSE
Nhận xét:
Bảng dữ liệu đã được trích xuất và chuẩn hóa thành công phản ánh đầy đủ hiệu quả hoạt động, cấu trúc tài chính và tăng trưởng của PVGas trong giai đoạn 2014–2024. Sáu dòng đầu tiên minh họa cho cấu trúc dữ liệu, với ba nhóm biến chính:
Nhóm biến gốc (hoạt động & quy mô):
DoanhThu, LoiNhuanSauThue,
TongTaiSan, VonChuSoHuu,
NoPhaiTra, CFO, EPS,
Gia_DongCua_CuoiNam, SL_CoPhieu_LuuHanh
→ Cung cấp nền tảng cho việc tính toán tỷ suất sinh lời và định
giá.
Nhóm biến hiệu suất & cấu trúc DuPont:
ROE_Nam, ROA_Nam,
BienLoiNhuanRong_Nam, TAT_Nam,
FL_Nam
→ Dùng để phân tích hiệu quả sinh lời, khả năng sử dụng tài sản và mức
độ đòn bẩy tài chính.
Nhóm biến tăng trưởng & chất lượng tài
chính:
DoanhThu_TangTruong_YoY,
LoiNhuan_TangTruong_YoY, VonHoa_TyVND,
TySoNo_Tren_VCSH, TyLe_CFO_Tren_LNST,
flag_roa_abnormal
→ Phản ánh tốc độ tăng trưởng, quy mô vốn hóa, sức khỏe tài chính và khả
năng tạo tiền của doanh nghiệp.
Mục này tập trung vào thống kê mô tả, phân phối, và xu hướng dòng
thời gian của các biến cốt lõi trong Nhóm 1 (DoanhThu,
LoiNhuanSauThue, ROE_Nam,
ROA_Nam, EPS,
BienLoiNhuanRong_Nam, và các biến tăng trưởng).
library(dplyr); library(moments); library(ggplot2)
library(tidyr); library(scales); library(zoo)
# 1. Thống kê mô tả chi tiết
stats_group1_full <- data %>%
dplyr::rename(ROE = ROE_Nam, ROA = ROA_Nam, BienLoiNhuanRong = BienLoiNhuanRong_Nam) %>%
dplyr::summarise(
dplyr::across(
c(DoanhThu, LoiNhuanSauThue, EPS, ROE, ROA, BienLoiNhuanRong),
list(
Mean = ~mean(., na.rm = TRUE),
Median = ~median(., na.rm = TRUE),
SD = ~sd(., na.rm = TRUE),
Min = ~min(., na.rm = TRUE),
Max = ~max(., na.rm = TRUE),
CV = ~sd(., na.rm = TRUE)/mean(., na.rm = TRUE)
),
.names = "{.col}_{.fn}"
)
) %>%
tidyr::pivot_longer(dplyr::everything(), names_to = "Tên_Biến_và_Hàm", values_to = "Giá_Trị") %>%
tidyr::separate(Tên_Biến_và_Hàm, into = c("Biến", "Hàm"), sep = "_", extra = "merge") %>%
tidyr::pivot_wider(names_from = Hàm, values_from = Giá_Trị) %>%
dplyr::rename(Hệ_số_biến_thiên_CV = CV)
# Đổi tên cột
stats_group1_display <- stats_group1_full
# In kết quả
print(stats_group1_display)# A tibble: 6 × 7
Biến Mean Median SD Min Max Hệ_số_biến_thiên_CV
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 DoanhThu 77207. 75005. 15041. 59076. 1.04e5 0.195
2 LoiNhuanSauThue 10110. 10590. 3884. 797. 1.51e4 0.384
3 EPS 5518. 4994 1264. 4028 7.65e3 0.229
4 ROE 20.6 20.6 8.74 1.61 3.81e1 0.423
5 ROA 190. 15.6 582. 1.26 1.94e3 3.06
6 BienLoiNhuanRong 13.0 13.7 4.68 1.24 1.96e1 0.360
Dựa trên Bảng Thống kê mô tả đã được tổng hợp, có thể rút ra các nhận định chính về Hiệu suất Hoạt động và Tăng trưởng của GAS trong giai đoạn 2014-2024 như sau:
1. Về Quy mô và Độ ổn định Doanh thu
2. Về Hiệu quả sinh lời kế toán (Lợi nhuận, ROE, Biên LNR)
3. Về Hiệu suất sử dụng tài sản (ROA) và Đòn bẩy
4. Về Lợi nhuận trên mỗi cổ phiếu (EPS)
Tóm tắt
Bảng thống kê cho thấy doanh nghiệp có nền tảng tăng trưởng doanh thu ổn định và khả năng sinh lời bền vững (ROE Median > 20% và hệ số biến thiên (CV) thấp).
Mặc dù tồn tại một số giá trị ngoại lệ cần được kiểm
tra lại ở chỉ tiêu ROA tuyệt đối
(Mean ≈ 190% do outlier), nhưng các giá trị trung vị
(Median) và độ biến động (CV) của các chỉ tiêu
lợi nhuận cho thấy rằng PVGas duy trì được mức sinh lời vượt
trội với:
Kết luận:
Các chỉ tiêu trên cho thấy PVGas là một doanh nghiệp có nền tảng tài chính vững mạnh, hiệu quả sinh lời cao, và rủi ro tài chính thấp, phù hợp với đặc điểm của một doanh nghiệp dẫn đầu ngành khí Việt Nam.
# 2. Phân tích Skewness và Kurtosis
skew_kurt_group1 <- data %>%
dplyr::select(LoiNhuanSauThue, ROE_Nam, BienLoiNhuanRong_Nam, DoanhThu_TangTruong_YoY) %>%
dplyr::summarise(
dplyr::across(
dplyr::everything(),
list(
Skewness = ~moments::skewness(., na.rm = TRUE),
Kurtosis = ~moments::kurtosis(., na.rm = TRUE)),
.names = "{.col}_{.fn}"))
print(skew_kurt_group1) LoiNhuanSauThue_Skewness LoiNhuanSauThue_Kurtosis ROE_Nam_Skewness
1 -1.11 4.14 -0.23
ROE_Nam_Kurtosis BienLoiNhuanRong_Nam_Skewness BienLoiNhuanRong_Nam_Kurtosis
1 4.26 -1.34 4.88
DoanhThu_TangTruong_YoY_Skewness DoanhThu_TangTruong_YoY_Kurtosis
1 0.215 1.6
# 3. Tính toán CAGR
# (Dựa trên 2.2.3, tính lại để đảm bảo tính độc lập)
cagr_dt <- ((data$DoanhThu[data$Nam == 2024] / data$DoanhThu[data$Nam == 2014])^(1/10) - 1) * 100
cagr_lnst_full <- ((data$LoiNhuanSauThue[data$Nam == 2024] / data$LoiNhuanSauThue[data$Nam == 2014])^(1/10) - 1) * 100
cagr_lnst_recovery <- ((data$LoiNhuanSauThue[data$Nam == 2024] / data$LoiNhuanSauThue[data$Nam == 2016])^(1/8) - 1) * 100
cat(sprintf("CAGR Doanh thu (2014-2024): %.2f%%\n", cagr_dt))CAGR Doanh thu (2014-2024): 3.50%
CAGR Lợi nhuận ST (2014-2024): -3.01%
CAGR Lợi nhuận ST (2016-2024 - Phục hồi): 4.99%
Nhận xét: Phân tích hình dạng phân phối và tăng trưởng kép (CAGR)
Phân tích Hình dạng phân phối (Skewness & Kurtosis)
| Biến | Skewness (Độ lệch) | Kurtosis (Độ nhọn) | Hình dạng Phân phối |
|---|---|---|---|
| LoiNhuanSauThue | -1.11 | 4.14 | Lệch âm (trái), Nhọn hơn Chuẩn |
| ROE_Nam | -0.23 | 4.26 | Gần đối xứng, Nhọn hơn Chuẩn |
| BienLoiNhuanRong_Nam | -1.34 | 4.88 | Lệch âm (trái) mạnh, Rất nhọn |
| DoanhThu_TangTruong_YoY | 0.215 | 1.6 | Gần đối xứng, Bẹt hơn Chuẩn |
Nhìn chung:
Phân tích Tốc độ tăng trưởng kép (CAGR)
| Giai đoạn | Chỉ tiêu | Tốc độ Tăng trưởng CAGR |
|---|---|---|
| 2014-2024 | Doanh thu | 3.50% |
| 2014-2024 | Lợi nhuận ST | -3.01% |
| 2016-2024 | Lợi nhuận ST (Phục hồi) | 4.99% |
Nhìn chung:
Tóm lại
Kết quả phân tích phân phối xác nhận rủi ro chu kỳ của GAS là có thật (phân phối nhọn và lệch âm của lợi nhuận/biên lợi nhuận). Tuy nhiên, mức tăng trưởng lợi nhuận sau khủng hoảng \(4.99\%\) song hành với tăng trưởng doanh thu \(3.50\%\) cho thấy doanh nghiệp đã duy trì được kỷ luật chi phí và hiệu quả hoạt động ổn định trong pha mở rộng, đảm bảo lợi nhuận tăng theo quy mô.
Biểu đồ 2.3.2a – Phân phối của Biên Lợi nhuận ròng
# Hình 1: Histogram & Density cho Biên LNR
ggplot(data, aes(x = BienLoiNhuanRong_Nam)) +
geom_histogram(aes(y = after_stat(density)), bins = 10, fill = "#0072B2", color = "white", alpha = 0.7) +
geom_density(color = "#D55E00", linewidth = 1) +
geom_vline(aes(xintercept = mean(BienLoiNhuanRong_Nam)), linetype = "dashed", color = "red") +
labs(title = "Phân phối của Biên lợi nhuận ròng (2014-2024)",
x = "Biên lợi nhuận ròng (%)", y = "Mật độ") +
theme_minimal()Nhận xét: Phân phối biên lợi nhuận ròng
Phân tích hình dạng và xu hướng tập trung
Biểu đồ Histogram và Mật độ (Density Plot) này cho thấy hình dạng
phân phối của Biên Lợi nhuận Ròng (BienLoiNhuanRong_Nam)
trong giai đoạn 2014-2024.
Về ý nghĩa kinh tế (Kỷ luật Biên Lợi nhuận)
Tóm lại có thể thấy:
Biểu đồ Phân phối của Biên Lợi nhuận Ròng trực quan hóa rõ ràng sự phân chia giữa Giai đoạn Khủng hoảng và Giai đoạn Vận hành Bền vững. Mặc dù Biên LNR phải chịu đựng sự sụt giảm nghiêm trọng trong các năm đáy, khả năng duy trì biên lợi nhuận ở mức \(>10\%\) trong phần lớn thời gian đã củng cố kết luận rằng GAS có khả năng chuyển đổi doanh thu thành lợi nhuận một cách hiệu quả và bền vững.
Biểu đồ 2.3.2b – Phát hiện Outlier trong ROE (Boxplot)
# Chỉ nhãn outlier ở boxplot
q <- quantile(data$ROE_Nam, probs = c(0.25, 0.75), na.rm = TRUE)
iqr <- q[2] - q[1]
upper <- q[2] + 1.5*iqr
lower <- q[1] - 1.5*iqr
# Hình 2: Box Plot ROE
ggplot(data, aes(x = factor(0), y = ROE_Nam)) +
geom_boxplot(fill = "#009E73", alpha = 0.7, outlier.colour = "red") +
geom_text(data = dplyr::filter(data, ROE_Nam > upper | ROE_Nam < lower),
aes(label = Nam), vjust = -0.5) +
labs(title = "Phát hiện Outlier của ROE (Năm 2014)",
x = "", y = "ROE (%)") +
theme_minimal() +
scale_y_continuous(labels = label_number(suffix = "%")) +
theme(legend.position = "none")Nhận xét biểu đồ: ROE (Hiệu suất sinh lời)
Phân tích tổng quan hình dạng phân bố
Biểu đồ boxplot minh họa sự phân bố của tỷ suất sinh lời trên vốn chủ sở hữu (ROE) của GAS trong giai đoạn 2014–2024. Phần “hộp” thể hiện khoảng giá trị trung tâm (từ tứ phân vị thứ nhất Q1 đến tứ phân vị thứ ba Q3), trong khi các điểm râu trên và dưới đại diện cho phạm vi giá trị bình thường.
Các điểm ngoại lai được phát hiện
Biểu đồ xác định hai năm ngoại lai rõ rệt:
Năm 2014 (Outlier cao): ROE vượt quá 30–35%, vượt xa phạm vi bình thường. → Đây là giai đoạn đỉnh lợi nhuận trước khủng hoảng giá dầu, khi giá bán khí và biên lợi nhuận ở mức cao kỷ lục. ROE cao phản ánh hiệu quả sử dụng vốn vượt trội, nhưng cũng là giá trị “đỉnh chu kỳ”.
Năm 2020 (Outlier thấp): ROE gần 0%, rơi xuống mức cực tiểu. → Đây là năm chịu tác động kép của đại dịch COVID-19 và giá dầu âm, khiến lợi nhuận sau thuế sụt giảm nghiêm trọng, dù doanh thu không giảm mạnh. ROE gần 0 cho thấy gần như toàn bộ lợi nhuận bị xóa bởi chi phí và dự phòng.
Ý nghĩa kinh tế và kết luận
Nhìn chung biểu đồ boxplot khẳng định:
Biểu đồ 2.3.3a – Xu hướng Doanh thu và Lợi nhuận tuyệt đối
library(ggplot2)
library(dplyr)
library(scales)
# Chuẩn bị dữ liệu
data_long_rev_profit <- data %>%
select(Nam, DoanhThu, LoiNhuanSauThue) %>%
mutate(
DoanhThu = DoanhThu / 1000,
LoiNhuanSauThue = LoiNhuanSauThue / 1000
) %>%
pivot_longer(-Nam, names_to = "ChiTieu", values_to = "GiaTri")
# Xác định các năm đặc biệt
highlight_years <- c(2016, 2020, 2022)
highlight_points <- data_long_rev_profit %>% filter(Nam %in% highlight_years)
# Vẽ biểu đồ
ggplot(data_long_rev_profit, aes(x = Nam, y = GiaTri, group = ChiTieu, color = ChiTieu)) +
# (1) Đường xu hướng chính
geom_line(linewidth = 1.3, alpha = 0.9) +
# (2) Điểm dữ liệu
geom_point(size = 3) +
# (3) Đánh dấu các năm đặc biệt
geom_point(
data = highlight_points,
aes(x = Nam, y = GiaTri),
size = 5,
shape = 21,
fill = "white",
color = "black",
stroke = 1.2
) +
# (4) Ghi chú (annotation)
geom_text(
data = highlight_points,
aes(
label = case_when(
Nam == 2016 ~ "Đáy chu kỳ\n(giá dầu giảm)",
Nam == 2020 ~ "Khủng hoảng COVID &\ngiá dầu âm",
Nam == 2022 ~ "Phục hồi mạnh\nBiên lợi nhuận cao"
)
),
vjust = -1.2, hjust = 0.5, size = 3.5, fontface = "italic", color = "black"
) +
# (5) Đường tham chiếu trung bình (Doanh thu & LNST)
geom_hline(
yintercept = mean(data_long_rev_profit$GiaTri[data_long_rev_profit$ChiTieu == "DoanhThu"]),
linetype = "dashed", color = "#0072B2", linewidth = 0.7, alpha = 0.7
) +
geom_hline(
yintercept = mean(data_long_rev_profit$GiaTri[data_long_rev_profit$ChiTieu == "LoiNhuanSauThue"]),
linetype = "dashed", color = "#D55E00", linewidth = 0.7, alpha = 0.7
) +
# (6) Ghi chú tên các đường trung bình
annotate("text", x = 2014.5,
y = mean(data_long_rev_profit$GiaTri[data_long_rev_profit$ChiTieu == "DoanhThu"]) + 2,
label = "Trung bình Doanh thu", color = "#0072B2", size = 2, hjust = 0) +
annotate("text", x = 2014.5,
y = mean(data_long_rev_profit$GiaTri[data_long_rev_profit$ChiTieu == "LoiNhuanSauThue"]) + 1,
label = "Trung bình LNST", color = "#D55E00", size = 2, hjust = 0) +
# (7) Cấu hình trục và theme
scale_y_continuous(labels = label_number(big.mark = ",", suffix = " Nghìn Tỷ VND")) +
scale_color_manual(
values = c("DoanhThu" = "#0072B2", "LoiNhuanSauThue" = "#D55E00"),
labels = c("DoanhThu" = "Doanh thu thuần", "LoiNhuanSauThue" = "Lợi nhuận Sau Thuế")
) +
labs(
title = "Biểu đồ 2.3.3a. Xu hướng Doanh thu và Lợi nhuận Sau Thuế",
subtitle = "Các năm đặc biệt được chú thích: 2016 (đáy), 2020 (khủng hoảng), 2022 (phục hồi mạnh)",
x = "Năm",
y = "Giá Trị (Nghìn Tỷ VND)",
color = "Chỉ tiêu"
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", size = 13, hjust = 0.5),
plot.subtitle = element_text(size = 7, hjust = 0.5),
legend.position = "bottom",
panel.grid.minor = element_blank(),
panel.grid.major.x = element_blank()
)Nhận xét tổng quan xu hướng doanh thu và lợi nhuận sau thuế (2014-2024)
Tổng quan xu hướng xem xét
Biểu đồ thể hiện rõ chu kỳ hoạt động gồm hai pha chính của Tổng Công ty Khí Việt Nam (GAS):
Giai đoạn 2014–2016 – Khủng hoảng và suy giảm:
Giai đoạn 2017–2024 – Phục hồi và mở rộng:
Mối quan hệ giữa hai đường xu hướng
Ý nghĩa tài chính và kinh tế
Kết luận
Biểu đồ cho thấy GAS có cấu trúc doanh thu vững, ít bị co hẹp, nhưng biên lợi nhuận nhạy với chu kỳ. Điều này củng cố kết luận:
“Hiệu suất sinh lời của GAS phụ thuộc chủ yếu vào khả năng duy trì biên lợi nhuận ổn định, chứ không chỉ ở quy mô doanh thu.”
Biểu đồ 2.3.3b – Tốc độ tăng trưởng tức thời (YoY)
# Hình 4: Bar Plot Tăng trưởng YoY
data_long_yoy <- data %>%
select(Nam, DoanhThu_TangTruong_YoY, LoiNhuan_TangTruong_YoY) %>%
filter(Nam != 2014) %>% # Loại bỏ năm gốc (NA/0)
pivot_longer(-Nam, names_to = "ChiTieu", values_to = "YoY")
ggplot(data_long_yoy, aes(x = factor(Nam), y = YoY, fill = ChiTieu)) +
geom_bar(stat = "identity", position = "dodge") +
scale_y_continuous(labels = label_number(suffix = "%")) +
scale_fill_manual(values = c("DoanhThu_TangTruong_YoY" = "#0072B2", "LoiNhuan_TangTruong_YoY" = "#D55E00"),
labels = c("DoanhThu_TangTruong_YoY" = "Doanh thu YoY", "LoiNhuan_TangTruong_YoY" = "Lợi nhuận YoY")) +
labs(title = "Biến động Tăng trưởng YoY: Doanh thu vs Lợi nhuận (2015-2024)",
x = "Năm", y = "Tốc độ Tăng trưởng (%)", fill = "Chỉ tiêu") +
theme_minimal()Nhận xét biểu đồ Biến động Tăng trưởng YoY (2015–2024)
Tổng quan hình dạng và biên độ biến động
Biểu đồ cột cho thấy mức tăng trưởng theo năm (YoY) của Doanh thu và Lợi nhuận sau thuế trong giai đoạn 2015–2024, qua đó phản ánh độ nhạy của lợi nhuận so với doanh thu.
Doanh thu YoY (cột xanh): Dao động hẹp, chủ yếu trong khoảng –10% đến +15%. Điều này cho thấy doanh thu của GAS ổn định, ít chịu biến động mạnh dù thị trường năng lượng có nhiều thay đổi.
Lợi nhuận YoY (cột cam): Biến động rất mạnh, đặc biệt có đột biến dương cực lớn vào năm 2021 (~1000%), trong khi các năm khác chỉ dao động quanh ±30%. → Điều này cho thấy lợi nhuận nhạy cảm hơn rất nhiều với biến động của giá dầu, chi phí vận hành, và các yếu tố tài chính khác.
Phân tích chi tiết theo giai đoạn
Giai đoạn 2015–2016 – Suy giảm lợi nhuận: Cả doanh thu và lợi nhuận đều tăng trưởng âm, trong đó lợi nhuận giảm mạnh hơn doanh thu. Đây là giai đoạn biên lợi nhuận bị bào mòn nghiêm trọng, phù hợp với thời kỳ giá dầu thế giới lao dốc.
Giai đoạn 2017–2019 – Ổn định tăng trưởng: Cả hai chỉ tiêu tăng trưởng nhẹ quanh mức dương. → GAS đã vượt qua giai đoạn khủng hoảng và bước vào chu kỳ tăng trưởng bền vững, nhờ giá dầu phục hồi và chi phí được kiểm soát tốt hơn.
Năm 2020 – Cú sốc suy giảm: Lợi nhuận YoY giảm sâu (~–40%), trong khi doanh thu chỉ giảm nhẹ. → Minh chứng cho tác động mạnh của đại dịch COVID-19 và giá dầu âm, khi chi phí hoạt động không thể giảm tương ứng với doanh thu.
Năm 2021 – Phục hồi kỹ thuật (đột biến): Lợi nhuận YoY tăng vọt ~1000%, do hiệu ứng nền thấp năm 2020. → Đây không phải là tăng trưởng thực chất, mà là “hiệu ứng đáy” khi lợi nhuận phục hồi từ mức rất thấp năm trước.
Giai đoạn 2022–2024 – Ổn định lại: Mức tăng trưởng lợi nhuận trở về mức dương vừa phải, dao động quanh 5–10%, phản ánh giai đoạn vận hành ổn định và bền vững.
Ý nghĩa kinh tế và kết luận
Tính ổn định khác biệt: Doanh thu phản ánh quy mô thị trường khí đốt – tương đối ổn định. Lợi nhuận lại phản ánh mức độ biến thiên của biên lợi nhuận ròng, chịu tác động mạnh từ giá dầu, chi phí tài chính và trích lập dự phòng.
Rủi ro lợi nhuận cao: Biến động YoY của lợi nhuận vượt xa doanh thu chứng minh rằng GAS có rủi ro chu kỳ lợi nhuận cao, dù doanh thu ổn định.
Khả năng phục hồi tốt: Dù có cú sốc năm 2020, doanh nghiệp phục hồi nhanh chóng trong 2021–2022 → thể hiện khả năng thích ứng và kiểm soát chi phí hiệu quả.
Từ đó biểu đồ khẳng định:
Biểu đồ 2.3.3c – Hiệu suất: ROE và ROA
# Hình 5: Line Plot ROE và ROA
data_long_roe_roa <- data %>%
select(Nam, ROE_Nam, ROA_Nam) %>%
pivot_longer(-Nam, names_to = "ChiTieu", values_to = "GiaTri")
ggplot(data_long_roe_roa, aes(x = Nam, y = GiaTri, group = ChiTieu, color = ChiTieu)) +
geom_line(linewidth = 1.2) +
geom_point(size = 3) +
scale_y_continuous(labels = label_number(suffix = "%")) +
scale_color_manual(values = c("ROE_Nam" = "#009E73", "ROA_Nam" = "#F0E442"),
labels = c("ROE_Nam" = "ROE", "ROA_Nam" = "ROA")) +
labs(title = "Quỹ đạo Hiệu suất Sinh lời: ROE vs ROA (2014-2024)",
x = "Năm", y = "Tỷ suất Sinh lời (%)", color = "Chỉ tiêu") +
theme_minimal()Nhận xét biểu đồ Quỹ đạo Hiệu suất Sinh lời: ROE vs ROA (2014–2024)
Tổng quan biến động
Biểu đồ thể hiện sự thay đổi của tỷ suất sinh lời trên tài sản (ROA) và tỷ suất sinh lời trên vốn chủ sở hữu (ROE) qua 11 năm (2014–2024). Hai chỉ tiêu này thường phản ánh hiệu quả sử dụng tài sản và hiệu quả sử dụng vốn chủ, do đó mối quan hệ giữa chúng giúp nhận diện đòn bẩy tài chính (Financial Leverage – FL).
Phân tích tương quan và diễn giải đòn bẩy
Ý nghĩa kinh tế và tài chính
(4) Kết luận
Biểu đồ cho thấy:
Biểu đồ 2.3.3d – Xu hướng EPS và Biên lợi nhuận ròng
# Hình 6: Dual Axis Plot EPS và Biên LNR
scale_factor_eps <- max(data$BienLoiNhuanRong_Nam) / max(data$EPS)
median_eps <- median(data$EPS)
median_margin <- median(data$BienLoiNhuanRong_Nam)
ggplot(data, aes(x = Nam)) +
geom_line(aes(y = EPS), color = "#0072B2", linewidth = 1.2) +
geom_point(aes(y = EPS), color = "#0072B2", size = 3) +
geom_line(aes(y = BienLoiNhuanRong_Nam / scale_factor_eps), color = "#D55E00", linewidth = 1.2, linetype = "dashed") +
scale_y_continuous(
name = "EPS (VND)",
labels = comma,
sec.axis = sec_axis(~ . * scale_factor_eps, name = "Biên Lợi nhuận Ròng (%)", labels = label_number(suffix = "%"))
) +
labs(title = "Xu hướng EPS và Biên Lợi nhuận Ròng (2014-2024)",
x = "Năm") +
theme_minimal()Nhận xét biểu đồ Xu hướng EPS và Biên lợi nhuận Ròng (2014–2024)
Xu hướng biến động và mối quan hệ cơ bản
Phân tích theo giai đoạn
Giai đoạn 2014–2016 – Suy giảm lợi nhuận:
Giai đoạn 2017–2019 – Ổn định:
Năm 2020 – Cú sốc lợi nhuận:
Năm 2021–2022 – Phục hồi mạnh:
Năm 2023–2024 – Điều chỉnh nhẹ:
Ý nghĩa tài chính
Kết luận
Biểu đồ khẳng định: “Biên lợi nhuận ròng là biến dẫn dắt chính của hiệu suất cổ phiếu GAS.”
Khi biên lợi nhuận tăng ổn định trên 12–15%, EPS duy trì ở mức ≥6.000 VND/cp, đảm bảo khả năng tạo giá trị ổn định cho cổ đông. Ngược lại, mỗi khi biên lợi nhuận suy giảm đột ngột (như 2015–2016, 2020), EPS lập tức giảm mạnh, phản ánh độ nhạy cao của lợi nhuận với biến động thị trường dầu khí.
Phân tích hồi quy song song được thực hiện nhằm kiểm định mối quan hệ tuyến tính giữa các chỉ tiêu tài chính cốt lõi của PVGas và đánh giá ảnh hưởng của các quan sát bất thường (outlier) đến độ tin cậy của mô hình.
Cụ thể, mẫu Full bao gồm toàn bộ giai đoạn 2014–2024, trong khi mẫu Clean loại bỏ năm 2019 do ROA bất thường (ROA > 100%) để kiểm tra tính ổn định của các hệ số.
Mục tiêu của phân tích là xác định hướng và độ mạnh của mối quan hệ giữa các biến (qua Slope và R²), so sánh sự khác biệt giữa hai mẫu để đánh giá độ nhạy của mô hình, đồng thời làm cơ sở định lượng cho việc phân tích hiệu quả sinh lời (ROE, ROA) và định giá cổ phiếu (Giá–EPS)
library(dplyr)
library(purrr)
library(broom)
library(tibble)
library(scales)
library(knitr)
library(kableExtra)
# 1) Tạo mẫu Full & Clean (loại 2019 do ROA bất thường)
data_full <- data
data_clean <- data %>% filter(Nam != 2019)
# 2) Định nghĩa công thức mô hình
fm_list <- list(
`LNST ~ DT` = LoiNhuanSauThue ~ DoanhThu,
`ROE ~ ROA` = ROE_Nam ~ ROA_Nam,
`Giá ~ EPS` = Gia_DongCua_CuoiNam ~ EPS
)
# 3) Hàm ước lượng & rút gọn chỉ số
fit_and_summarise <- function(df, name_suffix){
map_df(names(fm_list), function(lbl){
fit <- lm(fm_list[[lbl]], data = df)
g <- glance(fit) # r.squared, adj.r.squared, nobs, ...
t <- tidy(fit) # hệ số & p-value
slope_row <- t %>% filter(term != "(Intercept)") %>% slice(1)
tibble(
Model = lbl,
Mẫu = name_suffix,
n = g$nobs,
R2 = g$r.squared,
Adj_R2 = g$adj.r.squared,
Slope = slope_row$estimate,
`p-value` = slope_row$p.value,
Intercept = t$estimate[t$term == "(Intercept)"]
)
})
}
# 4) Chạy & gộp bảng
summary_models <- bind_rows(
fit_and_summarise(data_full, "Full"),
fit_and_summarise(data_clean, "Clean")
) %>%
mutate(
# làm tròn gọn gàng
R2 = round(R2, 5),
Adj_R2 = round(Adj_R2, 5),
Slope = round(Slope, 5),
Intercept = round(Intercept, 3),
`p-value` = ifelse(`p-value` < 1e-6,
format(`p-value`, scientific = TRUE, digits = 2),
round(`p-value`, 3))
) %>%
mutate(Model = factor(Model, levels = c("LNST ~ DT", "ROE ~ ROA", "Giá ~ EPS"))) %>%
arrange(Model, desc(Mẫu))
# 5) In bảng
kable(summary_models,
caption = "Bảng 2.3.4.1 – Tóm tắt hồi quy song song (Full vs Clean)",
align = c("l","l","r","r","r","r","r","r"),
digits = 3) %>%
kable_styling(full_width = FALSE, bootstrap_options = c("striped","hover","condensed")) %>%
column_spec(1, bold = TRUE) %>%
row_spec(which(summary_models$Mẫu == "Clean"), background = "#f7f7f7")| Model | Mẫu | n | R2 | Adj_R2 | Slope | p-value | Intercept |
|---|---|---|---|---|---|---|---|
| LNST ~ DT | Full | 11 | 0.298 | 0.220 | 0.141 | 0.082 | -774.923 |
| LNST ~ DT | Clean | 10 | 0.317 | 0.231 | 0.143 | 0.09 | -1193.544 |
| ROE ~ ROA | Full | 11 | 0.023 | -0.086 | 0.002 | 0.657 | 20.209 |
| ROE ~ ROA | Clean | 10 | 0.991 | 0.990 | 1.403 | 1.7e-09 | -0.325 |
| Giá ~ EPS | Full | 11 | 0.006 | -0.104 | -1.037 | 0.816 | 57749.126 |
| Giá ~ EPS | Clean | 10 | 0.010 | -0.113 | -1.338 | 0.778 | 58711.741 |
Nhận xét:
Ở đây ta chỉ xét mẫu sau khi làm sạch “Clean”, không xét trực tiếp
mẫu “Full” chứa năm 2019 - một quan sát ngoại lai có ROA bất
thường (>100%), làm sai lệch kết quả hồi quy và giảm mạnh
R².
> Khi loại bỏ năm này, mối quan hệ tuyến tính giữa các biến
(ROE–ROA, LNST–Doanh thu, Giá–EPS) trở nên rõ ràng, ổn
định và có ý nghĩa kinh tế hơn.
Đánh giá từng cặp biến:
1. ROE ~ ROA (Clean)
2. LNST ~ Doanh thu (Clean)
3. Giá ~ EPS (Clean)
Tổng kết
| Mô hình | R² | p-value | Kết luận chính |
|---|---|---|---|
| ROE ~ ROA | 0.991 | 1.7e-09 | Quan hệ cực kỳ chặt chẽ; hiệu suất sinh lời nội tại cao, đòn bẩy tài chính thấp. |
| LNST ~ Doanh thu | 0.317 | 0.09 | Mối quan hệ dương, trung bình; lợi nhuận chịu ảnh hưởng mạnh bởi biên lợi nhuận và chi phí ngoài quy mô. |
| Giá ~ EPS | 0.010 | 0.778 | Không có quan hệ tuyến tính đáng kể; thị trường không định giá GAS dựa trên EPS ngắn hạn. |
Biểu đồ 2.3.4b – ROE ~ ROA
library(ggplot2)
library(dplyr)
library(scales)
# Xác định dữ liệu
pt_2019 <- data %>% filter(Nam == 2019)
r2_full <- summary(lm(ROE_Nam ~ ROA_Nam, data = data))$r.squared
r2_clean <- summary(lm(ROE_Nam ~ ROA_Nam, data = filter(data, Nam != 2019)))$r.squared
ggplot(data, aes(x = ROA_Nam, y = ROE_Nam)) +
# (1) Nền xám nhẹ cho vùng hợp lý
annotate("rect", xmin = 0, xmax = 40, ymin = 0, ymax = 40,
fill = "grey95", alpha = 0.6) +
# (2) Các điểm dữ liệu thường (Full)
geom_point(aes(color = "Full sample"), size = 3, alpha = 0.9) +
# (3) Điểm ngoại lệ năm 2019
geom_point(data = pt_2019, color = "red", size = 4, shape = 8) +
geom_text(data = pt_2019,
aes(label = "2019"),
vjust = -1, color = "red", fontface = "bold", size = 3.5) +
# (4) Hồi quy – Full (nét liền)
geom_smooth(method = "lm", se = TRUE, color = "#1f77b4",
fill = alpha("#1f77b4", 0.15)) +
# (5) Hồi quy – Clean (nét gạch)
geom_smooth(data = filter(data, Nam != 2019),
aes(x = ROA_Nam, y = ROE_Nam),
method = "lm", se = TRUE,
color = "#d62728", linetype = "dashed",
fill = alpha("#d62728", 0.12)) +
# (6) Đường chấm chấm: ROE = ROA
geom_abline(slope = 1, intercept = 0,
linetype = "dotdash", color = "grey40") +
# (7) Ghi chú R²
annotate("text", x = 6, y = 37,
label = sprintf("R² Full = %.3f", r2_full),
color = "#1f77b4", hjust = 0, size = 3.3) +
annotate("text", x = 6, y = 33,
label = sprintf("R² Clean = %.3f", r2_clean),
color = "#d62728", hjust = 0, size = 3.3) +
# (8) Giới hạn trục để không bị kéo méo
coord_cartesian(xlim = c(0, 40), ylim = c(0, 40)) +
scale_x_continuous(labels = label_number(suffix = "%")) +
scale_y_continuous(labels = label_number(suffix = "%")) +
# (9) Nhãn & theme
labs(title = "Biểu đồ 2.3.4b – Tương quan: ROE ~ ROA (Full vs Clean)",
subtitle = "Đường nét liền: Full | Đường gạch: Clean (loại 2019) | Đường chấm: ROE = ROA",
x = "ROA (%)", y = "ROE (%)", color = "Mẫu dữ liệu") +
scale_color_manual(values = c("Full sample" = "#1f77b4")) +
theme_minimal(base_size = 12) +
theme(
legend.position = "bottom",
panel.grid.minor = element_blank(),
panel.grid.major.x = element_blank()
)Nhận xét Biểu đồ 2.3.4b:Tương quan: ROE ~ ROA (Full vs Clean)
Tổng quan và mục tiêu: Biểu đồ thể hiện mối quan hệ giữa ROE và ROA – hai chỉ tiêu cốt lõi đánh giá hiệu quả sinh lời của doanh nghiệp, nhằm kiểm định mức độ đòn bẩy tài chính của GAS. Hai mô hình được so sánh:
Quan sát trực quan:
Phân tích định lượng:
| Mẫu | Hệ số dốc (β) | R² | Giải thích |
|---|---|---|---|
| Full (11 năm) | ≈ 0.00–0.02 | 0.023 | Mối quan hệ bị méo mạnh do năm 2019 – ROA tăng bất thường, làm mất tương quan. |
| Clean (10 năm) | ≈ 1.40 | 0.991 | Quan hệ gần tuyến tính tuyệt đối – phản ánh cơ chế DuPont chuẩn ROE = ROA × FL. |
→ Khi bỏ năm 2019, ROE và ROA gần như song hành, xác nhận hiệu suất sinh lời vốn chủ phản ánh trung thực hiệu quả sử dụng tài sản. → Đòn bẩy tài chính (FL) trung bình khoảng 1.3–1.4 lần, tương đương cấu trúc vốn an toàn, ít rủi ro vay nợ.
Kết luận và ý nghĩa tài chính:
Biểu đồ 2.3.4c – Giá cuối năm ~ EPS
library(dplyr)
library(ggplot2)
library(broom)
library(scales)
if ("conflicted" %in% rownames(installed.packages())) {
conflicted::conflict_prefer("select", "dplyr", quiet = TRUE)
conflicted::conflict_prefer("filter", "dplyr", quiet = TRUE)
conflicted::conflict_prefer("rename", "dplyr", quiet = TRUE)
conflicted::conflict_prefer("summarise","dplyr", quiet = TRUE)
}
# 1) Dữ liệu cho mô hình Giá ~ EPS
d_price <- data %>%
dplyr::select(Nam, Gia_DongCua_CuoiNam, EPS) %>%
dplyr::filter(!is.na(EPS), !is.na(Gia_DongCua_CuoiNam))
d_clean <- d_price %>% dplyr::filter(Nam != 2019) # loại outlier nếu muốn
# 2) Ước lượng & R²
m_full <- lm(Gia_DongCua_CuoiNam ~ EPS, data = d_price)
m_clean <- lm(Gia_DongCua_CuoiNam ~ EPS, data = d_clean)
r2_full <- summary(m_full)$r.squared
r2_clean <- summary(m_clean)$r.squared
# 3) Biểu đồ 2.3.4c – Tương quan Giá ~ EPS (Full vs Clean)
ggplot(d_price, aes(x = EPS, y = Gia_DongCua_CuoiNam)) +
# (1) Nền vùng giá trị thường gặp (EPS 3k–8k; Giá 20k–75k) – chỉnh theo dữ liệu thực tế
annotate("rect", xmin = 3000, xmax = 8000, ymin = 20000, ymax = 75000,
fill = "grey95", alpha = 0.7) +
# (2) Điểm full
geom_point(aes(color = "Full"), size = 3, alpha = 0.9) +
# (3) Hồi quy Full
geom_smooth(method = "lm", se = TRUE, color = "#1f77b4",
fill = alpha("#1f77b4", 0.15)) +
# (4) Hồi quy Clean (loại 2019) – nét gạch
geom_smooth(data = d_clean, aes(x = EPS, y = Gia_DongCua_CuoiNam, color = "Clean"),
method = "lm", se = TRUE, linetype = "dashed",
fill = alpha("#d62728", 0.12)) +
# (5) Nhãn R²
annotate("text", x = min(d_price$EPS, na.rm=TRUE), y = max(d_price$Gia_DongCua_CuoiNam, na.rm=TRUE),
hjust = 0, vjust = 1.2, size = 3.5, color = "#1f77b4",
label = sprintf("R² Full = %.3f", r2_full)) +
annotate("text", x = min(d_price$EPS, na.rm=TRUE), y = max(d_price$Gia_DongCua_CuoiNam, na.rm=TRUE) - 3000,
hjust = 0, vjust = 1.2, size = 3.5, color = "#d62728",
label = sprintf("R² Clean = %.3f", r2_clean)) +
# (6) Thang trục
scale_x_continuous(labels = comma) +
scale_y_continuous(labels = comma) +
# (7) Nhãn & theme
scale_color_manual(values = c("Full" = "#1f77b4", "Clean" = "#d62728"),
name = "Mẫu dữ liệu") +
labs(title = "Biểu đồ 2.3.4c – Tương quan: Giá cổ phiếu ~ EPS (Full vs Clean)",
subtitle = "Đường liền: Full | Đường gạch: Clean (loại 2019)",
x = "EPS (VND/cp)", y = "Giá đóng cửa cuối năm (VND)") +
theme_minimal(base_size = 12) +
theme(legend.position = "bottom",
panel.grid.minor = element_blank(),
panel.grid.major.x = element_blank())# 4) Bảng tóm tắt mô hình (nếu cần chèn vào báo cáo)
summary_models_price_eps <- dplyr::bind_rows(
broom::tidy(m_full) %>% mutate(Model = "Giá ~ EPS", Mẫu = "Full"),
broom::tidy(m_clean) %>% mutate(Model = "Giá ~ EPS", Mẫu = "Clean")
) %>%
dplyr::filter(term != "(Intercept)") %>%
dplyr::select(Model, Mẫu,
Slope = estimate,
`Std.Err` = std.error,
`t` = statistic,
`p-value` = p.value) %>%
dplyr::mutate(across(c(Slope, `Std.Err`, `t`), ~round(., 4)),
`p-value` = signif(`p-value`, 3))
print(summary_models_price_eps)# A tibble: 2 × 6
Model Mẫu Slope Std.Err t `p-value`
<chr> <chr> <dbl> <dbl> <dbl> <dbl>
1 Giá ~ EPS Full -1.04 4.32 -0.24 0.816
2 Giá ~ EPS Clean -1.34 4.60 -0.291 0.778
Nhận xét Biểu đồ 2.3.4c: Tương quan: Giá cổ phiếu ~ EPS (Full vs Clean)
Mục tiêu xem xét: Biểu đồ kiểm định mối quan hệ tuyến tính giữa Giá cổ phiếu GAS tại ngày 31/12 hằng năm và EPS (thu nhập trên mỗi cổ phiếu), nhằm đánh giá liệu thị trường có phản ánh hợp lý hiệu quả sinh lời kế toán vào giá cổ phiếu hay không. Hai mô hình được so sánh:
Kết quả định lượng:
| Mẫu | Hệ số dốc (β) | R² | p-value | Diễn giải |
|---|---|---|---|---|
| Full (11 năm) | -1.04 | 0.006 | 0.816 | Không có ý nghĩa thống kê. Mối quan hệ gần như ngẫu nhiên. |
| Clean (10 năm) | -1.34 | 0.010 | 0.778 | Kết quả tương tự; loại bỏ 2019 không cải thiện đáng kể. |
→ Cả hai mô hình đều có R² rất thấp (<1%) và p-value > 0.7, chứng minh rằng biến động giá cổ phiếu GAS không phụ thuộc tuyến tính vào EPS kế toán.
Nhìn nhận trực quan:
Diễn giải kinh tế:
Mối quan hệ yếu hoặc âm giữa Giá và EPS trong dài hạn có thể bắt nguồn từ:
EPS ổn định, trong khi giá cổ phiếu chịu ảnh hưởng mạnh bởi yếu tố chu kỳ dầu khí và kỳ vọng vĩ mô, không phải lợi nhuận kế toán.
Cổ tức tiền mặt cao khiến giá cổ phiếu điều chỉnh sau chia, làm yếu tương quan với EPS.
Tác động chính sách nhà nước và giá dầu toàn cầu làm thay đổi kỳ vọng định giá mà không song hành với lợi nhuận kế toán.
Nói cách khác, EPS chỉ phản ánh hiệu quả kế toán nội tại, còn giá cổ phiếu phản ánh kỳ vọng tương lai và yếu tố chu kỳ, nên mối quan hệ tuyến tính bị phá vỡ.
Kết luận rằng:
# Gói và dữ liệu
library(dplyr)
library(ggplot2)
library(broom)
library(scales)
# Dữ liệu hồi quy LNST ~ Doanh thu
d_oper <- data %>%
dplyr::select(Nam, DoanhThu, LoiNhuanSauThue) %>%
dplyr::filter(!is.na(DoanhThu), !is.na(LoiNhuanSauThue))
# Mẫu clean loại 2019 nếu cần
d_oper_clean <- d_oper %>% dplyr::filter(Nam != 2019)
# Hồi quy song song
m_full <- lm(LoiNhuanSauThue ~ DoanhThu, data = d_oper)
m_clean <- lm(LoiNhuanSauThue ~ DoanhThu, data = d_oper_clean)
# R²
r2_full <- summary(m_full)$r.squared
r2_clean <- summary(m_clean)$r.squared
# Biểu đồ 2.3.4.d: Tương quan LNST ~ Doanh thu
ggplot(d_oper, aes(x = DoanhThu, y = LoiNhuanSauThue)) +
# (1) Nền vùng hoạt động bình thường (50k–100k tỷ)
annotate("rect", xmin = 50000, xmax = 100000, ymin = 5000, ymax = 15000,
fill = "grey95", alpha = 0.6) +
# (2) Điểm dữ liệu
geom_point(aes(color = "Full"), size = 3, alpha = 0.9) +
# (3) Hồi quy full
geom_smooth(method = "lm", se = TRUE, color = "#0072B2", fill = alpha("#0072B2", 0.15)) +
# (4) Hồi quy clean (loại 2019)
geom_smooth(data = d_oper_clean,
aes(x = DoanhThu, y = LoiNhuanSauThue, color = "Clean"),
method = "lm", se = TRUE, linetype = "dashed",
fill = alpha("#D55E00", 0.12)) +
# (5) Chú thích R²
annotate("text", x = 55000, y = 14500, label = sprintf("R² Full = %.3f", r2_full),
hjust = 0, size = 3.5, color = "#0072B2") +
annotate("text", x = 55000, y = 13500, label = sprintf("R² Clean = %.3f", r2_clean),
hjust = 0, size = 3.5, color = "#D55E00") +
# Thang trục
scale_x_continuous(labels = label_number(big.mark = ",", suffix = " tỷ VND")) +
scale_y_continuous(labels = label_number(big.mark = ",", suffix = " tỷ VND")) +
# Giao diện
scale_color_manual(values = c("Full" = "#0072B2", "Clean" = "#D55E00"),
name = "Mẫu dữ liệu") +
labs(title = "Biểu đồ 2.3.4.d – Tương quan: Lợi nhuận sau thuế ~ Doanh thu (Full vs Clean)",
subtitle = "Đường liền: Full | Đường gạch: Clean (loại 2019)",
x = "Doanh thu thuần (tỷ VND)",
y = "Lợi nhuận sau thuế (tỷ VND)") +
theme_minimal(base_size = 12) +
theme(legend.position = "bottom",
panel.grid.minor = element_blank(),
panel.grid.major.x = element_blank())Nhận xét Biểu đồ 2.3.4.d: Tương quan: LNST ~ Doanh thu
Tổng quan mối quan hệ: Biểu đồ thể hiện rõ mối tương quan dương giữa doanh thu thuần và lợi nhuận sau thuế (LNST) của GAS trong giai đoạn 2014–2024. Khi doanh thu tăng, lợi nhuận tăng tương ứng, cho thấy khả năng chuyển hóa quy mô thành lợi nhuận hiệu quả.
Đặc điểm độ dốc (Slope):
“Khi doanh thu tăng thêm 1.000 tỷ VND, lợi nhuận sau thuế tăng trung bình khoảng 140 tỷ VND.” * Tỷ lệ này thể hiện hiệu suất sinh lời ổn định ở mức 14%, phù hợp với kết quả biên lợi nhuận ròng trung bình (~13–15%) trong phần 2.3.1–2.3.3.
Về mức độ tương quan:
R² = 0.30–0.32 ⇒ mối quan hệ tuyến tính vừa phải, không quá mạnh nhưng ổn định.
Lý do R² chưa cao:
Ý nghĩa kinh tế:
Kết luận:
Tổng hợp các phát hiện định lượng và trực quan hóa từ toàn bộ nhóm biến Hiệu suất & Tăng trưởng, bao gồm Doanh thu, Lợi nhuận, ROE, ROA, Biên lợi nhuận ròng, EPS và Tốc độ tăng trưởng YoY, nhằm khái quát hóa đặc trưng vận hành và năng lực sinh lời của Tổng công ty Khí Việt Nam (GAS) trong giai đoạn 2014–2024.
1. Nền tảng quy mô ổn định và sức chống chịu chu kỳ mạnh
→ Kết luận: Quy mô hoạt động của GAS có tính ổn định cấu trúc, đóng vai trò “vành đai hấp thụ rủi ro” trong chu kỳ giá năng lượng.
2. Biên lợi nhuận ròng cao và duy trì ổn định
Biên lợi nhuận ròng trung bình ≈ 13.0%, dao động chủ yếu trong khoảng 10–18%.
Phân phối có Skewness âm (-1.34) và Kurtosis cao (4.88), nghĩa là:
Biểu đồ phân phối (Histogram) cho thấy hai cụm rõ rệt:
→ Kết luận: GAS duy trì khả năng kiểm soát chi phí và biên lợi nhuận hiệu quả; chỉ biến động mạnh trong các cú sốc dầu khí toàn cầu.
3. ROE duy trì mức cao, ROA ổn định – đòn bẩy tài chính an toàn
ROE trung bình = 20.6%, ROA trung vị ≈ 15.6%, chênh lệch nhỏ phản ánh đòn bẩy tài chính thấp (FL ≈ 1.3).
Ngoại trừ năm 2019 (ROA ≈ 2000%) – sai lệch kế toán hoặc mẫu số bất thường – hai chỉ tiêu này di chuyển gần như song song và đồng pha.
Kết quả hồi quy xác nhận:
→ Kết luận: GAS đạt hiệu suất sử dụng tài sản và vốn chủ gần như đồng nhất, cấu trúc vốn cực kỳ an toàn, ít phụ thuộc nợ vay.
4. Mối quan hệ giữa Doanh thu và Lợi nhuận: tăng trưởng thực chất
→ Kết luận: Tăng trưởng doanh thu của GAS thực sự chuyển hóa thành lợi nhuận, nhưng biên lợi nhuận là nhân tố quyết định hiệu suất ròng.
5. Mối liên hệ Giá cổ phiếu – EPS yếu: thị trường phản ứng chậm
→ Kết luận: GAS là cổ phiếu “giá trị phòng thủ” – giá thị trường ít biến động theo EPS, thể hiện đặc trưng của doanh nghiệp nhà nước có dòng tiền ổn định nhưng thiếu yếu tố đầu cơ.
6. Tổng hợp
| Giai đoạn | Đặc trưng chính | Tác động tài chính |
|---|---|---|
| 2014–2016 | Suy giảm mạnh do khủng hoảng dầu khí | Biên LNR < 5%, ROE giảm, EPS thấp |
| 2017–2019 | Phục hồi và ổn định | Biên LNR ~13–15%, ROE ~20% |
| 2020 | Cú sốc COVID và giá dầu âm | Lợi nhuận gần 0, ROE thấp nhất |
| 2021–2024 | Phục hồi mạnh và tái ổn định | ROE, EPS và Biên LNR tăng trở lại |
Tóm lại:
Từ các kết quả trên, có thể khẳng định rằng sinh lời của GAS đến chủ yếu từ hiệu quả hoạt động (ROA) chứ không phải do đòn bẩy tài chính (FL). Do đó, để hiểu sâu hơn nguồn gốc cấu thành của ROE, phần tiếp theo sẽ tiến hành phân rã DuPont, xem xét đóng góp của:
Bảng tóm tắt ngắn gọn:
| Chỉ tiêu | Trung bình | Độ biến động | Xu hướng chính |
|---|---|---|---|
| Doanh thu | ~77 nghìn tỷ VND | Thấp | Ổn định, tăng chậm |
| LNST | ~10 nghìn tỷ VND | Trung bình | Nhạy với chu kỳ giá dầu |
| Biên LNR | ~13% | Thấp | Duy trì bền vững |
| ROE | ~20.6% | Thấp | Ổn định, đòn bẩy thấp |
| ROA | ~15.6% (median) | Cao (do 2019) | Hiệu quả tài sản cao |
| EPS | ~5,500 VND/cp | Thấp | Gắn chặt Biên LNR |
| R²(ROE~ROA) | 0.991 (clean) | – | Quan hệ tuyến tính mạnh |
| R²(LNST~DT) | 0.30 | – | Quan hệ dương, ổn định |
| R²(Giá~EPS) | 0.01 | – | Thị trường phản ứng yếu |
library(dplyr)
library(tidyr)
library(ggplot2)
library(scales)
# Tính ba thành phần DuPont
dupont_df <- data %>%
mutate(
BienLoiNhuanRong = BienLoiNhuanRong_Nam / 100, # đổi về hệ số
TAT = TAT_Nam, # Hiệu suất sử dụng tài sản
FL = FL_Nam, # Đòn bẩy tài chính
ROE_DuPont = BienLoiNhuanRong * TAT * FL * 100 # ROE suy ra (%)
) %>%
select(Nam, BienLoiNhuanRong, TAT, FL, ROE_DuPont, ROE_Nam)
# Tạo bảng tổng hợp
dupont_summary <- dupont_df %>%
summarise(
Mean_NPM = mean(BienLoiNhuanRong, na.rm = TRUE) * 100,
Mean_TAT = mean(TAT, na.rm = TRUE),
Mean_FL = mean(FL, na.rm = TRUE),
Mean_ROE_ThucTe = mean(ROE_Nam, na.rm = TRUE),
Mean_ROE_DuPont = mean(ROE_DuPont, na.rm = TRUE)
)
print("Bảng tóm tắt DuPont trung bình (2014–2024):")[1] "Bảng tóm tắt DuPont trung bình (2014–2024):"
Mean_NPM Mean_TAT Mean_FL Mean_ROE_ThucTe Mean_ROE_DuPont
1 13 12 1.25 20.6 20.6
# BIỂU ĐỒ 2.4.1a: PHÂN RÃ DUPONT THEO THỜI GIAN (STACKED AREA)
# Chuẩn bị dữ liệu cho stacked area
dupont_long <- dupont_df %>%
select(Nam, BienLoiNhuanRong, TAT, FL) %>%
pivot_longer(cols = c(BienLoiNhuanRong, TAT, FL),
names_to = "ThànhPhan", values_to = "GiáTrị")
ggplot(dupont_long, aes(x = Nam, y = GiáTrị, fill = ThànhPhan)) +
geom_area(alpha = 0.8, color = "white", size = 0.4) +
scale_fill_manual(
values = c("BienLoiNhuanRong" = "#0072B2",
"TAT" = "#E69F00",
"FL" = "#56B4E9"),
labels = c("BienLoiNhuanRong" = "Biên lợi nhuận ròng (NPM)",
"TAT" = "Hiệu suất tài sản (TAT)",
"FL" = "Đòn bẩy tài chính (FL)")
) +
labs(
title = "Biểu đồ 2.4.1a – Phân rã DuPont: Cấu trúc ROE theo thời gian (2014–2024)",
subtitle = "ROE = Biên lợi nhuận ròng × Hiệu suất sử dụng tài sản × Đòn bẩy tài chính",
x = "Năm",
y = "Giá trị (hệ số)",
fill = "Thành phần"
) +
theme_minimal(base_size = 10) +
theme(legend.position = "bottom",
plot.title = element_text(face = "bold", hjust = 0.5),
plot.subtitle = element_text(size = 9, hjust = 0.5))# BIỂU ĐỒ 2.4.1b: SO SÁNH ROE THỰC TẾ VS. ROE TÍNH THEO DUPONT
ggplot(dupont_df, aes(x = Nam)) +
geom_line(aes(y = ROE_Nam, color = "ROE thực tế"), linewidth = 1.2) +
geom_point(aes(y = ROE_Nam, color = "ROE thực tế"), size = 3) +
geom_line(aes(y = ROE_DuPont, color = "ROE tính theo DuPont"), linewidth = 1.2, linetype = "dashed") +
geom_point(aes(y = ROE_DuPont, color = "ROE tính theo DuPont"), size = 2) +
scale_color_manual(values = c("ROE thực tế" = "#D55E00", "ROE tính theo DuPont" = "#0072B2")) +
scale_y_continuous(labels = label_number(suffix = "%")) +
labs(
title = "Biểu đồ 2.4.1b – So sánh ROE thực tế và ROE theo mô hình DuPont",
x = "Năm",
y = "Tỷ suất sinh lời (%)",
color = "Loại ROE"
) +
theme_minimal(base_size = 12) +
theme(legend.position = "bottom",
plot.title = element_text(face = "bold", hjust = 0.5),
panel.grid.minor = element_blank())Mô hình DuPont là công cụ phân rã lợi nhuận trên vốn chủ sở hữu (ROE) thành ba thành phần cốt lõi:
\[ ROE = \text{NPM} \times \text{TAT} \times \text{FL} \]
Trong đó: - NPM: Biên lợi nhuận ròng (Net Profit Margin) dùng để đo hiệu quả kiểm soát chi phí và khả năng chuyển hóa doanh thu thành lợi nhuận ròng.
TAT: Hiệu suất sử dụng tài sản (Total Asset Turnover) sẽ phản ánh tốc độ quay vòng tài sản
FL: Đòn bẩy tài chính (Financial Leverage) cho biết mức khuếch đại lợi nhuận từ vốn chủ sở hữu.
Kết quả định lượng trung bình giai đoạn 2014–2024
| Chỉ tiêu | Giá trị trung bình | Ý nghĩa |
|---|---|---|
| Biên lợi nhuận ròng (NPM) | 13% | Doanh nghiệp duy trì biên lợi nhuận ổn định và cao trong ngành năng lượng. |
| Hiệu suất sử dụng tài sản (TAT) | 12% | Mỗi đồng tài sản tạo ra 0.12 đồng doanh thu, phản ánh hiệu quả tài sản ở mức khá. |
| Đòn bẩy tài chính (FL) | 1.25 lần | Mức đòn bẩy thấp, cấu trúc vốn an toàn, rủi ro tài chính nhỏ. |
| ROE thực tế (Mean) | 20.6% | Mức sinh lời cao, ổn định qua nhiều năm. |
| ROE tính theo DuPont | 20.6% | Khớp hoàn toàn với ROE thực tế → mô hình phản ánh đúng cấu trúc sinh lời. |
Như vậy, toàn bộ ROE của GAS được tái tạo chính xác bởi mô hình DuPont, chứng minh sự ổn định và hợp lý trong cấu trúc sinh lời của doanh nghiệp.
Phân tích biến động theo thời gian (Biểu đồ 2.4.1a)
→ Có thể khẳng định: TAT và NPM là hai yếu tố chi phối ROE, trong khi FL giữ vai trò khuếch đại nhẹ, giúp ROE duy trì trên 20% mà không tăng rủi ro tài chính.
Kiểm chứng mô hình DuPont (Biểu đồ 2.4.1b)
Giải thích kinh tế – Cấu trúc sinh lời của GAS
| Thành phần | Vai trò trong ROE | Đặc điểm tại GAS |
|---|---|---|
| NPM | Quyết định chất lượng lợi nhuận | Ổn định quanh 13%, cao so với trung bình ngành. |
| TAT | Phản ánh hiệu quả khai thác tài sản | Duy trì 0.12–0.15, cải thiện giai đoạn sau 2021. |
| FL | Khuếch đại lợi nhuận vốn chủ | Thấp (1.2–1.3) → GAS gần như không vay nợ nhiều. |
Do đó, ROE cao của GAS đến chủ yếu từ hiệu quả hoạt động (ROA cao) chứ không phải từ đòn bẩy tài chính, minh chứng cho chiến lược tăng trưởng an toàn và quản trị vốn thận trọng.
Kết luận
Cơ sở lý thuyết
Theo mô hình DuPont:
\[ ROE = NPM \times TAT \times FL \]
Ta có vi phân tương đối (độ nhạy tuyến tính):
\[ \frac{\Delta ROE}{ROE} = \frac{\Delta NPM}{NPM} + \frac{\Delta TAT}{TAT} + \frac{\Delta FL}{FL} \]
Suy ra, hệ số co giãn của ROE theo từng biến được tính bằng:
\[ E_{ROE,x} = \frac{\partial (ROE) / ROE}{\partial x / x} = \frac{x}{ROE} \times \frac{\partial (ROE)}{\partial x} \]
Do \(\frac{\partial ROE}{\partial NPM} = TAT \times FL\), ta có:
| Thành phần | Hệ số co giãn |
|---|---|
| \(E_{ROE,NPM} = \frac{NPM \times TAT \times FL}{ROE}\) | ≈ 1 |
| \(E_{ROE,TAT} = \frac{NPM \times TAT \times FL}{ROE}\) | ≈ 1 |
| \(E_{ROE,FL} = \frac{NPM \times TAT \times FL}{ROE}\) | ≈ 1 |
Trong mô hình tuyến tính hoàn hảo, tất cả các hệ số co giãn
đều bằng 1.
Tuy nhiên, trong dữ liệu thực tế, do phi tuyến và các hiệu ứng kế toán,
ta đo mức thay đổi ROE (%) khi từng biến tăng 1%, giữ
các biến khác cố định.
Mục tiêu
Phân tích độ nhạy nhằm xác định ROE của GAS nhạy cảm nhất với yếu tố nào trong ba thành phần của mô hình DuPont:
Từ đó, xác định nguồn gốc động lực sinh lời chủ yếu và mức độ bền vững của ROE.
library(dplyr)
library(ggplot2)
library(scales)
# Tạo biến độ nhạy (thay đổi 1%)
dupont_sens <- dupont_df %>%
mutate(
dNPM = (BienLoiNhuanRong * 1.01) * TAT * FL * 100,
dTAT = BienLoiNhuanRong * (TAT * 1.01) * FL * 100,
dFL = BienLoiNhuanRong * TAT * (FL * 1.01) * 100,
Sens_NPM = (dNPM - ROE_DuPont) / ROE_DuPont * 100,
Sens_TAT = (dTAT - ROE_DuPont) / ROE_DuPont * 100,
Sens_FL = (dFL - ROE_DuPont) / ROE_DuPont * 100
) %>%
select(Nam, Sens_NPM, Sens_TAT, Sens_FL) %>%
pivot_longer(cols = starts_with("Sens_"),
names_to = "ThànhPhan", values_to = "ĐộNhạy") %>%
mutate(ThànhPhan = recode(ThànhPhan,
"Sens_NPM" = "Biên lợi nhuận ròng (NPM)",
"Sens_TAT" = "Hiệu suất tài sản (TAT)",
"Sens_FL" = "Đòn bẩy tài chính (FL)"))
# BIỂU ĐỒ 2.4.1c – Độ nhạy ROE theo các thành phần DuPont
ggplot(dupont_sens, aes(x = Nam, y = ĐộNhạy, color = ThànhPhan, group = ThànhPhan)) +
geom_line(linewidth = 1.2) +
geom_point(size = 2) +
geom_hline(yintercept = 1, color = "grey40", linetype = "dotted") +
scale_color_manual(values = c("#0072B2", "#E69F00", "#56B4E9")) +
scale_y_continuous(labels = label_percent(scale = 1)) +
labs(
title = "Biểu đồ 2.4.1c – Phân tích độ nhạy của ROE theo mô hình DuPont",
subtitle = "Biểu diễn mức thay đổi (%) của ROE khi từng thành phần tăng 1%",
x = "Năm", y = "Độ nhạy (%)",
color = "Thành phần ảnh hưởng"
) +
theme_minimal(base_size = 12) +
theme(legend.position = "bottom",
plot.title = element_text(face = "bold", hjust = 0.5))Nhận xét
Kết quả mô phỏng độ nhạy
Biểu đồ 2.4.2a thể hiện mức thay đổi (%) của ROE khi từng thành phần trong mô hình DuPont tăng 1%, các yếu tố còn lại giữ nguyên.
| Thành phần | Độ nhạy trung bình (E) | Diễn giải |
|---|---|---|
| NPM (Biên lợi nhuận ròng) | ≈ 1.00 | Tăng 1% NPM → ROE tăng 1% |
| TAT (Hiệu suất tài sản) | ≈ 1.00 | Tăng 1% TAT → ROE tăng 1% |
| FL (Đòn bẩy tài chính) | ≈ 1.00 | Tăng 1% FL → ROE tăng 1% |
Giải thích kết quả
Ba đường trùng khít hoàn toàn ở mức 1.00% cho thấy:
Vì giá trị trung bình của các yếu tố khác nhau (NPM = 13%, TAT = 0.12, FL = 1.25) → tác động tuyệt đối đến ROE không ngang nhau, dù hệ số co giãn tương đối bằng 1.
Về ý nghĩa kinh tế
Biên lợi nhuận ròng (NPM) là yếu tố chi phối chính của ROE, bởi:
Hiệu suất tài sản (TAT) phản ánh hiệu quả sử dụng tài sản cố định:
Đòn bẩy tài chính (FL) duy trì quanh 1.2–1.3, cho thấy:
Kết luận
ROE của GAS nhạy tuyến tính 1:1 với từng yếu tố DuPont, nhưng ảnh hưởng thực tế lớn nhất đến từ NPM.
TAT và FL đóng vai trò bổ trợ, giúp duy trì cấu trúc sinh lời ổn định.
Mô hình DuPont khớp tuyệt đối (E = 1) cho thấy GAS có cấu trúc tài chính minh bạch, ổn định và kiểm soát rủi ro tốt.
ROE duy trì cao (≈20%) chủ yếu nhờ hiệu quả hoạt động và khả năng kiểm soát chi phí vượt trội, không dựa vào nợ vay.
Điều này chứng tỏ ROE tăng tỷ lệ thuận với từng yếu tố cấu thành, trong đó Biên lợi nhuận ròng là nhân tố tác động mạnh nhất và đóng vai trò trung tâm trong cấu trúc sinh lời của doanh nghiệp.*
1. Mục tiêu
Phân tích và trực quan hóa tác động kết hợp giữa Biên lợi nhuận ròng (NPM) và Hiệu suất sử dụng tài sản (TAT) đến tỷ suất sinh lời trên vốn chủ (ROE) theo mô hình DuPont. Từ đó xác định vùng sinh lời tối ưu, và đánh giá mức độ phụ thuộc lẫn nhau giữa hai yếu tố vận hành cốt lõi.
2. Cơ sở lý thuyết
Theo mô hình DuPont rút gọn (vì FL gần như ổn định):
\[ ROE = NPM \times TAT \times FL \]
Với giá trị trung bình \(FL = 1.25\) (giai đoạn 2014–2024), công thức trở thành:
\[ ROE = 1.25 \times NPM \times TAT \]
Từ đó, mô phỏng ROE theo các mức kết hợp khác nhau của NPM và TAT nhằm đánh giá:
library(ggplot2)
library(dplyr)
library(scales)
# Tạo lưới giá trị NPM & TAT
npm_seq <- seq(0.05, 0.25, by = 0.005) # 5% → 25%
tat_seq <- seq(0.05, 0.25, by = 0.005) # 0.05 → 0.25
fl_fixed <- 1.25
# Tạo khung dữ liệu mô phỏng
heat_df <- expand.grid(NPM = npm_seq, TAT = tat_seq) %>%
mutate(ROE = NPM * TAT * fl_fixed)
# Biểu đồ 2.4.1d: Bản đồ nhiệt (Heatmap)
ggplot(heat_df, aes(x = NPM, y = TAT, fill = ROE)) +
geom_tile() +
geom_contour(aes(z = ROE), color = "white", linewidth = 0.3) +
scale_fill_gradient(low = "#f7fbff", high = "#08306b", labels = label_percent(accuracy = 1)) +
labs(
title = "Biểu đồ 2.4.1d – Mô phỏng tác động đồng thời của NPM và TAT lên ROE",
subtitle = "Mô hình DuPont (FL cố định = 1.25) | ROE = NPM × TAT × FL",
x = "Biên lợi nhuận ròng (NPM)",
y = "Hiệu suất sử dụng tài sản (TAT)",
fill = "ROE (%)"
) +
theme_minimal(base_size = 9) +
theme(
legend.position = "right",
plot.title = element_text(face = "bold", hjust = 0.5),
plot.subtitle = element_text(size = 7)
)Diễn giải biểu đồ 2.4.3a
Biểu đồ thể hiện mối quan hệ đồng biến và tuyến tính hoàn hảo giữa NPM, TAT và ROE:
Đây là dạng mặt phẳng đồng dốc, đặc trưng cho mô hình DuPont tuyến tính, phản ánh mối quan hệ nhân quả rõ ràng giữa hiệu quả hoạt động và tỷ suất sinh lời.
Về ý nghĩa kinh tế
| Thành phần | Ảnh hưởng đến ROE | Giải thích chi tiết |
|---|---|---|
| NPM – Biên lợi nhuận ròng | Tác động mạnh nhất | Khi NPM tăng, mỗi đồng doanh thu tạo ra nhiều lợi nhuận hơn → ROE tăng nhanh. |
| TAT – Hiệu suất sử dụng tài sản | Tác động khuếch đại | Khi TAT cao, tài sản quay vòng nhanh hơn → cùng biên lợi nhuận, ROE vẫn cao hơn. |
| FL – Đòn bẩy tài chính | Ổn định, đóng vai trò cố định | FL cố định 1.25 giúp ROE phản ánh đúng hiệu quả nội tại thay vì bị khuếch đại bởi nợ vay. |
Khi NPM và TAT tăng đồng thời, hiệu ứng cộng hưởng (multiplicative) khiến ROE tăng nhanh gấp đôi so với từng yếu tố riêng lẻ. Đây là dấu hiệu mô hình vận hành hiệu quả — doanh nghiệp có thể tối đa hóa ROE mà không cần tăng nợ.
Kết luận
Mô hình mô phỏng xác nhận ROE của GAS phụ thuộc đồng thời và tuyến tính vào NPM và TAT.
Cải thiện đồng thời biên lợi nhuận và hiệu suất tài sản là chìa khóa để tăng mạnh ROE,trong khi việc thay đổi đòn bẩy tài chính (FL) không ảnh hưởng đáng kể.
Vùng hiệu quả cao (ROE > 6%) đạt được khi NPM > 20% và TAT > 0.20,thể hiện khả năng sinh lời bền vững của GAS từ hiệu quả vận hành chứ không từ rủi ro tài chính.
Kiểm định và đánh giá mối quan hệ tuyến tính giữa Biên lợi nhuận ròng (NPM) và Tỷ suất sinh lời trên tài sản (ROA). Mục tiêu là xác định xem ROA có phản ánh trực tiếp khả năng sinh lợi ròng, hay chịu ảnh hưởng mạnh của yếu tố khác như cơ cấu tài sản hoặc chi phí vốn.
# Tránh xung đột select()
library(dplyr)
library(ggplot2)
library(broom)
library(scales)
# Nếu dữ liệu phân tích chính đang ở object `data`, tạo khung DuPont chuẩn:
dupont_df <- data %>%
# Chuẩn hoá tên biến về 1 chuẩn dùng trong các mục 2.4.x
transmute(
Nam,
# Biên lợi nhuận ròng (đưa về tỷ lệ 0–1 để hồi quy; vẽ sẽ format %)
NPM = BienLoiNhuanRong_Nam / 100,
# Hiệu suất sử dụng tài sản (vòng quay TAT) – giữ nguyên hệ số
TAT = TAT_Nam,
# Đòn bẩy tài chính
FL = FL_Nam,
# ROA & ROE đưa về tỷ lệ 0–1 để đồng nhất khi hồi quy & format khi vẽ
ROA = ROA_Nam / 100,
ROE_ThucTe = ROE_Nam / 100
) %>%
mutate(
ROE_DuPont = NPM * TAT * FL
)# Tạo bộ dữ liệu cho 2.4.2
d_profit <- dupont_df %>% dplyr::select(Nam, NPM, ROA)
# Loại năm outlier 2019 cho mẫu Clean (nếu không có 2019, dòng này vẫn an toàn)
d_profit_clean <- d_profit %>% filter(Nam != 2019)
# Hồi quy tuyến tính
lm_full <- lm(NPM ~ ROA, data = d_profit)
lm_clean <- lm(NPM ~ ROA, data = d_profit_clean)
# Bảng kết quả gọn
res_full <- summary(lm_full)
res_clean <- summary(lm_clean)
result_table_242 <- tibble::tibble(
Mẫu = c("Full", "Clean"),
n = c(nrow(d_profit), nrow(d_profit_clean)),
R2 = c(res_full$r.squared, res_clean$r.squared),
Adj_R2 = c(res_full$adj.r.squared, res_clean$adj.r.squared),
Slope = c(coef(lm_full)[2], coef(lm_clean)[2]),
`p-value(Slope)` = c(res_full$coefficients[2,4], res_clean$coefficients[2,4]),
Intercept= c(coef(lm_full)[1], coef(lm_clean)[1])
)
print(result_table_242)# A tibble: 2 × 7
Mẫu n R2 Adj_R2 Slope `p-value(Slope)` Intercept
<chr> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Full 11 0.0525 -0.0528 0.00184 0.498 0.127
2 Clean 10 0.930 0.921 0.718 0.00000670 0.0218
Kết quả mô hình:
| Mẫu | n | R² | Adj-R² | Slope | p-value(Slope) | Intercept |
|---|---|---|---|---|---|---|
| Full | 11 | 0.0525 | -0.0528 | 0.00184 | 0.4979 | 0.1267 |
| Clean | 10 | 0.9302 | 0.9214 | 0.7176 | 0.000067 | 0.0218 |
Nhận xét chi tiết
Ý nghĩa kinh tế
Tổng kết
| Nhận xét | Diễn giải |
|---|---|
| Mối quan hệ | Tuyến tính, chặt chẽ và có ý nghĩa thống kê cao trong mẫu Clean |
| Hệ số dốc (Slope) | 0.72 → ROA tăng 1% → NPM tăng 0.72% |
| Ý nghĩa | NPM phản ánh gần như trực tiếp hiệu quả hoạt động (ROA) của doanh nghiệp |
| Kết luận | Sau khi loại bỏ năm 2019, mô hình trở nên ổn định và phù hợp, khẳng định ROA là yếu tố quyết định biên lợi nhuận ròng của PVGas |
ggplot() +
# Điểm full
geom_point(data = d_profit,
aes(x = ROA, y = NPM),
size = 3, alpha = 0.85, color = "#264C99") +
# Hồi quy full
geom_smooth(data = d_profit,
aes(x = ROA, y = NPM),
method = "lm", se = TRUE,
color = "#264C99", fill = "#264C99",
alpha = 0.15, linewidth = 1) +
# Hồi quy clean (loại 2019)
geom_smooth(data = d_profit_clean,
aes(x = ROA, y = NPM),
method = "lm", se = TRUE,
linetype = "dashed",
color = "#D55E00", fill = "#D55E00",
alpha = 0.15, linewidth = 1) +
# Đường y = x để tham chiếu “NPM ~ ROA”
geom_abline(slope = 1, intercept = 0, linetype = "dotted", color = "grey40") +
# Nhãn R2
annotate("text", x = min(d_profit$ROA, na.rm=TRUE),
y = max(d_profit$NPM, na.rm=TRUE),
hjust = 0, vjust = 1.2,
label = paste0("R² Full = ", round(res_full$r.squared, 3)),
color = "#264C99", fontface = "bold") +
annotate("text", x = min(d_profit$ROA, na.rm=TRUE),
y = max(d_profit$NPM, na.rm=TRUE) - 0.03,
hjust = 0, vjust = 1.2,
label = paste0("R² Clean = ", round(res_clean$r.squared, 3)),
color = "#D55E00", fontface = "bold") +
# Gán nhãn outlier (nếu có 2019)
{
if (any(d_profit$Nam == 2019)) {
annotate("text",
x = d_profit$ROA[d_profit$Nam == 2019],
y = d_profit$NPM[d_profit$Nam == 2019] + 0.02,
label = "2019", color = "red", fontface = "bold")
}
} +
scale_x_continuous(labels = label_percent(accuracy = 1)) +
scale_y_continuous(labels = label_percent(accuracy = 1)) +
labs(
title = "Biểu đồ 2.4.2a – Tương quan: Biên lợi nhuận ròng (NPM) ~ ROA (Full vs Clean)",
subtitle = "Đường liền: Full | Đường gạch: Clean (loại 2019) | Đường chấm: y = x",
x = "ROA (%)", y = "Biên lợi nhuận ròng (NPM, %)"
) +
theme_minimal(base_size = 10) +
theme(plot.title = element_text(face = "bold", hjust = 0.5),
panel.grid.minor = element_blank())Nhận xét: Biểu đồ 2.4.2a – Tương quan: Biên lợi nhuận ròng (NPM) ~ ROA (Full vs Clean)
Biểu đồ thể hiện mối quan hệ tuyến tính giữa Biên lợi nhuận
ròng (NPM) và Hiệu suất sử dụng tài sản (ROA)
qua hai trường hợp:
- Đường liền (Full): mô hình sử dụng toàn bộ giai đoạn
2014–2024.
- Đường gạch (Clean): mô hình loại bỏ năm 2019 – năm có
ROA bất thường (>100%).
- Đường chấm: đường y = x, minh họa mức tỷ lệ 1:1 giữa
NPM và ROA.
Tổng quan trực quan:
Điểm dữ liệu năm 2019 (màu đỏ) nằm xa
hoàn toàn khỏi cụm chính, cho thấy đây là outlier rõ
ràng, làm nghiêng đường hồi quy Full.
→ Điều này khiến đường Full (màu xanh liền) gần như
phẳng, biểu thị mối quan hệ yếu (R² Full =
0.053).
Ngược lại, đường Clean (màu cam gạch) cho thấy
xu hướng tăng rõ rệt, khi ROA tăng → NPM cũng
tăng tương ứng.
→ Mô hình Clean đạt R² = 0.93, thể hiện mối
tương quan tuyến tính rất mạnh giữa hai biến.
Vùng màu xanh nhạt quanh đường hồi quy Full thể
hiện khoảng tin cậy 95%, khá rộng → mô hình Full thiếu ổn
định và có sai số cao.
Trong khi đó, mô hình Clean có độ tin cậy cao hơn, do
các điểm dữ liệu tập trung và nhất quán hơn.
Diễn giải kinh tế:
Kết luận từ biểu đồ:
| Mẫu | Đặc điểm | Ý nghĩa |
|---|---|---|
| Full | Đường phẳng, R² = 0.05 | Mối quan hệ yếu, bị nhiễu bởi outlier (2019) |
| Clean | Đường dốc tăng mạnh, R² = 0.93 | Mối quan hệ chặt chẽ, phản ánh đúng hiệu quả hoạt động nội tại |
| Điểm 2019 | Lệch xa cụm chính | Biểu hiện của biến động bất thường (không thuộc xu hướng chung) |
# Dữ liệu gốc
df_temp <- data %>%
# Đảm bảo tất cả các biến phái sinh được tính toán lại với tên CHUẨN
mutate(
# Tính lại các biến thị trường
P_E_CuoiNam = Gia_DongCua_CuoiNam / EPS,
VonHoa_TyVND = (Gia_DongCua_CuoiNam * SL_CoPhieu_LuuHanh) / 1e9,
# Tính lại các tỷ số
ROE_Nam = (LoiNhuanSauThue / VonChuSoHuu) * 100,
ROA_Nam = (LoiNhuanSauThue / TongTaiSan) * 100,
BienLoiNhuanRong_Nam = (LoiNhuanSauThue / DoanhThu) * 100,
FL_Nam = TongTaiSan / VonChuSoHuu,
TAT_Nam = DoanhThu / TongTaiSan,
# Cờ loại trừ outlier
flag_roa_abnormal = dplyr::case_when(ROA_Nam > 100 ~ TRUE, TRUE ~ FALSE)
)
# Lọc dữ liệu (Đã lọc outlier ROA > 100%)
df_clean <- df_temp %>%
dplyr::filter(flag_roa_abnormal == FALSE)
# 1. TẠO: DataFrame vars_corr
# A. Chọn các biến cần thiết cho ma trận tương quan (Hiệu suất & Định giá)
vars_raw <- df_clean %>%
select(ROE_Nam, ROA_Nam, BienLoiNhuanRong_Nam, TAT_Nam, FL_Nam, EPS, P_E_CuoiNam)
# B. Đổi tên Biến cho Biểu đồ
vars_corr <- vars_raw %>%
rename(
ROE = ROE_Nam,
ROA = ROA_Nam,
`Biên LNR` = BienLoiNhuanRong_Nam,
`Hiệu suất TS` = TAT_Nam,
`Đòn bẩy TC` = FL_Nam,
PE = P_E_CuoiNam
)
# 2. VẼ BIỂU ĐỒ 2.4.3a – Heatmap ma trận tương quan
vars_short_names <- vars_corr %>%
rename(
NPM = `Biên LNR`,
TAT = `Hiệu suất TS`,
FL = `Đòn bẩy TC`
)
corr_matrix_short <- round(cor(vars_short_names, use = "pairwise.complete.obs"), 3)
corr_long <- reshape2::melt(corr_matrix_short)
ggplot(corr_long, aes(x = Var1, y = Var2, fill = value)) +
geom_tile(color = "white") +
geom_text(aes(label = sprintf("%.2f", value)), size = 3.5, color = "black") + # Giảm size chữ
scale_fill_gradient2(low = "#B2182B", mid = "white", high = "#2166AC",
midpoint = 0, limit = c(-1, 1),
name = "Hệ số\nTương quan") +
labs(
title = "Biểu đồ 2.4.3a – Ma trận tương quan Pearson giữa các chỉ tiêu tài chính",
subtitle = "Mẫu đã lọc Outlier (n=10): Mối quan hệ giữa Hiệu suất & Định giá",
x = NULL, y = NULL
) +
theme_minimal(base_size = 10) +
theme(
axis.text.x = element_text(angle = 45, hjust = 1, size = 10), # Giảm size tên trục X
axis.text.y = element_text(size = 10),
plot.title = element_text(face = "bold", hjust = 0.5),
legend.position = "right"
)# 3. VẼ BIỂU ĐỒ 2.4.3b – Scatter Matrix
GGally::ggpairs(
vars_corr,
title = "Biểu đồ 2.4.3b – Ma trận Scatter giữa các biến Hiệu suất và Định giá",
# SỬA LỖI: Gọi rõ GGally::wrap()
upper = list(continuous = GGally::wrap("cor", size = 3.5, color = "darkred")),
lower = list(continuous = GGally::wrap("points", alpha = 0.6, size = 1.5, color = "#0072B2")),
diag = list(continuous = GGally::wrap("densityDiag", fill = "#56B4E9", alpha = 0.6))
) +
theme_bw(base_size = 8) +
theme(plot.title = element_text(face = "bold", hjust = 0.5, size = 12))Biểu đồ 2.4.3a – Ma trận tương quan Pearson giữa các chỉ tiêu tài chính
Biểu đồ thể hiện mức độ tương quan tuyến tính
(Pearson) giữa các chỉ tiêu tài chính trọng yếu, sau khi
đã loại bỏ outlier (n = 10).
Các nhóm biến bao gồm:
- Nhóm Hiệu suất & Sinh lời: ROA, ROE, Biên lợi
nhuận ròng (NPM), Hiệu suất tài sản (TAT), Đòn bẩy tài chính (FL)
- Nhóm Định giá & Lợi nhuận thị trường: EPS,
P/E
1. Mối quan hệ trong nhóm Hiệu suất & Sinh lời
ROA, ROE và NPM có mức tương quan gần
như tuyệt đối (r ≈ 0.96–1.00) → cho thấy hiệu quả hoạt
động nội tại là nhân tố quyết định trực tiếp lợi nhuận ròng và tỷ suất
sinh lời vốn chủ.
→ Điều này củng cố kết quả các hồi quy trước (ROE ~ ROA, NPM ~ ROA) rằng
cấu trúc sinh lời của PVGas chủ yếu đến từ hoạt động kinh doanh
cốt lõi, không phụ thuộc vào đòn bẩy.
TAT (Hiệu suất tài sản) có tương quan
trung bình đến mạnh với ROA và ROE (r ≈
0.71–0.73), nghĩa là khả năng quay vòng tài sản
đóng vai trò tích cực trong việc nâng cao lợi nhuận.
→ Tuy nhiên, hệ số < 1 cho thấy ngoài hiệu suất tài sản, biên
lợi nhuận ròng (NPM) vẫn là yếu tố chi phối chính của
ROA.
FL (Đòn bẩy tài chính) có tương quan yếu – trung bình (r ≈ 0.34–0.42) với ROA và ROE, chứng tỏ đòn bẩy không phải yếu tố chính tạo ra lợi nhuận, phù hợp với đặc điểm của PVGas – doanh nghiệp có vốn chủ sở hữu lớn và nợ vay thấp.
2. Mối quan hệ giữa Hiệu suất và Định giá
EPS có tương quan tương đối cao với nhóm
hiệu suất (r ≈ 0.66–0.67 với ROA, ROE, TAT) → phản ánh
lợi nhuận kế toán di chuyển cùng chiều với hiệu quả hoạt
động.
Tuy nhiên, mức tương quan chưa quá mạnh, cho thấy thị trường
chưa phản ánh đầy đủ hiệu quả hoạt động vào EPS.
P/E (Price-to-Earnings ratio) có tương
quan âm khá rõ với ROA, ROE, EPS (r ≈ -0.57 đến -0.59) → khi
hiệu quả sinh lời tăng, P/E có xu hướng giảm, nghĩa là
cổ phiếu được định giá rẻ hơn tương đối so với lợi nhuận tạo
ra.
→ Đây là dấu hiệu thận trọng của thị trường, cho thấy
nhà đầu tư có thể chưa định giá đúng tiềm năng nội tại
của PVGas, hoặc giá cổ phiếu biến động theo yếu tố vĩ mô hơn là
lợi nhuận thực tế.
3. Nhận xét tổng thể
| Nhóm chỉ tiêu | Tương quan nội bộ | Tương quan với P/E | Nhận định chính |
|---|---|---|---|
| ROA – ROE – NPM | R ≈ 0.96–1.00 | Âm (≈ -0.57) | Hiệu suất nội tại cao, phản ánh cùng chiều với nhau; P/E giảm khi hiệu quả tăng. |
| TAT (Hiệu suất tài sản) | Trung bình – mạnh (≈ 0.7) | Âm nhẹ (≈ -0.38) | Quay vòng tài sản cao giúp tăng sinh lời, nhưng không ảnh hưởng trực tiếp đến định giá. |
| FL (Đòn bẩy tài chính) | Yếu (≈ 0.34- 0.42) | Gần như không đáng kể | Đòn bẩy thấp, không đóng vai trò chính trong sinh lời hay định giá. |
| EPS | Dương với hiệu suất (≈ 0.66–0.67) | Âm với P/E (≈ -0.59) | Lợi nhuận kế toán tăng cùng hiệu quả hoạt động, nhưng thị trường chưa phản ánh tương xứng. |
Kết luận từ ma trận tương quan
PVGas có cấu trúc sinh lời nội sinh vững chắc:
các chỉ tiêu hiệu quả (ROA, ROE, NPM) đồng biến mạnh → cho thấy doanh
nghiệp hoạt động hiệu quả và ổn định.
Tác động của đòn bẩy tài chính thấp, phù hợp với
mô hình doanh nghiệp vốn hóa lớn và ít vay nợ.
Tương quan âm giữa P/E và nhóm hiệu suất – EPS hàm ý thị trường chưa định giá đúng năng lực lợi nhuận, hoặc phản ứng chậm với kết quả tài chính.
Biểu đồ 2.4.3a cho thấy PVGas là doanh nghiệp có hiệu quả sinh lời cao và ổn định, song thị trường chưa phản ánh đầy đủ giá trị nội tại vào định giá cổ phiếu (P/E), mở ra tiềm năng định giá lại (re-rating) trong tương lai.
library(tidyverse)
library(ggplot2)
library(broom)
library(scales)
# Đổi tên DataFrame
analysis_data <- data %>%
arrange(Nam) %>%
mutate(
# 1. TÍNH LẠI CÁC BIẾN PHÁI SINH TRỌNG YẾU ĐỂ ĐẢM BẢO CHÚNG TỒN TẠI VÀ CHÍNH XÁC
P_E_CuoiNam = Gia_DongCua_CuoiNam / EPS, # Tính lại P/E
ROE_Nam = (LoiNhuanSauThue / VonChuSoHuu) * 100, # Tính lại ROE
# 2. CHUẨN HÓA TÊN BIẾN
LNST_YoY = (LoiNhuanSauThue / dplyr::lag(LoiNhuanSauThue) - 1) * 100,
Gia = Gia_DongCua_CuoiNam,
ROE = ROE_Nam,
PE = P_E_CuoiNam
)
# 2.4.4a. Biểu đồ xu hướng EPS theo thời gian
ggplot(analysis_data, aes(x = Nam, y = EPS)) +
geom_line(linewidth = 1.2, color = "#0072B2") +
geom_point(size = 3, color = "#0072B2") +
geom_smooth(method = "lm", se = FALSE, linetype = "dashed", color = "grey40") +
labs(
title = "Biểu đồ 2.4.4a – Xu hướng EPS qua các năm",
x = "Năm", y = "EPS (đồng/cp)"
) +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(face = "bold", hjust = 0.5))# 2.4.4b. Hồi quy Giá ~ EPS (Full & Clean)
lm_eps_full <- lm(Gia ~ EPS, data = analysis_data)
analysis_data_clean <- analysis_data %>% filter(Nam != 2019)
lm_eps_clean <- lm(Gia ~ EPS, data = analysis_data_clean)
result_eps <- tibble(
Mẫu = c("Full", "Clean"),
R2 = c(summary(lm_eps_full)$r.squared, summary(lm_eps_clean)$r.squared),
Adj_R2 = c(summary(lm_eps_full)$adj.r.squared, summary(lm_eps_clean)$adj.r.squared),
Slope = c(coef(lm_eps_full)[2], coef(lm_eps_clean)[2]),
p_value = c(summary(lm_eps_full)$coefficients[2,4], summary(lm_eps_clean)$coefficients[2,4]),
Intercept = c(coef(lm_eps_full)[1], coef(lm_eps_clean)[1])
)
print(result_eps)# A tibble: 2 × 6
Mẫu R2 Adj_R2 Slope p_value Intercept
<chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Full 0.00636 -0.104 -1.04 0.816 57749.
2 Clean 0.0105 -0.113 -1.34 0.778 58712.
# Biểu đồ 2.4.4b – Scatter: Giá ~ EPS
ggplot() +
geom_point(data = analysis_data, aes(x = EPS, y = Gia), color = "#0072B2", size = 3, alpha = 0.8) +
geom_smooth(data = analysis_data, aes(x = EPS, y = Gia), method = "lm", color = "#0072B2", se = TRUE, fill = "#0072B2", alpha = 0.15) +
geom_smooth(data = analysis_data_clean, aes(x = EPS, y = Gia), method = "lm", color = "#D55E00", se = TRUE, fill = "#D55E00", alpha = 0.15, linetype = "dashed") +
labs(
title = "Biểu đồ 2.4.4b – Hồi quy Giá cổ phiếu ~ EPS (Full vs Clean)",
x = "EPS (đồng/cp)",
y = "Giá cổ phiếu (đồng)"
) +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(face = "bold", hjust = 0.5))
Call:
lm(formula = ROE ~ PE, data = analysis_data)
Residuals:
Min 1Q Median 3Q Max
-13.99 -2.98 2.49 3.10 11.15
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 32.888 6.315 5.21 0.00056 ***
PE -1.234 0.593 -2.08 0.06730 .
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 7.57 on 9 degrees of freedom
Multiple R-squared: 0.325, Adjusted R-squared: 0.25
F-statistic: 4.33 on 1 and 9 DF, p-value: 0.0673
ggplot(analysis_data, aes(x = PE, y = ROE)) +
geom_point(size = 3, color = "#009E73", alpha = 0.8) +
geom_smooth(method = "lm", se = TRUE, color = "#009E73", fill = "#009E73", alpha = 0.2) +
scale_y_continuous(labels = label_percent(scale = 1)) +
labs(
title = "Biểu đồ 2.4.4c – Hồi quy ROE ~ P/E",
x = "Hệ số P/E",
y = "ROE (%)"
) +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(face = "bold", hjust = 0.5))# 2.4.4d. Hồi quy P/E ~ Tăng trưởng LNST YoY
lm_pe_growth <- lm(PE ~ LNST_YoY, data = analysis_data)
summary(lm_pe_growth)
Call:
lm(formula = PE ~ LNST_YoY, data = analysis_data)
Residuals:
Min 1Q Median 3Q Max
-5.714 -1.230 -0.135 2.620 4.773
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 10.00864 1.25286 7.99 0.000044 ***
LNST_YoY 0.00452 0.00389 1.16 0.28
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 3.78 on 8 degrees of freedom
(1 observation deleted due to missingness)
Multiple R-squared: 0.144, Adjusted R-squared: 0.0373
F-statistic: 1.35 on 1 and 8 DF, p-value: 0.279
ggplot(analysis_data, aes(x = LNST_YoY, y = PE)) +
geom_point(size = 3, color = "#E69F00", alpha = 0.8) +
geom_smooth(method = "lm", se = TRUE, color = "#E69F00", fill = "#E69F00", alpha = 0.2) +
labs(
title = "Biểu đồ 2.4.4d – Hồi quy P/E ~ Tăng trưởng LNST (YoY)",
x = "Tăng trưởng LNST YoY (%)",
y = "Hệ số P/E"
) +
theme_minimal(base_size = 13) +
theme(plot.title = element_text(face = "bold", hjust = 0.5))Nhận xét tổng quan các biểu đồ
Biểu đồ 2.4.4a – Xu hướng EPS qua các năm
Biểu đồ 2.4.4b – Hồi quy Giá cổ phiếu ~ EPS (Full vs Clean)
Biểu đồ 2.4.4c – Hồi quy ROE ~ P/E
Biểu đồ 2.4.4d – Hồi quy P/E ~ Tăng trưởng LNST (YoY)
Tổng kết nhóm biểu đồ 2.4.4
| Biểu đồ | Mối quan hệ | Kết luận chính |
|---|---|---|
| 2.4.4a – EPS theo năm | Biến động chu kỳ, xu hướng giảm nhẹ | EPS không ổn định, chịu ảnh hưởng yếu tố bên ngoài |
| 2.4.4b – Giá ~ EPS | Gần như không có (Slope âm nhẹ) | Giá cổ phiếu không phản ứng với EPS ngắn hạn |
| 2.4.4c – ROE ~ P/E | Tương quan âm | P/E thấp khi ROE cao → thị trường định giá ngược chu kỳ |
| 2.4.4d – P/E ~ Tăng trưởng LNST (YoY) | Tương quan dương yếu | P/E tăng khi tăng trưởng lợi nhuận cao, nhưng không ổn định |
Kết luận tổng quát
Từ chuỗi phân tích hồi quy, tương quan và mô phỏng trong các mục 2.4.1–2.4.4, có thể tổng hợp các phát hiện chính như sau:
1. Hiệu suất sinh lời (ROE, ROA, NPM, TAT, FL)
2. Quan hệ giữa ROA và NPM
3. Tương quan đa biến (Hiệu suất & Định giá)
4. EPS, tăng trưởng và định giá thị trường
library(tidyverse)
library(ggplot2)
library(zoo)
library(scales)
df_roll <- data %>%
rename(
LNST = LoiNhuanSauThue,
Gia = Gia_DongCua_CuoiNam,
ROE = ROE_Nam
) %>%
arrange(Nam)
# 1. Tính Rolling Correlation LNST ~ Doanh thu
roll_corr_LNST_DT <- df_roll %>%
mutate(Roll_Corr_LNST_DT = rollapplyr(
data = cbind(LNST, DoanhThu),
width = 3,
FUN = function(x) cor(x[,1], x[,2], use = "complete.obs"),
by.column = FALSE,
fill = NA
))
# 2. Tính Rolling Correlation ROE ~ Giá cổ phiếu
roll_corr_ROE_Gia <- df_roll %>%
mutate(Roll_Corr_ROE_Gia = rollapplyr(
data = cbind(ROE, Gia),
width = 3,
FUN = function(x) cor(x[,1], x[,2], use = "complete.obs"),
by.column = FALSE,
fill = NA
))
# 3. Gộp hai chuỗi Rolling Correlation
roll_corr_all <- df_roll %>%
select(Nam) %>%
left_join(roll_corr_LNST_DT %>% select(Nam, Roll_Corr_LNST_DT), by = "Nam") %>%
left_join(roll_corr_ROE_Gia %>% select(Nam, Roll_Corr_ROE_Gia), by = "Nam") %>%
pivot_longer(cols = starts_with("Roll_Corr"), names_to = "MốiQuanHe", values_to = "Corr") %>%
mutate(
# SỬA LỖI ĐÁNH MÁY: MốiQuanHe = recode(MốiQuanHe, ...)
MốiQuanHe = recode(MốiQuanHe,
"Roll_Corr_LNST_DT" = "LNST ~ Doanh thu",
"Roll_Corr_ROE_Gia" = "ROE ~ Giá cổ phiếu")
)
# 4. Biểu đồ 2.5.1a – Rolling Correlation
ggplot(roll_corr_all, aes(x = Nam, y = Corr, color = MốiQuanHe, group = MốiQuanHe)) +
geom_line(linewidth = 1.2) +
geom_point(size = 2.5) +
geom_hline(yintercept = 0, linetype = "dashed", color = "grey40") +
scale_color_manual(values = c("#0072B2", "#D55E00")) +
scale_y_continuous(labels = label_number(accuracy = 0.1), limits = c(-1, 1)) +
labs(
title = "Biểu đồ 2.5.1a – Rolling Correlation (Độ bền theo thời gian)",
subtitle = "Cửa sổ trượt 3 năm – So sánh mối quan hệ LNST~Doanh thu và ROE~Giá cổ phiếu",
x = "Năm",
y = "Hệ số tương quan (r)",
color = "Mối quan hệ"
) +
theme_minimal(base_size = 10) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
legend.position = "bottom"
)Nhận xét Biểu đồ 2.5.1a: Rolling Correlation (Độ bền theo thời gian)
Tổng quan theo giai đoạn
Giai đoạn 2015–2018:
Hệ số tương quan của LNST–Doanh thu duy trì r ≈
0.95–1.0, phản ánh sự ổn định gần như tuyệt
đối giữa tăng trưởng doanh thu và lợi nhuận.
ROE–Giá cổ phiếu tăng dần từ r ≈ 0.4 lên
0.9, cho thấy niềm tin thị trường dần cải
thiện đối với hiệu quả sinh lời của doanh nghiệp.
Năm 2019:
Xuất hiện biến động mạnh – hệ số ROE–Giá cổ
phiếu chuyển sang âm (-0.5), trong khi LNST–Doanh thu
vẫn cao (~1.0).
Đây là hiện tượng nhiễu do outlier 2019 (ROA >
100%), khiến thị trường mất tương quan tạm thời với
hiệu quả kế toán.
Giai đoạn 2020–2023:
Mối quan hệ ROE–Giá cổ phiếu phục hồi mạnh mẽ, đạt lại
r ≈ 0.8–1.0, phản ánh niềm tin nhà đầu tư quay
trở lại.
LNST–Doanh thu vẫn ổn định đến 2022, nhưng giảm
nhẹ ở 2023 (r ~0.2–0.3) – dấu hiệu cho thấy biên lợi
nhuận đang chịu áp lực từ chi phí và yếu tố thị
trường.
Tổng kết ý nghĩa
| Mối quan hệ | Giai đoạn ổn định | Giai đoạn biến động | Nhận định |
|---|---|---|---|
| LNST ~ Doanh thu | 2014–2022 (r ≈ 0.95–1.0) | 2023 (r ~0.2) | Hoạt động kinh doanh ổn định, chỉ suy yếu nhẹ do biến động chu kỳ. |
| ROE ~ Giá cổ phiếu | 2015–2018, 2021–2023 (r ≈ 0.8–1.0) | 2019–2020 (r âm) | Thị trường định giá lệch do outlier 2019, sau đó phục hồi mạnh. |
Kết luận
library(tidyverse)
library(ggplot2)
library(scales)
library(broom)
# 1. Chuẩn hóa DataFrame và tên biến
df_cook <- data %>%
rename(
Gia = Gia_DongCua_CuoiNam,
LNST = LoiNhuanSauThue
) %>%
# Loại bỏ các hàng có NA (cho mô hình hồi quy, ví dụ: năm 2014 của YoY)
filter(!is.na(Gia), !is.na(EPS), !is.na(LNST), !is.na(DoanhThu))
# 2. Hồi quy Giá ~ EPS
lm_gia_eps <- lm(Gia ~ EPS, data = df_cook)
cook_gia_eps <- broom::augment(lm_gia_eps) %>%
mutate(CooksD = .cooksd) %>%
bind_cols(Nam = df_cook$Nam) %>%
select(Nam, CooksD)
# 3. Hồi quy LNST ~ Doanh thu
lm_lnst_dt <- lm(LNST ~ DoanhThu, data = df_cook)
cook_lnst_dt <- broom::augment(lm_lnst_dt) %>%
mutate(CooksD = .cooksd) %>%
bind_cols(Nam = df_cook$Nam) %>%
select(Nam, CooksD)
# 4. Chuẩn hóa & gộp kết quả
# Tính ngưỡng Cook's D: 4/n
n_rows <- nrow(df_cook)
nguong_cooks_d <- 4 / n_rows
cook_all <- cook_gia_eps %>%
rename(Cook_Gia_EPS = CooksD) %>%
left_join(cook_lnst_dt %>% rename(Cook_LNST_DT = CooksD), by = "Nam") %>%
pivot_longer(cols = starts_with("Cook_"), names_to = "MôHình", values_to = "CooksD") %>%
mutate(
MôHình = recode(MôHình,
"Cook_Gia_EPS" = "Giá ~ EPS",
"Cook_LNST_DT" = "LNST ~ Doanh thu"),
Ngưỡng = nguong_cooks_d # Sử dụng ngưỡng đã tính
)
# 5. Biểu đồ 2.5.2a – Cook’s Distance
ggplot(cook_all, aes(x = factor(Nam), y = CooksD, fill = MôHình)) +
geom_col(position = "dodge", alpha = 0.8) +
geom_hline(aes(yintercept = Ngưỡng), color = "red", linetype = "dashed", linewidth = 1) +
geom_text(
# Chỉ đánh dấu các năm vượt ngưỡng
aes(label = ifelse(CooksD > Ngưỡng, Nam, "")),
vjust = -0.5, size = 3, fontface = "bold", color = "black"
) +
scale_fill_manual(values = c("#0072B2", "#E69F00")) +
scale_y_continuous(labels = label_number(accuracy = 0.001)) +
labs(
title = "Biểu đồ 2.5.2a – Phân tích Ảnh hưởng Outlier theo Cook’s Distance",
subtitle = paste0("Ngưỡng phát hiện: Cook’s D > 4/n (", round(nguong_cooks_d, 3), ")"),
x = "Năm",
y = "Giá trị Cook’s D",
fill = "Mô hình"
) +
theme_minimal(base_size = 10) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
legend.position = "bottom"
)# 6. Bảng Top năm có ảnh hưởng mạnh nhất
cook_top <- cook_all %>%
group_by(MôHình) %>%
slice_max(order_by = CooksD, n = 3) %>%
arrange(MôHình, desc(CooksD))
print(cook_top)# A tibble: 6 × 4
# Groups: MôHình [2]
Nam MôHình CooksD Ngưỡng
<dbl> <chr> <dbl> <dbl>
1 2022 Giá ~ EPS 0.663 0.364
2 2015 Giá ~ EPS 0.505 0.364
3 2014 Giá ~ EPS 0.203 0.364
4 2020 LNST ~ Doanh thu 0.568 0.364
5 2024 LNST ~ Doanh thu 0.488 0.364
6 2014 LNST ~ Doanh thu 0.117 0.364
Nhận xét Biểu đồ 2.5.2a: Phân tích Ảnh hưởng Outlier theo Cook’s Distance
Ý nghĩa chỉ số Cook’s D
Cook’s Distance đo lường mức độ ảnh hưởng của từng quan sát
đến mô hình hồi quy.
- Giá trị Cook’s D > 4/n (≈ 0.364) được xem là
điểm có ảnh hưởng mạnh (influential point).
- Các năm vượt ngưỡng này có thể khiến hệ số hồi quy và R² bị
méo lệch, cần xem xét loại trừ hoặc kiểm định lại mô hình với
mẫu “Clean”.
Bảng tổng hợp kết quả
Từ bảng và biểu đồ:
| Năm | Mô hình | Cook’s D | So với ngưỡng | Nhận định |
|---|---|---|---|---|
| 2015 | Giá ~ EPS | 0.505 | > 0.364 | Ảnh hưởng mạnh – biến động EPS cao và thị trường phản ứng lệch. |
| 2022 | Giá ~ EPS | 0.663 | > 0.364 | Ảnh hưởng mạnh nhất – giá cổ phiếu tăng vọt không tương ứng với EPS. |
| 2014 | Giá ~ EPS | 0.203 | < 0.364 | Ảnh hưởng nhỏ, chấp nhận được. |
| 2020 | LNST ~ Doanh thu | 0.568 | > 0.364 | Ảnh hưởng mạnh – lợi nhuận bị co hẹp do chi phí tăng, lệch quy mô doanh thu. |
| 2024 | LNST ~ Doanh thu | 0.488 | > 0.364 | Ảnh hưởng mạnh – có khả năng do yếu tố chu kỳ hoặc thay đổi giá khí đầu ra. |
| 2014 | LNST ~ Doanh thu | 0.117 | < 0.364 | Không ảnh hưởng đáng kể. |
Diễn giải theo từng nhóm mô hình
Giá ~ EPS:
Các năm 2015 và 2022 vượt ngưỡng mạnh
nhất, phản ánh hiện tượng thị trường định giá lệch so với lợi
nhuận kế toán.
→ Cần lưu ý đây là các giai đoạn biến động thị trường năng lượng (giá
dầu và khí tự nhiên tăng mạnh), khiến giá cổ phiếu biến động
ngoài quy luật EPS.
LNST ~ Doanh thu:
Hai năm 2020 và 2024 vượt ngưỡng rõ
rệt, tương ứng với các biến động lớn trong biên lợi
nhuận (chi phí vận hành, giá đầu vào, sản lượng khí).
→ Điều này cho thấy mô hình bị tác động tạm thời bởi yếu tố
ngoài quy mô doanh thu, chứ không phải do sai lệch cấu
trúc.
Kết luận tổng quát
library(tidyverse)
library(ggplot2)
library(reshape2)
library(scales)
df_analysis <- data %>%
rename(
ROE = ROE_Nam,
ROA = ROA_Nam,
`Biên LNR` = BienLoiNhuanRong_Nam, # Tên có khoảng trắng
`Hiệu suất TS` = TAT_Nam, # Tên có khoảng trắng
EPS = EPS,
Gia = Gia_DongCua_CuoiNam
)
# 1. Tách dữ liệu thành hai pha
phase_pre2016 <- df_analysis %>% filter(Nam <= 2016)
phase_post2016 <- df_analysis %>% filter(Nam > 2016)
# 2. Chọn nhóm biến hiệu suất và định giá
vars_eff <- c("ROE", "ROA", "Biên LNR", "Hiệu suất TS", "EPS", "Gia")
# 3. Tính ma trận tương quan cho từng pha
corr_pre <- cor(phase_pre2016[vars_eff], use = "pairwise.complete.obs", method = "pearson")
corr_post <- cor(phase_post2016[vars_eff], use = "pairwise.complete.obs", method = "pearson")
# 4. Chuyển sang dạng long để vẽ heatmap
corr_pre_long <- melt(corr_pre) %>%
mutate(Pha = "Trước 2016 (2014–2016)")
corr_post_long <- melt(corr_post) %>%
mutate(Pha = "Sau 2016 (2017–2024)")
corr_all_long <- bind_rows(corr_pre_long, corr_post_long)
# 5. Biểu đồ 2.5.3a – Heatmap So sánh Chu kỳ
ggplot(corr_all_long, aes(x = Var1, y = Var2, fill = value)) +
geom_tile(color = "white") +
geom_text(aes(label = sprintf("%.2f", value)), size = 3, color = "black") +
scale_fill_gradient2(
low = "#D55E00", mid = "white", high = "#0072B2",
midpoint = 0, limits = c(-1, 1),
name = "Hệ số\nTương quan (r)"
) +
facet_wrap(~ Pha) +
labs(
title = "Biểu đồ 2.5.3a – So sánh Tương quan theo Pha Chu kỳ (Trước & Sau 2016)",
subtitle = "So sánh độ mạnh yếu của mối quan hệ giữa các biến hiệu suất và định giá",
x = "Biến 1",
y = "Biến 2"
) +
theme_minimal(base_size = 10) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
strip.text = element_text(face = "bold", size = 12),
axis.text.x = element_text(angle = 45, hjust = 1),
# SỬA: Đảm bảo có đủ lề để tên biến hiển thị (Mục tiêu khắc phục vấn đề hiển thị)
plot.margin = unit(c(1, 1, 1, 1), "cm")
)
Nhận xét Biểu đồ 2.5.3a: So sánh Tương quan theo Pha Chu kỳ
(Trước & Sau 2016)
Mục tiêu phân tích
Biểu đồ thể hiện sự thay đổi cấu trúc tương quan giữa các
biến hiệu suất (ROE, ROA, Biên LNR, Hiệu suất TS) và
các biến định giá thị trường (EPS, Giá cổ phiếu)
qua hai pha chu kỳ: - Trước 2016
(2014–2016): giai đoạn thị trường khí – dầu còn ổn định, doanh
nghiệp có tính tuyến tính cao giữa các chỉ tiêu.
- Sau 2016 (2017–2024): giai đoạn tái cơ cấu thị trường
khí, giá năng lượng biến động mạnh và chính sách tài chính thay đổi.
Diễn biến tương quan theo từng pha chu kì
Pha chu kì trước 2016 (2014–2016)
Pha chu kì sau 2016 (2017–2024)
Kết luận
Phân tích toàn bộ giai đoạn 2014–2024 cho thấy hiệu suất tài chính, cấu trúc sinh lời và cơ chế định giá của PVGas (GAS) có sự ổn định nội tại cao, nhưng mối liên hệ với thị trường đã biến đổi đáng kể theo chu kỳ năng lượng.Kết luận được chia thành những nhận định chung sau đây:
1. Hiệu suất sinh lời và cấu trúc nội tại
2. Quan hệ giữa Hiệu quả hoạt động và Định giá
3. Tính ổn định và kiểm định độ bền mô hình
4. Hàm ý kinh tế – Tính bền vững của doanh nghiệp