PHẦN 1. PHÂN TÍCH DỮ LIỆU ĐẦU TƯ VÀ CHỈ SỐ TÀI CHÍNH CỦA CÁC CÔNG TY NIÊM YẾT TRÊN SÀN NYSE

1.1. GIỚI THIỆU VÀ CHUẨN BỊ DỮ LIỆU NYSE

1.1.1. Tổng quan về bộ dữ liệu và mục tiêu phân tích

1.1.1.1. Giới thiệu chung và mục tiêu phân tích

Trong bối cảnh nền kinh tế toàn cầu ngày càng vận hành dựa trên dữ liệu, năng lực phân tích và khai thác thông tin từ dữ liệu tài chính đóng vai trò then chốt đối với các nhà phân tích, nhà đầu tư và các tổ chức tài chính. Ngôn ngữ lập trình R, với hệ sinh thái thư viện phong phú và khả năng xử lý thống kê mạnh mẽ, đã trở thành một công cụ phân tích dữ liệu hàng đầu, cho phép thực hiện các thao tác từ làm sạch, biến đổi, trực quan hóa đến mô hình hóa phức tạp.

Nghiên cứu này tập trung vào việc áp dụng ngôn ngữ R để thực hiện:

“Phân tích dữ liệu đầu tư và chỉ số tài chính của các công ty niêm yết trên sàn NYSE”

Bộ dữ liệu nền tảng cho nghiên cứu là “400K NYSE Random Investments + Financial Ratios” thu thập từ nền tảng Kaggle. Đây là một bộ dữ liệu giả lập quy mô lớn, mô phỏng 405.258 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. Dữ liệu kết hợp thông tin về giao dịch (ngày mua/bán, giá, số tiền), hiệu suất đầu tư (lợi suất, rủi ro), và các chỉ số tài chính cơ bản của doanh nghiệp tại thời điểm đầu tư.

Mục tiêu chính của nghiên cứu bao gồm:

  1. Áp dụng quy trình phân tích dữ liệu bằng R: Thực hiện tuần tự các bước từ làm sạch, chuẩn bị dữ liệu, thống kê mô tả, đến trực quan hóa đa chiều.

  2. Khám phá đặc điểm dữ liệu đầu tư NYSE: Phân tích cấu trúc, phân bố của các biến số chính (lợi suất, rủi ro, định giá, hiệu quả hoạt động) trong bộ dữ liệu mẫu.

  3. Xác định các yếu tố ảnh hưởng đến hiệu suất đầu tư: Sử dụng các phương pháp thống kê và trực quan hóa để khám phá mối quan hệ giữa các chỉ số tài chính, đặc điểm giao dịch (thời gian nắm giữ, ngành nghề), rủi ro và kết quả đầu tư thực tế (Real_Return, investment GOOD/BAD).

  4. Đánh giá sự khác biệt giữa các nhóm: So sánh hiệu suất, rủi ro, và đặc điểm tài chính giữa các ngành (sector), các chiến lược nắm giữ (Holding_Period), và các nhóm kết quả đầu tư (investment).

1.1.1.2. Cấu trúc và đặc điểm bộ dữ liệu

  • Tên: 400K NYSE Random Investments + Financial Ratios Dataset.

  • Nguồn: Kaggle (Dữ liệu giả lập dựa trên hoạt động thực tế tại NYSE).

  • Kích thước: 405.258 quan sát (giao dịch) x 25 biến (cột).

  • Loại dữ liệu: Hỗn hợp gồm biến định tính (Factor: company, sector, investment, ngày tháng dạng text) và biến định lượng (Numeric: giá, lợi suất, chỉ số tài chính).

  • Phạm vi thời gian: Giao dịch mua được thực hiện từ năm 2013 đến 2018.

  • Mô tả chi tiết các biến:

Bảng 1.1.1: Mô tả chi tiết các biến trong bộ dữ liệu NYSE gốc
Nhóm Biến Tên Biến Gốc Mô tả
Định danh X ID tự tăng của dòng dữ liệu
Định danh company Mã cổ phiếu (Factor)
Định danh sector Ngành nghề (Factor)
Giao dịch horizon..days. Số ngày nắm giữ (Integer)
Giao dịch amount Số tiền đầu tư (Integer)
Giao dịch date_BUY_fix Ngày mua (Factor, YYYY-MM-DD)
Giao dịch date_SELL_fix Ngày bán (Factor, YYYY-MM-DD)
Giao dịch price_BUY Giá mua (Numeric)
Giao dịch price_SELL Giá bán (Numeric)
Hiệu suất & Rủi ro nominal_return Lợi suất danh nghĩa (Numeric, %)
Hiệu suất & Rủi ro expected_return..yearly. Lợi suất kỳ vọng hàng năm (Numeric, %)
Hiệu suất & Rủi ro Volatility_Buy Độ biến động giá khi mua (Numeric)
Hiệu suất & Rủi ro Volatility_sell Độ biến động giá khi bán (Numeric)
Hiệu suất & Rủi ro Sharpe.Ratio Tỷ suất Sharpe (Numeric)
Hiệu suất & Rủi ro inflation Tỷ lệ lạm phát tại thời điểm bán (Numeric, %)
Chỉ số Tài chính PE_ratio Tỷ số Giá/Thu nhập (Numeric)
Chỉ số Tài chính EPS_ratio Thu nhập trên mỗi cổ phiếu (Numeric)
Chỉ số Tài chính PS_ratio Tỷ số Giá/Doanh thu (Numeric)
Chỉ số Tài chính PB_ratio Tỷ số Giá/Giá trị sổ sách (Numeric)
Chỉ số Tài chính current_ratio Tỷ lệ Thanh khoản hiện hành (Numeric)
Chỉ số Tài chính roa_ratio Tỷ suất Sinh lời trên Tài sản (Numeric, %)
Chỉ số Tài chính roe_ratio Tỷ suất Sinh lời trên Vốn CSH (Numeric, %)
Chỉ số Tài chính NetProfitMargin_ratio Biên Lợi nhuận ròng (Numeric, %)
Phân loại & Xếp hạng investment Kết quả đầu tư (Factor: GOOD/BAD)
Phân loại & Xếp hạng ESG_ranking Xếp hạng ESG (Numeric)

1.1.1.3. Tóm tắt cấu trúc phân tích

Nghiên cứu này được cấu trúc thành 6 mục chính, bám sát quy trình phân tích dữ liệu:

  1. Giới thiệu và chuẩn bị dữ liệu (Mục 1.1): Bao gồm tổng quan, kiểm tra chất lượng, làm sạch, và tạo các biến phái sinh cần thiết từ bộ dữ liệu gốc. Kết quả là bộ dữ liệu nyse_clean sẵn sàng cho phân tích.

  2. Lược khảo nghiên cứu liên quan (Mục 1.2): Trình bày các lý thuyết tài chính nền tảng và kết quả từ các nghiên cứu thực nghiệm trước đây về các yếu tố ảnh hưởng đến lợi suất cổ phiếu, làm cơ sở để đối chiếu và thảo luận kết quả.

  3. Thống kê mô tả (Mục 1.3): Đi sâu vào phân tích đặc điểm phân phối, tương quan, và kiểm định sự khác biệt trung bình giữa các nhóm dữ liệu bằng các công cụ thống kê.

  4. Trực quan hóa dữ liệu phân tích (Mục 1.4): Sử dụng ggplot2plotly để xây dựng một hệ thống biểu đồ đa dạng (phân bố, mối quan hệ, so sánh nhóm, xu hướng thời gian) nhằm khám phá và trình bày các phát hiện một cách trực quan.

  5. Thảo luận kết quả (Mục 1.5): Tổng hợp, so sánh các kết quả phân tích thống kê và trực quan hóa với phần lược khảo, đưa ra các bình luận và giải thích về mặt kinh tế/tài chính.

  6. Kết luận và hạn chế (Mục 1.6): Tóm tắt các phát hiện chính, nêu rõ các hạn chế của nghiên cứu và đề xuất hướng phát triển trong tương lai.

1.1.2. Kiểm tra cấu trúc và chất lượng dữ liệu ban đầu

1.1.2.1. Đọc dữ liệu và kiểm tra kích thước

# 1. Tải các thư viện cần thiết cho mục này
library(dplyr)      # Cho các thao tác dữ liệu sau này
library(readr)      # Cung cấp hàm read_csv tối ưu hơn read.csv
library(skimr)      # Cung cấp hàm skim() để tóm tắt dữ liệu
library(knitr)      # Để tạo bảng đẹp (kable)

# 2. Đọc dữ liệu từ file CSV
# Sử dụng read_csv từ readr để đọc nhanh hơn và xử lý kiểu dữ liệu tốt hơn
# na.strings được giữ nguyên để xử lý giá trị rỗng
file_path <- "C:/Users/Admin/Documents/NGÔN NGỮ R/final_transactions_dataset.csv"
nyse_raw <- read_csv(file_path, na = c("", "NA"))

# 3. Kiểm tra kích thước dữ liệu (Số dòng, số cột)
num_obs_raw <- nrow(nyse_raw) # Số lượng quan sát (dòng)
num_vars_raw <- ncol(nyse_raw) # Số lượng biến (cột)

# In kết quả kích thước
cat("1.1.2.1: Kiểm tra kích thước dữ liệu \n")
## 1.1.2.1: Kiểm tra kích thước dữ liệu
cat("Số lượng quan sát (giao dịch):", format(num_obs_raw, big.mark = ","), "\n") # Định dạng số lớn
## Số lượng quan sát (giao dịch): 405,258
cat("Số lượng biến (trường thông tin):", num_vars_raw, "\n")
## Số lượng biến (trường thông tin): 25
# Chuyển đổi các cột ngày tháng sang Date ngay sau khi đọc
# (Thao tác này nằm ở Mục 1.3, nhưng thực hiện sớm để skim() nhận diện đúng)
if("date_BUY_fix" %in% names(nyse_raw)) {
  nyse_raw <- nyse_raw %>% mutate(date_BUY_fix = as.Date(date_BUY_fix))
}
if("date_SELL_fix" %in% names(nyse_raw)) {
  nyse_raw <- nyse_raw %>% mutate(date_SELL_fix = as.Date(date_SELL_fix))
}

Dữ liệu gốc được đọc thành công vào đối tượng nyse_raw. Kết quả kiểm tra kích thước xác nhận quy mô lớn của bộ dữ liệu với num_obs_raw = 405,258 quan sát và num_vars_raw = 25 biến. Các cột ngày tháng đã được chuyển đổi sang kiểu Date để chuẩn bị cho các bước kiểm tra tiếp theo.

1.1.2.2. Kiểm tra kiểu dữ liệu và 6 dòng đầu

# 1. Kiểm tra cấu trúc dữ liệu chi tiết (tên biến, kiểu dữ liệu)
cat("\n 1.1.2.2: Kiểm tra cấu trúc dữ liệu (str)\n")
## 
##  1.1.2.2: Kiểm tra cấu trúc dữ liệu (str)
str(nyse_raw)
## tibble [405,258 × 25] (S3: tbl_df/tbl/data.frame)
##  $ ...1                    : num [1:405258] 0 1 2 3 4 5 7 8 9 10 ...
##  $ company                 : chr [1:405258] "BBY" "BAC" "AXP" "KSS" ...
##  $ sector                  : chr [1:405258] "RETAIL" "BANK" "BANK" "RETAIL" ...
##  $ horizon (days)          : num [1:405258] 2 330 7 5 360 15 720 600 30 6 ...
##  $ amount                  : num [1:405258] 100 15000 3000 20000 15000 50000 1500 300 50000 400 ...
##  $ date_BUY_fix            : Date[1:405258], format: "2017-05-25" "2016-11-22" ...
##  $ date_SELL_fix           : Date[1:405258], format: "2017-05-26" "2017-10-18" ...
##  $ price_BUY               : num [1:405258] 55.6 18.6 59.9 38.2 51.9 ...
##  $ price_SELL              : num [1:405258] 53.5 24.7 59.5 36 52 ...
##  $ Volatility_Buy          : num [1:405258] 0.384 0.323 0.239 0.429 0.195 ...
##  $ Volatility_sell         : num [1:405258] 0.386 0.236 0.235 0.429 0.254 ...
##  $ Sharpe Ratio            : num [1:405258] 0.384 0.323 0.239 0.429 0.195 ...
##  $ expected_return (yearly): num [1:405258] 1.44e-03 1.71e-01 2.82e-03 9.39e-05 1.50e-01 ...
##  $ inflation               : num [1:405258] 1.96 -0.2 -0.2 -0.2 -0.5 -0.2 -0.15 -0.2 -0.5 -0.2 ...
##  $ nominal_return          : num [1:405258] -0.03722 0.32432 -0.00576 -0.05839 0.00344 ...
##  $ investment              : chr [1:405258] "BAD" "GOOD" "BAD" "BAD" ...
##  $ ESG_ranking             : num [1:405258] 12 26.3 19.8 12.9 27.9 17.6 31.6 24.8 26.3 27.9 ...
##  $ PE_ratio                : num [1:405258] 12.58 11.39 10.58 11.09 9.38 ...
##  $ EPS_ratio               : num [1:405258] 3.73 1.26 5.64 3.27 5.46 4.56 1.05 1.71 0.96 5.99 ...
##  $ PS_ratio                : num [1:405258] 0.38 1.71 1.67 0.36 1.87 ...
##  $ PB_ratio                : num [1:405258] 3.19 0.54 2.6 1.25 0.81 ...
##  $ NetProfitMargin_ratio   : num [1:405258] 3.01 15.7 15.68 3.17 19.91 ...
##  $ current_ratio           : num [1:405258] 1.49 0.92 1.91 1.6 0.99 ...
##  $ roa_ratio               : num [1:405258] 8.69 0.67 3.39 4.41 0.81 ...
##  $ roe_ratio               : num [1:405258] 26.69 5.54 25.78 11.35 8.91 ...
# 2. Hiển thị 6 dòng dữ liệu đầu tiên để xem mẫu dữ liệu thực tế
cat("\n 1.1.2.2: Hiển thị 6 Dòng Đầu tiên (head)\n")
## 
##  1.1.2.2: Hiển thị 6 Dòng Đầu tiên (head)
# Sử dụng kable để hiển thị bảng đẹp hơn head() mặc định
kable(head(nyse_raw),
      caption = "Bảng 1.1.2: Sáu quan sát đầu tiên của bộ dữ liệu NYSE", # Cập nhật caption
      format = "pipe",
      align = "l")
Bảng 1.1.2: Sáu quan sát đầu tiên của bộ dữ liệu NYSE
…1 company sector horizon (days) amount date_BUY_fix date_SELL_fix price_BUY price_SELL Volatility_Buy Volatility_sell Sharpe Ratio expected_return (yearly) inflation nominal_return investment ESG_ranking PE_ratio EPS_ratio PS_ratio PB_ratio NetProfitMargin_ratio current_ratio roa_ratio roe_ratio
0 BBY RETAIL 2 100 2017-05-25 2017-05-26 55.55180 53.48391 0.3836656 0.3857480 0.3836656 0.0014373 1.96 -0.0372245 BAD 12.0 12.58 3.73 0.38 3.19 3.01 1.49 8.69 26.69
1 BAC BANK 330 15000 2016-11-22 2017-10-18 18.61675 24.65447 0.3228091 0.2363500 0.3228091 0.1709691 -0.20 0.3243168 GOOD 26.3 11.39 1.26 1.71 0.54 15.70 0.92 0.67 5.54
2 AXP BANK 7 3000 2016-09-27 2016-10-04 59.86230 59.51773 0.2386420 0.2354905 0.2386420 0.0028236 -0.20 -0.0057560 BAD 19.8 10.58 5.64 1.67 2.60 15.68 1.91 3.39 25.78
3 KSS RETAIL 5 20000 2016-10-11 2016-10-17 38.21672 35.98533 0.4285595 0.4293397 0.4285595 0.0000939 -0.20 -0.0583879 BAD 12.9 11.09 3.27 0.36 1.25 3.17 1.60 4.41 11.35
4 JPM BANK 360 15000 2015-03-12 2016-03-07 51.86934 52.04797 0.1946118 0.2540115 0.1946118 0.1499787 -0.50 0.0034439 GOOD 27.9 9.38 5.46 1.87 0.81 19.91 0.99 0.81 8.91
5 PEP FMCG 15 50000 2016-09-09 2016-09-23 91.77097 94.67268 0.1376212 0.1382858 0.1376212 0.0032632 -0.20 0.0316190 GOOD 17.6 21.03 4.56 2.27 10.83 10.74 1.32 9.29 54.98

Kết quả từ str() cho thấy cấu trúc chi tiết:

  • Kiểu dữ liệu: Các biến số (price_BUY, nominal_return…) là num (numeric). Các biến định danh (company, sector, investment) là chr (character). Quan trọng là các biến ngày tháng (date_BUY_fix, date_SELL_fix) đã được chuyển thành kiểu Date. Các kiểu chr sẽ cần chuyển thành Factor ở Mục 1.3. Biến Xdbl cần loại bỏ.

  • Giá trị mẫu: head() hiển thị dữ liệu thực tế, giúp hình dung rõ hơn về định dạng và giá trị của các biến.

1.1.2.3. Tóm tắt tổng quan bằng

# 1. Sử dụng hàm skim() để có cái nhìn tổng quan nhanh về phân bố và kiểu dữ liệu
cat("\n1.1.2.3: Tóm tắt tổng quan (skim)\n")
## 
## 1.1.2.3: Tóm tắt tổng quan (skim)
# (Chạy skim() trên nyse_raw SAU khi đã chuyển đổi Date)
skim_summary <- skim(nyse_raw)
print(skim_summary) # In kết quả skim đầy đủ
## ── Data Summary ────────────────────────
##                            Values  
## Name                       nyse_raw
## Number of rows             405258  
## Number of columns          25      
## _______________________            
## Column type frequency:             
##   character                3       
##   Date                     2       
##   numeric                  20      
## ________________________           
## Group variables            None    
## 
## ── Variable type: character ────────────────────────────────────────────────────
##   skim_variable n_missing complete_rate min max empty n_unique whitespace
## 1 company               0             1   1   4     0       27          0
## 2 sector                0             1   4   6     0        5          0
## 3 investment            0             1   3   4     0        2          0
## 
## ── Variable type: Date ─────────────────────────────────────────────────────────
##   skim_variable n_missing complete_rate min        max        median    
## 1 date_BUY_fix          0             1 2013-10-10 2018-10-09 2016-05-19
## 2 date_SELL_fix         0             1 2013-10-11 2020-09-28 2016-11-21
##   n_unique
## 1     1248
## 2     1729
## 
## ── Variable type: numeric ──────────────────────────────────────────────────────
##    skim_variable            n_missing complete_rate        mean          sd
##  1 ...1                             0             1 249936.     144240.    
##  2 horizon (days)                   0             1    187.        211.    
##  3 amount                           0             1   8108.      12774.    
##  4 price_BUY                        0             1    105.        217.    
##  5 price_SELL                       0             1    117.        250.    
##  6 Volatility_Buy                   0             1      0.254       0.0981
##  7 Volatility_sell                  0             1      0.260       0.0994
##  8 Sharpe Ratio                     0             1      0.254       0.0981
##  9 expected_return (yearly)         0             1      0.0708      0.143 
## 10 inflation                        0             1      0.578       1.04  
## 11 nominal_return                   0             1      0.0710      0.299 
## 12 ESG_ranking                      0             1     22.6         6.51  
## 13 PE_ratio                         0             1     30.3        84.7   
## 14 EPS_ratio                        0             1      3.44        4.39  
## 15 PS_ratio                         0             1      2.72        3.60  
## 16 PB_ratio                         0             1      4.69        5.91  
## 17 NetProfitMargin_ratio            0             1      9.21       10.4   
## 18 current_ratio                    0             1      2.17        2.56  
## 19 roa_ratio                        0             1      5.60        5.98  
## 20 roe_ratio                        0             1     15.6        17.5   
##          p0          p25         p50         p75       p100 hist 
##  1   0      125063.      249938.     374755.     499999     ▇▇▇▇▇
##  2   1          15           90         300         720     ▇▂▂▁▁
##  3  50         400         2000       10000       50000     ▇▁▁▁▁
##  4   7.14       28.3         46.2        76.3      2040.    ▇▁▁▁▁
##  5   4.01       28.4         48.0        81.6      3451.    ▇▁▁▁▁
##  6   0.0904      0.185        0.232       0.307       0.698 ▇▇▃▁▁
##  7   0.0904      0.189        0.238       0.316       0.923 ▇▅▁▁▁
##  8   0.0904      0.185        0.232       0.307       0.698 ▇▇▃▁▁
##  9  -0.278       0.00106      0.0128      0.0826      1.02  ▁▇▁▁▁
## 10  -0.5        -0.2         -0.15        1.68        1.96  ▇▁▁▁▅
## 11  -0.872      -0.0284       0.0141      0.111       8.85  ▇▁▁▁▁
## 12  12          16.3         25.1        27.9        31.6   ▇▅▂▇▇
## 13   0           9.82        13.7        23.5      1117.    ▇▁▁▁▁
## 14  -6.56        1.46         2.96        4.56       29.9   ▂▇▁▁▁
## 15   0.16        0.47         1.71        3.18       24.5   ▇▁▁▁▁
## 16   0           1.22         3.05        5.23       47.6   ▇▁▁▁▁
## 17 -24.6         2.62         7.7        15.8        62     ▁▇▆▁▁
## 18   0.61        0.98         1.22        1.79       13.6   ▇▁▁▁▁
## 19 -13.0         1.74         5.71        7.99       38.1   ▁▇▃▁▁
## 20 -99.5         8.83        16.1        26.0        57.2   ▁▁▁▇▃
  • Xác nhận kích thước & kiểu: Tái xác nhận 405,258 dòng x 25 cột. Phân loại kiểu dữ liệu cho thấy 3 biến character (cần chuyển thành Factor), 2 biến Date (đã chuẩn hóa), và 20 biến numeric.

  • Kiểm tra NA: Cột n_missingcomplete_rate sẽ xác nhận lại việc bộ dữ liệu không có giá trị khuyết thiếu.

  • Phân bố sơ bộ (Numeric): Phần thống kê và histogram nhỏ cho các biến numeric sẽ tiếp tục cho thấy:

    • Độ lệch lớn: Các biến như nominal_return, PE_ratiomean khác median (p50), histogram lệch, cần xử lý outlier/chuẩn hóa ở Mục 1.3.

    • Phạm vi rộng: Nhiều biến có khoảng min-max lớn.

  • Phân bố sơ bộ (Character): Số lượng giá trị duy nhất (n_unique) cho company, sector sẽ được hiển thị, xác nhận tính phù hợp để chuyển thành Factor.

1.1.2.4. Kiểm tra giá trị khuyết thiếu (NA)

# 1. Tính toán số lượng NA cho từng cột
cat("\n1.1.2.4: Kiểm tra giá trị khuyết thiếu (NA)\n")
## 
## 1.1.2.4: Kiểm tra giá trị khuyết thiếu (NA)
na_counts <- colSums(is.na(nyse_raw))

# 2. Lọc ra các cột có NA (nếu có)
cols_with_na <- na_counts[na_counts > 0]

# 3. Trình bày kết quả
if (length(cols_with_na) == 0) {
  cat("Xác nhận: Không có giá trị khuyết thiếu (NA) trong bất kỳ cột nào.\n")
} else {
  cat("Các cột chứa giá trị NA và số lượng tương ứng:\n")
  # Tạo data frame để trình bày bằng kable
  na_table <- data.frame(
    TenBien = names(cols_with_na),
    SoLuongNA = as.integer(cols_with_na)
  )
  print(kable(na_table,
              caption = "Bảng 1.1.3: Thống kê giá trị khuyết thiếu (NA) theo biến", # Cập nhật caption
              format = "pipe",
              align = "l"))
}
## Xác nhận: Không có giá trị khuyết thiếu (NA) trong bất kỳ cột nào.

Kết quả kiểm tra chi tiết tái khẳng định: không có giá trị khuyết thiếu (NA) nào trong bộ dữ liệu nyse_raw.

1.1.2.5. Kiểm tra bản ghi trùng lặp

# 1. Đếm số lượng bản ghi (dòng) trùng lặp hoàn toàn
cat("\n 1.1.2.5: Kiểm tra bản ghi trùng lặp\n")
## 
##  1.1.2.5: Kiểm tra bản ghi trùng lặp
num_duplicates <- sum(duplicated(nyse_raw))

# 2. In kết quả
cat("Số lượng bản ghi trùng lặp hoàn toàn:", num_duplicates, "\n")
## Số lượng bản ghi trùng lặp hoàn toàn: 0
# 3. Kiểm tra và thông báo
if (num_duplicates == 0) {
    cat("Xác nhận: Không có bản ghi trùng lặp hoàn toàn.\n")
} else {
    cat("Cảnh báo: Phát hiện", num_duplicates, "bản ghi trùng lặp. Cần xem xét loại bỏ ở Mục 1.3.\n")
}
## Xác nhận: Không có bản ghi trùng lặp hoàn toàn.

Kết quả kiểm tra xác nhận không có bản ghi nào bị trùng lặp hoàn toàn.

Tổng kết 1.1.2: Bộ dữ liệu nyse_raw (sau khi chuyển đổi Date) có quy mô lớn, đầy đủ (không NA, không trùng lặp), nhưng cần chuẩn hóa các kiểu dữ liệu character thành Factor, loại bỏ biến X, và xử lý các biến numeric có độ lệch cao.

1.1.3. Xử lý dữ liệu, làm sạch và tạo biến phái sinh

1.1.3.1. Loại bỏ biến thừa và đổi tên biến

# 1. Tải thư viện cần thiết cho mục này
library(dplyr)
library(lubridate) # Cần cho xử lý ngày tháng
library(knitr)     # Cần cho kable

# 2. Tạo bản sao để tránh thay đổi dữ liệu gốc
nyse_clean <- nyse_raw

# 3. Loại bỏ cột index tự động '...1' và cột ngày bán gốc
nyse_clean <- nyse_clean %>%
  select(-`...1`, -date_SELL_fix) # Loại bỏ 2 cột

cat("1.1.3.1a: Loại bỏ biến thừa \n")
## 1.1.3.1a: Loại bỏ biến thừa
cat("Số lượng biến sau khi loại bỏ (...1, date_SELL_fix):", ncol(nyse_clean), "\n") # Còn lại 23 biến
## Số lượng biến sau khi loại bỏ (...1, date_SELL_fix): 23
# 4. Đổi tên biến ngay từ đầu cho ngắn gọn và nhất quán
cat("\n1.1.3.1b: Đổi tên biến \n")
## 
## 1.1.3.1b: Đổi tên biến
nyse_clean <- nyse_clean %>%
  rename(
    Horizon_Days = `horizon (days)`, # Đổi tên cho Số ngày nắm giữ
    Expected_Return_Yr = `expected_return (yearly)`,
    NetProfitMargin = NetProfitMargin_ratio,
    Current_Ratio = current_ratio,
    ROA = roa_ratio,
    ROE = roe_ratio,
    EPS = EPS_ratio,
    PS = PS_ratio,
    PB = PB_ratio,
    PE = PE_ratio,
    ESG = ESG_ranking,
    Nominal_Return = nominal_return,
    Date_Buy_Raw = date_BUY_fix, # Giữ lại ngày gốc dạng Date
    Sharpe_Ratio = `Sharpe Ratio` # Giả sử tên gốc có dấu cách
)
# 5. Kiểm tra lại tên biến sau khi đổi
cat("Tên biến mới (một phần):\n")
## Tên biến mới (một phần):
print(head(colnames(nyse_clean)))
## [1] "company"      "sector"       "Horizon_Days" "amount"       "Date_Buy_Raw"
## [6] "price_BUY"

Thao tác đầu tiên là dọn dẹp bộ dữ liệu. Biến index ...1 và biến ngày bán gốc date_SELL_fix được loại bỏ. Quan trọng hơn, các biến có tên dài hoặc chứa ký tự đặc biệt/dấu cách (như `horizon (days)`, `expected_return (yearly)`, `Sharpe Ratio`) đã được đổi tên thành các tên ngắn gọn, nhất quán ngay từ đầu. Bộ dữ liệu nyse_clean hiện có 23 biến với tên đã chuẩn hóa.

1.1.3.2. Chuyển đổi kiểu dữ liệu (Factor)

# 1. Xác định các biến Character cần chuyển đổi thành Factor
# (company, sector, investment - tên gốc đã là character)
cat("\n 1.1.3.2: Chuyển đổi kiểu dữ liệu (Character -> Factor) \n")
## 
##  1.1.3.2: Chuyển đổi kiểu dữ liệu (Character -> Factor)
# 2. Sử dụng mutate() kết hợp as.factor() để chuyển đổi
nyse_clean <- nyse_clean %>%
  mutate(
    # across() áp dụng hàm as.factor cho nhiều cột cùng lúc
    across(c(company, sector, investment), as.factor)
  )

# 3. Kiểm tra lại kiểu dữ liệu của các biến đã chuyển đổi
cat("Kiểu dữ liệu mới của 'company':", class(nyse_clean$company), "\n")
## Kiểu dữ liệu mới của 'company': factor
cat("Kiểu dữ liệu mới của 'sector':", class(nyse_clean$sector), "\n")
## Kiểu dữ liệu mới của 'sector': factor
cat("Kiểu dữ liệu mới của 'investment':", class(nyse_clean$investment), "\n")
## Kiểu dữ liệu mới của 'investment': factor
# 4. In ra các cấp độ (levels) của biến sector để xem xét
cat("Các cấp độ (levels) của biến 'sector':\n")
## Các cấp độ (levels) của biến 'sector':
print(levels(nyse_clean$sector))
## [1] "AUTO"   "BANK"   "FMCG"   "RETAIL" "TECH"

Chuyển đổi các biến character (company, sector, investment) thành kiểu factor là bước chuẩn hóa quan trọng. Kiểu factor giúp R hiểu rằng đây là các biến phân loại, tối ưu hóa lưu trữ và cho phép thực hiện các phân tích nhóm và vẽ biểu đồ phân loại hiệu quả. Kết quả xác nhận việc chuyển đổi thành công và cho thấy có 5 ngành (sector) chính.

1.1.3.3. Xử lý biến ngày tháng và tính toán thời gian nắm giữ

# 1. Đảm bảo cột ngày mua có kiểu Date
cat("\n 1.1.3.3: Xử lý biến Nngày tháng \n")
## 
##  1.1.3.3: Xử lý biến Nngày tháng
if (!inherits(nyse_clean$Date_Buy, "Date")) {
  # (Code chuyển đổi nếu cần, giả sử Date_Buy đã là Date)
  cat("Cảnh báo: 'Date_Buy' chưa phải kiểu Date. Đang chuyển đổi...\n")
  nyse_clean <- nyse_clean %>% mutate(Date_Buy = as.Date(Date_Buy_Raw))
} else {
  cat("'Date_Buy' đã có kiểu Date.\n")
}
## Cảnh báo: 'Date_Buy' chưa phải kiểu Date. Đang chuyển đổi...
# 2. Tính toán ngày bán dự kiến từ ngày mua và số ngày nắm giữ
nyse_clean <- nyse_clean %>%
  mutate(
    Horizon_Days_Int = as.integer(Horizon_Days),
    Date_Sell = Date_Buy + Horizon_Days_Int
  )

# 3. Tính toán lại Thời gian nắm giữ thực tế (để kiểm tra) bằng difftime
nyse_clean <- nyse_clean %>%
  mutate(
    Holding_Days = as.numeric(difftime(Date_Sell, Date_Buy, units = "days"))
  )

# 4. So sánh Horizon_Days gốc và Holding_Days tính lại
cat("So sánh số ngày nắm giữ gốc và tính toán lại:\n")
## So sánh số ngày nắm giữ gốc và tính toán lại:
print(kable(head(nyse_clean %>% select(Horizon_Days, Holding_Days)),
            caption = "Bảng 1.1.4: Kiểm tra tính toán Thời gian Nắm giữ",
            format="pipe"))
## 
## 
## Table: Bảng 1.1.4: Kiểm tra tính toán Thời gian Nắm giữ
## 
## | Horizon_Days| Holding_Days|
## |------------:|------------:|
## |            2|            2|
## |          330|          330|
## |            7|            7|
## |            5|            5|
## |          360|          360|
## |           15|           15|
# 5. Trích xuất Năm mua (Buy_Year) và Quý mua (Buy_Quarter)
nyse_clean <- nyse_clean %>%
  mutate(
    Buy_Year = year(Date_Buy),                 # Trích xuất năm
    Buy_Quarter_Num = quarter(Date_Buy),       # Trích xuất số quý (1-4)
    # Tạo biến Buy_Quarter dạng YYYY.Q bằng cách kết hợp Year và Quarter_Num
    Buy_Quarter = paste0(Buy_Year, ".", Buy_Quarter_Num) 
  )

# 6. Hiển thị kết quả trích xuất thời gian
cat("Kết quả trích xuất Năm và Quý mua (6 dòng đầu):\n")
## Kết quả trích xuất Năm và Quý mua (6 dòng đầu):
print(kable(head(nyse_clean %>% select(Date_Buy, Buy_Year, Buy_Quarter)),
            caption = "Bảng 1.1.5: Kết quả Trích xuất Thông tin Thời gian",
            format="pipe"))
## 
## 
## Table: Bảng 1.1.5: Kết quả Trích xuất Thông tin Thời gian
## 
## |Date_Buy   | Buy_Year|Buy_Quarter |
## |:----------|--------:|:-----------|
## |2017-05-25 |     2017|2017.2      |
## |2016-11-22 |     2016|2016.4      |
## |2016-09-27 |     2016|2016.3      |
## |2016-10-11 |     2016|2016.4      |
## |2015-03-12 |     2015|2015.1      |
## |2016-09-09 |     2016|2016.3      |
  • Chuẩn hóa ngày: Biến ngày mua Date_Buy (được tạo từ Date_Buy_Raw) được đảm bảo có kiểu Date.

  • Tái tạo ngày bán & kiểm tra: Date_Sell được tính toán lại từ Date_BuyHorizon_Days. So sánh Holding_Days với Horizon_Days gốc xác nhận tính nhất quán.

  • Trích xuất chu kỳ: Các biến Buy_YearBuy_Quarter được tạo ra, quan trọng cho phân tích xu hướng và thời vụ sau này.

1.1.3.4. Chuẩn hóa tỷ suất định giá (Tạo Log_PE)

# 1. Kiểm tra phân bố gốc của PE
# (Đã thấy lệch ở 1.1.2.3 khi xem PE_ratio gốc)
cat("\n 1.1.3.4: Chuẩn hóa Tỷ suất Định giá P/E \n")
## 
##  1.1.3.4: Chuẩn hóa Tỷ suất Định giá P/E
cat("Tóm tắt PE gốc:\n")
## Tóm tắt PE gốc:
summary_pe_raw <- summary(nyse_clean$PE) # Sử dụng tên biến mới 'PE'
print(summary_pe_raw)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    0.00    9.82   13.71   30.33   23.49 1116.57
# 2. Tạo biến PE_Positive để xử lý giá trị âm/0 trước khi lấy log
# Chỉ giữ lại các giá trị P/E > 0 (hợp lý về mặt kinh tế)
nyse_clean <- nyse_clean %>%
  mutate(
    # Sử dụng tên biến mới 'PE'
    PE_Positive = if_else(PE > 0, PE, NA_real_) # Gán NA nếu PE <= 0
  )

# 3. Tính toán logarit tự nhiên của PE_Positive (Log_PE)
# Phép biến đổi log giúp giảm độ lệch và ảnh hưởng của outliers
nyse_clean <- nyse_clean %>%
  mutate(
    Log_PE = log(PE_Positive) # log() tự động trả về NA nếu input là NA
  )

# 4. Kiểm tra phân bố của Log_PE
cat("\nTóm tắt Log_PE (sau khi chuẩn hóa):\n")
## 
## Tóm tắt Log_PE (sau khi chuẩn hóa):
summary_log_pe <- summary(nyse_clean$Log_PE) # Sử dụng tên biến mới 'Log_PE'
print(summary_log_pe)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##    1.13    2.38    2.69    2.88    3.21    7.02   39751
# 5. So sánh Mean và Median để đánh giá hiệu quả chuẩn hóa
mean_pe_raw <- summary_pe_raw["Mean"]
median_pe_raw <- summary_pe_raw["Median"]
mean_log_pe <- summary_log_pe["Mean"]
median_log_pe <- summary_log_pe["Median"]

cat(paste("\nPE gốc: Mean =", round(mean_pe_raw, 2), "| Median =", round(median_pe_raw, 2), "=> Chênh lệch lớn (Lệch phải)\n"))
## 
## PE gốc: Mean = 30.33 | Median = 13.71 => Chênh lệch lớn (Lệch phải)
cat(paste("Log_PE: Mean =", round(mean_log_pe, 2), "| Median =", round(median_log_pe, 2), "=> Chênh lệch nhỏ (Đối xứng hơn)\n"))
## Log_PE: Mean = 2.88 | Median = 2.69 => Chênh lệch nhỏ (Đối xứng hơn)
# 6. Đếm số lượng NA phát sinh do PE <= 0
na_log_pe <- sum(is.na(nyse_clean$Log_PE)) # Sử dụng tên biến mới 'Log_PE'
cat("Số lượng quan sát có PE <= 0 (bị gán NA trong Log_PE):", format(na_log_pe, big.mark = ","), "\n")
## Số lượng quan sát có PE <= 0 (bị gán NA trong Log_PE): 39,751

Nhận xét phân tích 1.1.3.4:

Biến PE gốc có phân bố cực kỳ lệch phải (Mean=30.33 >> Median=13.71), bị ảnh hưởng nặng bởi các giá trị ngoại lai rất lớn (Max=1116.57).

  • Xử lý giá trị không hợp lệ: Bước tạo PE_Positive đã loại bỏ các giá trị P/E âm hoặc bằng 0 (khoảng 39,751 quan sát), đảm bảo chỉ các công ty có lợi nhuận dương mới được đưa vào phân tích định giá P/E.

  • Hiệu quả chuẩn hóa: Phép biến đổi logarit tự nhiên đã tạo ra biến Log_PE với phân bố gần đối xứng hơn nhiều (Mean=2.88 và Median=2.69). Việc này giúp giảm thiểu tác động của outliers và làm cho biến Log_PE phù hợp hơn khi sử dụng trong các mô hình thống kê sau này.

1.1.3.5. Tạo biến đòn bẩy tài chính (Leverage_Ratio)

# 1. Định nghĩa công thức xấp xỉ từ DuPont: Leverage ~ ROE / ROA
cat("\n 1.1.3.5: Tạo biến Đòn bẩy Tài chính (Leverage_Ratio) \n")
## 
##  1.1.3.5: Tạo biến Đòn bẩy Tài chính (Leverage_Ratio)
# 2. Tính toán Leverage_Ratio, kiểm soát lỗi chia cho 0 hoặc ROA quá nhỏ
nyse_clean <- nyse_clean %>%
  mutate(
    # Sử dụng giá trị tuyệt đối abs(ROA)
    # Ngưỡng 0.001 (0.1%) để loại bỏ các trường hợp ROA gần bằng 0
    Leverage_Ratio = if_else(
      abs(ROA) > 0.001, # Điều kiện: ROA phải đủ lớn
      ROE / ROA,       # Công thức tính
      NA_real_         # Gán NA nếu ROA quá nhỏ
    )
  )

# 3. Kiểm tra phân bố của biến Leverage_Ratio mới tạo
cat("Tóm tắt phân bố Leverage_Ratio:\n")
## Tóm tắt phân bố Leverage_Ratio:
summary_leverage <- summary(nyse_clean$Leverage_Ratio)
print(summary_leverage)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##   1.103   2.486   3.439   5.212   6.692  34.545    2468
# 4. Đếm số lượng NA phát sinh do ROA quá nhỏ
na_leverage <- sum(is.na(nyse_clean$Leverage_Ratio))
cat("Số lượng quan sát có ROA quá nhỏ (bị gán NA trong Leverage_Ratio):", format(na_leverage, big.mark = ","), "\n")
## Số lượng quan sát có ROA quá nhỏ (bị gán NA trong Leverage_Ratio): 2,468
# 5. Phân tích ý nghĩa kinh tế của Min > 1
min_leverage <- summary_leverage["Min."]
if (!is.na(min_leverage) && min_leverage > 1) {
  cat("Phân tích: Min > 1 cho thấy các công ty hợp lệ đều có ROE > ROA, tức là đòn bẩy đang có hiệu ứng tích cực.\n")
}
## Phân tích: Min > 1 cho thấy các công ty hợp lệ đều có ROE > ROA, tức là đòn bẩy đang có hiệu ứng tích cực.

Nhận xét phân tích 1.1.3.5:

Biến Leverage_Ratio được tạo ra như một thước đo xấp xỉ mức độ sử dụng đòn bẩy tài chính, dựa trên mối quan hệ ROE ≈ ROA * Đòn bẩy (sử dụng tên biến mới ROEROA).

  • Kiểm soát Lỗi: Điều kiện abs(ROA) > 0.001 loại bỏ khoảng 2,468 quan sát có ROA gần bằng 0, tránh kết quả vô cực.

  • Phân bố và ý nghĩa: Phân bố lệch phải (Mean=5.21 > Median=3.44). Giá trị Min > 1.1 ngụ ý rằng, trong các trường hợp hợp lệ, việc sử dụng nợ đã có tác động khuếch đại tích cực lên ROE.

1.1.3.6. Phân loại thời gian nắm giữ (Holding_Period)

# 1. Xác định các ngưỡng cắt (breaks) và nhãn (labels)
cat("\n 1.1.3.6: Phân loại thời gian nắm giữ (Holding_Period) \n")
## 
##  1.1.3.6: Phân loại thời gian nắm giữ (Holding_Period)
breaks_days <- c(0, 30, 180, Inf) # Ngưỡng: 0-30 ngày, 31-180 ngày, >180 ngày
labels_period <- c("Short-term (<=30d)", "Mid-term (31-180d)", "Long-term (>180d)")

# 2. Sử dụng hàm cut() để tạo biến Factor mới
# Sử dụng tên biến mới Horizon_Days
nyse_clean <- nyse_clean %>%
  mutate(
    Holding_Period = cut(Horizon_Days,
                         breaks = breaks_days,
                         labels = labels_period,
                         right = TRUE, include.lowest = TRUE)
  )

# 3. Tính toán tần suất và tỷ lệ phần trăm cho từng nhóm
holding_freq <- nyse_clean %>%
  count(Holding_Period, name = "Count") %>%
  mutate(Percentage = round((Count / sum(Count)) * 100, 2)) %>%
  arrange(desc(Count))

# 4. Trình bày kết quả bằng kable
cat("Phân bổ tần suất theo Thời gian Nắm giữ:\n")
## Phân bổ tần suất theo Thời gian Nắm giữ:
print(kable(holding_freq,
            caption = "Bảng 1.1.6: Tần suất Giao dịch theo Chiến lược Nắm giữ",
            col.names = c("Thời gian Nắm giữ", "Số lượng", "Tỷ lệ (%)"),
            format = "pipe", align = "l"))
## 
## 
## Table: Bảng 1.1.6: Tần suất Giao dịch theo Chiến lược Nắm giữ
## 
## |Thời gian Nắm giữ  |Số lượng |Tỷ lệ (%) |
## |:------------------|:--------|:---------|
## |Long-term (>180d)  |147526   |36.40     |
## |Short-term (<=30d) |135001   |33.31     |
## |Mid-term (31-180d) |122731   |30.28     |

Nhận xét phân tích 1.1.3.6:

Biến liên tục Horizon_Days được chuyển đổi thành biến phân loại Holding_Period (Factor).

  • Phân bổ: Ba chiến lược (Ngắn, Trung, Dài hạn) có sự phân bổ tương đối đồng đều (~30-36%).

  • Ý nghĩa: Biến Holding_Period cho phép so sánh hiệu suất, rủi ro giữa các chiến lược thời gian khác nhau.

1.1.3.7. Tính toán lợi suất thực tế (Real_Return)

# 1. Áp dụng công thức Fisher Equation: Real = (1+Nominal)/(1+Inflation) - 1
cat("\n 1.1.3.7: Tính toán Lợi suất Thực tế (Real_Return) \n")
## 
##  1.1.3.7: Tính toán Lợi suất Thực tế (Real_Return)
nyse_clean <- nyse_clean %>%
  mutate(
    Real_Return = ((1 + Nominal_Return) / (1 + inflation)) - 1
  )

# 2. Kiểm tra kết quả tính toán (so sánh Nominal và Real cho vài dòng)
cat("So sánh Lợi suất Danh nghĩa và Thực tế (10 dòng đầu):\n")
## So sánh Lợi suất Danh nghĩa và Thực tế (10 dòng đầu):
real_return_check <- nyse_clean %>%
  select(Nominal_Return, inflation, Real_Return) %>% 
  mutate(across(everything(), ~ round(. * 100, 2))) # Nhân 100 để hiển thị dạng %

print(kable(head(real_return_check, 10),
            caption = "Bảng 1.1.7: So sánh Lợi suất Danh nghĩa và Thực tế (%)",
            col.names = c("Danh nghĩa (%)", "Lạm phát (%)", "Thực tế (%)"),
            format = "pipe"))
## 
## 
## Table: Bảng 1.1.7: So sánh Lợi suất Danh nghĩa và Thực tế (%)
## 
## | Danh nghĩa (%)| Lạm phát (%)| Thực tế (%)|
## |--------------:|------------:|-----------:|
## |          -3.72|          196|      -67.47|
## |          32.43|          -20|       65.54|
## |          -0.58|          -20|       24.28|
## |          -5.84|          -20|       17.70|
## |           0.34|          -50|      100.69|
## |           3.16|          -20|       28.95|
## |          73.31|          -15|      103.90|
## |          23.67|          -20|       54.59|
## |          -1.39|          -50|       97.21|
## |           5.10|          -20|       31.37|
# 3. Tóm tắt phân bố của Real_Return
cat("\nTóm tắt phân bố Lợi suất Thực tế (Real_Return):\n")
## 
## Tóm tắt phân bố Lợi suất Thực tế (Real_Return):
summary_real_return <- summary(nyse_clean$Real_Return) # Sử dụng tên mới
print(summary_real_return)
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## -0.95232 -0.62084  0.16733  0.08676  0.48586 16.35331

Nhận xét phân tích 1.1.3.7:

Lợi suất thực tế (Real_Return) được tính toán để phản ánh sự thay đổi sức mua thực sự sau lạm phát, sử dụng biến Nominal_Return.

  • Kiểm tra Logic: Khi inflation âm, Real_Return > Nominal_Return, phù hợp lý thuyết.

  • Phân bố: Phân bố rộng (Min -95%, Max 1635%), lệch nhẹ (Mean < Median). Trung vị dương (16.73%) cho thấy đa số giao dịch vẫn có lãi thực. Real_Return là biến phụ thuộc quan trọng.

1.1.3.8. Tạo biến phân loại rủi ro (Risk_Level)

# 1. Phân tích phân vị của Volatility_Buy để xác định ngưỡng
cat("\n 1.1.3.8: Tạo biến phân loại rủi ro (Risk_Level) \n")
## 
##  1.1.3.8: Tạo biến phân loại rủi ro (Risk_Level)
vol_quantiles <- quantile(nyse_clean$Volatility_Buy, probs = c(0, 0.33, 0.66, 1), na.rm = TRUE)
cat("Phân vị của Volatility_Buy (0%, 33%, 66%, 100%):\n")
## Phân vị của Volatility_Buy (0%, 33%, 66%, 100%):
print(vol_quantiles)
##         0%        33%        66%       100% 
## 0.09041632 0.20200655 0.26697053 0.69755648
# 2. Tạo biến Risk_Level dựa trên phân vị (3 nhóm: Low, Medium, High)
nyse_clean <- nyse_clean %>%
  mutate(
    Risk_Level = cut(Volatility_Buy,
                     breaks = vol_quantiles,
                     labels = c("Low", "Medium", "High"),
                     include.lowest = TRUE, right = TRUE)
  )

# 3. Kiểm tra tần suất của biến Risk_Level mới
risk_level_freq <- nyse_clean %>%
  count(Risk_Level, name = "Count") %>%
  mutate(Percentage = round((Count / sum(Count)) * 100, 2))

cat("\nPhân bổ tần suất theo Mức độ Rủi ro:\n")
## 
## Phân bổ tần suất theo Mức độ Rủi ro:
print(kable(risk_level_freq,
            caption = "Bảng 1.1.8: Tần suất Giao dịch theo Mức độ Rủi ro",
            col.names = c("Mức Rủi ro", "Số lượng", "Tỷ lệ (%)"),
            format = "pipe", align = "l"))
## 
## 
## Table: Bảng 1.1.8: Tần suất Giao dịch theo Mức độ Rủi ro
## 
## |Mức Rủi ro |Số lượng |Tỷ lệ (%) |
## |:----------|:--------|:---------|
## |Low        |133740   |33        |
## |Medium     |133747   |33        |
## |High       |137771   |34        |

Nhận xét phân tích 1.1.3.8:

Biến Volatility_Buy được phân loại thành 3 nhóm (Low, Medium, High) dựa trên phân vị.

  • Phân bổ đều: Mỗi nhóm rủi ro có số lượng quan sát gần bằng nhau (~33%).

  • Ý nghĩa: Biến Risk_Level giúp đơn giản hóa phân tích ảnh hưởng của rủi ro và so sánh hiệu suất giữa các nhóm rủi ro.

1.1.3.9. Tạo biến phân loại quy mô giao dịch (Amount_Level)

# 1. Phân tích phân vị của amount để xác định ngưỡng
cat("\n 1.1.3.9: Tạo biến Phân loại Quy mô Giao dịch (Amount_Level) \n")
## 
##  1.1.3.9: Tạo biến Phân loại Quy mô Giao dịch (Amount_Level)
amount_quantiles <- quantile(nyse_clean$amount, probs = c(0, 0.33, 0.66, 1), na.rm = TRUE)
cat("Phân vị của amount (0%, 33%, 66%, 100%):\n")
## Phân vị của amount (0%, 33%, 66%, 100%):
print(amount_quantiles)
##    0%   33%   66%  100% 
##    50   500  5000 50000
# 2. Tạo biến Amount_Level dựa trên phân vị (3 nhóm: Small, Medium, Large)
nyse_clean <- nyse_clean %>%
  mutate(
    Amount_Level = cut(amount,
                       breaks = amount_quantiles,
                       labels = c("Small", "Medium", "Large"),
                       include.lowest = TRUE, right = TRUE)
  )

# 3. Kiểm tra tần suất của biến Amount_Level mới
amount_level_freq <- nyse_clean %>%
  count(Amount_Level, name = "Count") %>%
  mutate(Percentage = round((Count / sum(Count)) * 100, 2))

cat("\nPhân bổ tần suất theo Quy mô Giao dịch:\n")
## 
## Phân bổ tần suất theo Quy mô Giao dịch:
print(kable(amount_level_freq,
            caption = "Bảng 1.1.9: Tần suất Giao dịch theo Quy mô Đầu tư",
            col.names = c("Quy mô GD", "Số lượng", "Tỷ lệ (%)"),
            format = "pipe", align = "l"))
## 
## 
## Table: Bảng 1.1.9: Tần suất Giao dịch theo Quy mô Đầu tư
## 
## |Quy mô GD |Số lượng |Tỷ lệ (%) |
## |:---------|:--------|:---------|
## |Small     |142692   |35.21     |
## |Medium    |143246   |35.35     |
## |Large     |119320   |29.44     |

Nhận xét phân tích 1.1.3.9:

Biến amount được phân thành 3 nhóm (Small, Medium, Large) dựa trên phân vị.

  • Ngưỡng phân vị: Kết quả cho thấy các ngưỡng phân vị xác định các nhóm như sau: Small (<= 500 USD), Medium (từ 501 đến 5000 USD), và Large (> 5000 USD).

  • Phân bổ: Tần suất các nhóm khá đồng đều, với nhóm Small (35.21%) và Medium (35.35%) chiếm tỷ trọng lớn hơn một chút so với nhóm Large (29.44%). Mặc dù không hoàn toàn bằng 1/3, sự phân bổ này vẫn đủ cân bằng để thực hiện các so sánh ý nghĩa giữa các nhóm quy mô giao dịch.

  • Ý nghĩa: Biến Amount_Level cho phép phân tích xem quy mô giao dịch có ảnh hưởng đến lợi suất (Real_Return) hay hành vi đầu tư khác (ví dụ: các giao dịch lớn có tập trung vào ngành/rủi ro nào không?).

1.1.3.10. Kiểm tra các biến Tài chính/ESG

# Kiểm tra sự tồn tại và tóm tắt nhanh các biến đã đổi tên
cat("\n 1.1.3.10: Kiểm tra các biến có sẵn khác \n")
## 
##  1.1.3.10: Kiểm tra các biến có sẵn khác
# Sử dụng các tên biến mới đã được đổi ở 1.1.3.1
cat("Tóm tắt Biên Lợi nhuận ròng (NetProfitMargin):\n")
## Tóm tắt Biên Lợi nhuận ròng (NetProfitMargin):
summary(nyse_clean$NetProfitMargin)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## -24.630   2.620   7.700   9.205  15.770  62.000
cat("\nTóm tắt Tỷ số Giá/Doanh thu (PS):\n")
## 
## Tóm tắt Tỷ số Giá/Doanh thu (PS):
summary(nyse_clean$PS)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   0.160   0.470   1.710   2.725   3.180  24.490
cat("\nTóm tắt Tỷ lệ Thanh khoản (Current_Ratio):\n")
## 
## Tóm tắt Tỷ lệ Thanh khoản (Current_Ratio):
summary(nyse_clean$Current_Ratio)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   0.610   0.980   1.220   2.173   1.790  13.560
cat("\nTóm tắt Tỷ suất Sharpe (Sharpe_Ratio):\n")
## 
## Tóm tắt Tỷ suất Sharpe (Sharpe_Ratio):
summary(nyse_clean$Sharpe_Ratio) # Nếu đã đổi tên thành Sharpe_Ratio
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 0.09042 0.18536 0.23220 0.25414 0.30673 0.69756
cat("\nTóm tắt Xếp hạng ESG (ESG):\n")
## 
## Tóm tắt Xếp hạng ESG (ESG):
summary(nyse_clean$ESG)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   12.00   16.30   25.10   22.57   27.90   31.60

Nhận xét phân tích 1.1.3.10:

Việc kiểm tra tóm tắt thống kê cho các biến tài chính, rủi ro và ESG cung cấp cái nhìn sâu hơn về đặc điểm của các công ty trong mẫu:

  • Biên Lợi nhuận ròng (NetProfitMargin):

    • Phân bố rộng từ -24.63% đến 62.00%, cho thấy sự khác biệt rất lớn về hiệu quả hoạt động giữa các công ty.

    • Giá trị trung bình (Mean = 9.21%) cao hơn trung vị (Median = 7.70%), cho thấy phân bố hơi lệch phải, có một số công ty đạt biên lợi nhuận rất cao kéo trung bình lên. Tuy nhiên, mức độ lệch không quá nghiêm trọng như PE. Đa số công ty có biên lợi nhuận dương.

  • Tỷ số Giá/Doanh thu (PS):

    • Dao động từ 0.16 đến 24.49. Giá trị trung bình (Mean = 2.73) cao hơn trung vị (Median = 1.71), cho thấy phân bố lệch phải, có một số công ty được thị trường định giá rất cao so với doanh thu.

    • Giá trị PS thường thấp hơn PE, điều này phù hợp với kết quả (Median PS=1.71 < Median PE=13.71).

  • Tỷ lệ Thanh khoản (Current_Ratio):

    • Dao động từ 0.61 đến 13.56. Giá trị trung bình (Mean = 2.17) cao hơn trung vị (Median = 1.22) khá nhiều, cho thấy sự lệch phải mạnh do một số công ty có tỷ lệ thanh khoản cực kỳ cao.

    • Mức trung vị 1.22 cho thấy một nửa số công ty có tỷ lệ thanh khoản ở mức an toàn (tài sản ngắn hạn > nợ ngắn hạn). Tuy nhiên, 1st Qu. = 0.98 cho thấy có khoảng 25% công ty có rủi ro thanh khoản tiềm ẩn (tài sản ngắn hạn < nợ ngắn hạn).

  • Tỷ suất Sharpe (Sharpe_Ratio):

    • Điều thú vị là tất cả các giá trị đều dương, dao động từ 0.09 đến 0.70. Giá trị trung bình (Mean = 0.25) và trung vị (Median = 0.23) khá gần nhau, cho thấy phân bố tương đối đối xứng.

    • Việc Sharpe Ratio luôn dương có thể là đặc điểm của dữ liệu giả lập hoặc giai đoạn thị trường được mô phỏng. Nó đo lường lợi suất vượt trội trên mỗi đơn vị rủi ro (so với tài sản phi rủi ro), giá trị dương cho thấy các khoản đầu tư, trung bình, đã tạo ra lợi suất bù đắp được rủi ro.

  • Xếp hạng ESG (ESG):

    • Dao động từ 12.00 đến 31.60. Giá trị trung bình (Mean = 22.57) và trung vị (Median = 25.10) khá gần nhau, nhưng Mean < Median cho thấy phân bố hơi lệch trái nhẹ (có một số công ty bị xếp hạng ESG thấp kéo trung bình xuống).

    • Nhìn chung, các công ty trong mẫu có xếp hạng ESG tập trung ở mức trung bình đến khá (đa số nằm giữa 1st Qu.=16.3 và 3rd Qu.=27.9).

Kết luận: Các biến này cung cấp thêm thông tin đa chiều về hiệu quả hoạt động (NetProfitMargin), định giá (PS), sức khỏe tài chính (Current_Ratio), hiệu quả điều chỉnh rủi ro (Sharpe_Ratio), và yếu tố bền vững (ESG).

1.1.3.11. Kiểm tra cuối cùng và lưu trữ dữ liệu

# 1. Kiểm tra nhanh các biến quan trọng đã được tạo/xử lý/đổi tên
cat("\n 1.1.3.11: Chọn lọc Biến cuối cùng và Lưu trữ \n")
## 
##  1.1.3.11: Chọn lọc Biến cuối cùng và Lưu trữ
cat("Kiểm tra tóm tắt một vài biến cuối cùng (trước khi chọn lọc):\n")
## Kiểm tra tóm tắt một vài biến cuối cùng (trước khi chọn lọc):
summary(nyse_clean %>% select(Log_PE, Leverage_Ratio, Real_Return, Holding_Period, Risk_Level, Amount_Level))
##      Log_PE      Leverage_Ratio    Real_Return      
##  Min.   :1.13    Min.   : 1.103   Min.   :-0.95232  
##  1st Qu.:2.38    1st Qu.: 2.486   1st Qu.:-0.62084  
##  Median :2.69    Median : 3.439   Median : 0.16733  
##  Mean   :2.88    Mean   : 5.212   Mean   : 0.08676  
##  3rd Qu.:3.21    3rd Qu.: 6.692   3rd Qu.: 0.48586  
##  Max.   :7.02    Max.   :34.545   Max.   :16.35331  
##  NA's   :39751   NA's   :2468                       
##             Holding_Period    Risk_Level     Amount_Level   
##  Short-term (<=30d):135001   Low   :133740   Small :142692  
##  Mid-term (31-180d):122731   Medium:133747   Medium:143246  
##  Long-term (>180d) :147526   High  :137771   Large :119320  
##                                                             
##                                                             
##                                                             
## 
# 2. Tạo phiên bản "Cốt lõi" (32 biến) bằng cách loại bỏ các cột trung gian
# Liệt kê các cột trung gian không cần thiết cho phân tích cuối cùng:
# Date_Buy_Raw (đã có Date_Buy), Horizon_Days_Int (đã có Horizon_Days),
# Holding_Days (đã có Horizon_Days), PE_Positive (đã có Log_PE),
# Buy_Quarter_Num (đã có Buy_Quarter)
cols_to_remove <- c("Date_Buy_Raw", "Horizon_Days_Int", "Holding_Days", "PE_Positive", "Buy_Quarter_Num")

# Kiểm tra xem các cột này có tồn tại không trước khi loại bỏ (tránh lỗi)
cols_exist <- cols_to_remove %in% colnames(nyse_clean)
cols_to_remove_final <- cols_to_remove[cols_exist]

# Tạo nyse_clean_core bằng cách loại bỏ các cột trên
nyse_clean_core <- nyse_clean %>%
  select(-all_of(cols_to_remove_final))

# 3. Kiểm tra tên và số lượng biến của cả hai phiên bản
cat("\nKiểm tra phiên bản đầy đủ (nyse_clean):\n")
## 
## Kiểm tra phiên bản đầy đủ (nyse_clean):
cat("Số biến:", ncol(nyse_clean), "\n") # 37 biến
## Số biến: 37
print(head(colnames(nyse_clean)))
## [1] "company"      "sector"       "Horizon_Days" "amount"       "Date_Buy_Raw"
## [6] "price_BUY"
cat("\nKiểm tra phiên bản cốt lõi (nyse_clean_core):\n")
## 
## Kiểm tra phiên bản cốt lõi (nyse_clean_core):
cat("Số biến:", ncol(nyse_clean_core), "\n") # Số biến: 32
## Số biến: 32
print(head(colnames(nyse_clean_core)))
## [1] "company"      "sector"       "Horizon_Days" "amount"       "price_BUY"   
## [6] "price_SELL"
# 4. Lưu cả hai đối tượng vào file .RData
# Hàm save() có thể lưu nhiều đối tượng cùng lúc
save(nyse_clean, nyse_clean_core, file = "nyse_processed_final.RData")
cat("\n✅ Đã hoàn tất Mục 1.1.3 và lưu cả hai phiên bản dữ liệu (nyse_clean, nyse_clean_core) vào file: nyse_processed_final.RData\n")
## 
## ✅ Đã hoàn tất Mục 1.1.3 và lưu cả hai phiên bản dữ liệu (nyse_clean, nyse_clean_core) vào file: nyse_processed_final.RData

Nhận xét:

Sau khi hoàn tất các bước xử lý, một phiên bản dữ liệu “cốt lõi” (nyse_clean_core) gồm 32 biến chính đã được tạo ra bằng cách loại bỏ 5 cột tính toán trung gian (Date_Buy_Raw, Horizon_Days_Int, Holding_Days, PE_Positive, Buy_Quarter_Num) khỏi phiên bản đầy đủ (nyse_clean, 37 biến). Cả hai phiên bản dữ liệu này đều được lưu vào tệp nyse_processed_final.RData. Phiên bản nyse_clean_core gọn gàng hơn và sẽ là cơ sở chính cho các phân tích, trong khi nyse_clean có thể được giữ lại để tham chiếu nếu cần xem xét các bước tính toán trung gian.

1.2. LƯỢC KHẢO CÁC NGHIÊN CỨU LIÊN QUAN

1.2.1. Các lý thuyết Nnền tảng

1.2.1.1. Lý thuyết Thị trường hiệu quả (Efficient Market Hypothesis - EMH):

Do Fama (1970) đề xuất, EMH cho rằng giá cả chứng khoán luôn phản ánh đầy đủ và ngay lập tức tất cả các thông tin sẵn có. Lý thuyết này tồn tại ở ba dạng: yếu (giá quá khứ không dự báo được giá tương lai), trung bình (thông tin công khai đã phản ánh vào giá), và mạnh (mọi thông tin, kể cả nội bộ, đã phản ánh vào giá). Nếu EMH đúng, việc phân tích các chỉ số tài chính (thông tin công khai) sẽ không giúp nhà đầu tư đạt được lợi suất vượt trội một cách nhất quán. Tuy nhiên, nhiều nghiên cứu đã chỉ ra các Bất thường Thị trường (Anomalies) như hiệu ứng quy mô (size effect), hiệu ứng giá trị (value effect - cổ phiếu P/B thấp có lợi suất cao hơn), hay hiệu ứng đà (momentum effect), thách thức tính đúng đắn tuyệt đối của EMH. Phân tích về mối quan hệ giữa các chỉ số (PE, PB) và lợi suất (Real_Return) sẽ kiểm chứng sự tồn tại của các bất thường này trong bộ dữ liệu.

1.2.1.2. Mô hình Định giá tài sản vốn (Capital Asset Pricing Model - CAPM) và Mô hình đa nhân tố:

CAPM (Sharpe, 1964; Lintner, 1965) là mô hình cơ bản giải thích lợi suất kỳ vọng của một tài sản dựa trên lãi suất phi rủi ro, phần bù rủi ro thị trường và hệ số beta (đo lường rủi ro hệ thống). Tuy nhiên, CAPM bị phê bình vì chỉ dựa vào một yếu tố rủi ro duy nhất. Các mô hình đa nhân tố như Mô hình ba nhân tố Fama-French (1993) bổ sung thêm yếu tố quy mô (SMB - Small Minus Big) và yếu tố giá trị (HML - High Minus Low Book-to-Market) để giải thích tốt hơn sự biến động của lợi suất. *Mô hình năm nhân tố Fama-French (2015)** tiếp tục bổ sung yếu tố lợi nhuận (RMW - Robust Minus Weak) và yếu tố đầu tư (CMA - Conservative Minus Aggressive). Mặc dù bộ dữ liệu không có đủ thông tin để tính toán trực tiếp các nhân tố Fama-French, việc phân tích ảnh hưởng của các biến đại diện như quy mô (amount), định giá (Log_PE, PB), và hiệu quả sinh lời (ROE, ROA) lên Real_Return là có liên quan mật thiết đến các lý thuyết này.

1.2.1.3. Tài chính hành vi (Behavioral Finance):

Ngược lại với EMH giả định nhà đầu tư hoàn toàn lý trí, Tài chính hành vi (Kahneman & Tversky, 1979; Thaler, 1980) cho rằng các yếu tố tâm lý và sai lệch nhận thức (cognitive biases) ảnh hưởng đáng kể đến quyết định đầu tư và biến động thị trường. Các hiệu ứng như quá tự tin (overconfidence), tâm lý bầy đàn (herding), sợ thua lỗ (loss aversion) có thể dẫn đến việc định giá sai lệch và các bất thường thị trường. Phân tích về sự biến động của P/E (Mục 1.5.3, Biểu đồ 15) hay sự phân kỳ giữa vốn hóa và lợi nhuận (Biểu đồ 14) có thể phản ánh một phần các yếu tố tâm lý này.

1.2.1.4. Vai trò của các chỉ số tài chính:

Nhiều lý thuyết và thực nghiệm cho thấy các chỉ số tài chính cơ bản là công cụ quan trọng để đánh giá giá trị nội tại và dự báo lợi suất cổ phiếu.

  • Định giá (P/E, P/B, PS): Lý thuyết đầu tư giá trị (Graham & Dodd) cho rằng mua cổ phiếu có tỷ số định giá thấp (so với ngành hoặc lịch sử) có thể mang lại lợi suất cao hơn trong dài hạn. Biến Log_PE và các tỷ số khác trong bộ dữ liệu sẽ được dùng để kiểm chứng giả thuyết này.

  • Hiệu quả Sinh lời (ROE, ROA, NetProfitMargin): Lợi nhuận cao và bền vững là động lực tăng trưởng giá trị doanh nghiệp. Các chỉ số này phản ánh khả năng quản lý và tạo ra lợi nhuận từ vốn và tài sản. Mối quan hệ giữa các chỉ số này và Real_Return sẽ được phân tích.

  • Đòn bẩy (Leverage): Lý thuyết cấu trúc vốn (Modigliani & Miller) cho thấy việc sử dụng nợ có thể khuếch đại lợi nhuận (ROE) nhưng cũng làm tăng rủi ro tài chính. Tác động thực tế của Leverage_Ratio lên Real_ReturnROE sẽ được kiểm tra.

1.2.2. Các nghiên cứu thực nghiệm liên quan

Các nghiên cứu thực nghiệm trên thị trường chứng khoán, đặc biệt là NYSE và các thị trường phát triển, đã cung cấp nhiều bằng chứng về các yếu tố ảnh hưởng đến lợi suất:

  • Yếu tố ảnh hưởng Lợi suất: Nhiều nghiên cứu thực nghiệm (ví dụ: Al-Qenae et al., 2002; Al-Sharkas, 2004; Eita, 2012, trích dẫn trong AB Academies, 2021; Nguyen & Pham, 2023) đã xác nhận tác động của các biến số như EPS (+), Lãi suất (-), Lạm phát (-/+ tùy bối cảnh), Quy mô doanh nghiệp (+/- tùy nghiên cứu), Tỷ giá (+/- tùy ngành) lên giá cổ phiếu hoặc lợi suất. Nghiên cứu của ta sẽ kiểm tra lại các mối quan hệ này trong bộ dữ liệu cụ thể đang phân tích.

  • Hiệu quả Chiến lược đầu tư: Các nghiên cứu về bất thường thị trường thường kiểm chứng hiệu quả của các chiến lược như đầu tư giá trị (dựa trên P/B, P/E thấp), đầu tư theo đà (momentum - mua cổ phiếu tăng giá gần đây), hoặc đầu tư theo quy mô (cổ phiếu nhỏ). Phân tích của chúng ta về hiệu suất theo Holding_Period và mối quan hệ giữa Log_PEReal_Return sẽ cung cấp góc nhìn về hiệu quả tương đối của các chiến lược này.

  • Quan hệ Rủi ro - Lợi suất: Mối quan hệ dương giữa rủi ro (thường đo bằng Beta hoặc Độ lệch chuẩn - Volatility) và lợi suất kỳ vọng là nền tảng của tài chính hiện đại. Tuy nhiên, một số nghiên cứu thực nghiệm (đặc biệt là về “anomalies”) đôi khi tìm thấy mối quan hệ yếu hoặc thậm chí nghịch đảo (cổ phiếu rủi ro thấp lại có lợi suất cao hơn). Phân tích về Volatility_BuySharpe_Ratio sẽ đóng góp vào cuộc tranh luận này. Phát hiện sơ bộ về tương quan dương mạnh giữa Sharpe_RatioVolatility là một điểm cần thảo luận.

  • Ảnh hưởng của ESG: Các yếu tố Môi trường (Environmental), Xã hội (Social), và Quản trị (Governance) ngày càng được quan tâm. Nhiều nghiên cứu (chủ yếu gần đây) cho thấy các công ty có xếp hạng ESG cao hơn có thể có hiệu quả hoạt động tốt hơn và rủi ro thấp hơn trong dài hạn, mặc dù kết quả vẫn còn tranh cãi. Chúng ta sẽ phân tích mối quan hệ giữa biến ESG và các chỉ số hiệu suất (Real_Return, ROE) trong bộ dữ liệu này.

Kết luận lược khảo: Các lý thuyết và nghiên cứu thực nghiệm cung cấp một khung phân tích phong phú về các yếu tố có thể ảnh hưởng đến lợi suất đầu tư trên sàn NYSE. Phân tích dữ liệu khám phá (EDA) trong các mục tiếp theo sẽ đối chiếu các phát hiện từ bộ dữ liệu cụ thể này với các cơ sở lý luận và bằng chứng thực nghiệm đã có, nhằm đưa ra những kết luận sâu sắc và có ý nghĩa.

1.3. THỐNG KÊ MÔ TẢ

1.3.1. Thống kê mô tả tổng quan

1.3.1.1. Tóm tắt phân bố trung tâm và phân tán

# 1. Tải các thư viện cần thiết
library(dplyr)
library(knitr)
library(tibble)

# 2. Tải dữ liệu đã xử lý (phiên bản core - 32 biến)
load("nyse_processed_final.RData")

# 3. Chọn các biến định lượng quan trọng để tóm tắt
vars_to_summarize <- c("Real_Return", "Nominal_Return", "amount", "Horizon_Days",
                       "Volatility_Buy", "Sharpe_Ratio",
                       "Log_PE", "PB", "PS",
                       "ROE", "ROA", "NetProfitMargin",
                       "Leverage_Ratio", "Current_Ratio", "ESG")

# 4. Tính toán trực tiếp và trình bày dạng biến là hàng
cat(" 1.3.1.1: Tóm tắt Phân bố Trung tâm và Phân tán \n")
##  1.3.1.1: Tóm tắt Phân bố Trung tâm và Phân tán
summary_stats_wide <- nyse_clean_core %>%
  # Chọn các cột cần tóm tắt
  select(all_of(vars_to_summarize)) %>%
  # Tính toán từng thống kê mong muốn, xử lý NA
  summarise(across(everything(),
                   list(
                     Min    = ~ min(.x, na.rm = TRUE),
                     Q1     = ~ quantile(.x, 0.25, na.rm = TRUE),
                     Median = ~ median(.x, na.rm = TRUE),
                     Mean   = ~ mean(.x, na.rm = TRUE),
                     Q3     = ~ quantile(.x, 0.75, na.rm = TRUE),
                     Max    = ~ max(.x, na.rm = TRUE)
                   ),
                   # Đặt tên cột kết quả dạng: TenBien_TenThongKe
                   .names = "{.col}_{.fn}"
                   ))

# 5. Chuyển vị (Transpose) kết quả
# Chuyển tibble 1 hàng thành matrix, sau đó chuyển vị, rồi chuyển lại data frame
summary_transposed_df <- summary_stats_wide %>%
  as.matrix() %>%      # Chuyển thành ma trận
  t() %>%              # Chuyển vị (Transpose)
  as.data.frame()      # Chuyển lại thành data frame

# Đặt tên cột đầu tiên là "Value" (vì data frame chuyển vị chỉ có 1 cột)
colnames(summary_transposed_df) <- "Value"

# 6. Tách tên hàng (vd: "Real_Return_Min") thành tên biến và tên thống kê
summary_final_table <- summary_transposed_df %>%
  rownames_to_column(var = "VarStat") %>% # Chuyển tên hàng thành cột VarStat
  mutate(
    Statistic = gsub(".*_", "", VarStat), # Lấy phần sau dấu "_" (Min, Q1...)
    Variable = gsub("_.*", "", VarStat)   # Lấy phần trước dấu "_" (Real_Return...)
  ) %>%
  select(Variable, Statistic, Value) %>% # Chọn và sắp xếp lại cột
  # Sắp xếp lại thứ tự thống kê cho chuẩn
  mutate(Statistic = factor(Statistic, levels = c("Min", "Q1", "Median", "Mean", "Q3", "Max"))) %>%
  # Chuyển lại dạng rộng để trình bày bảng (Biến là hàng, Thống kê là cột)
  tidyr::pivot_wider(names_from = Statistic, values_from = Value) %>%
  # Làm tròn số cuối cùng
  mutate(across(where(is.numeric), ~ round(.x, 3))) %>%
  # Sắp xếp theo tên biến
  arrange(Variable)

# 7. In bảng kết quả bằng kable
kable(summary_final_table,
      caption = "Bảng 1.3.1: Thống kê Mô tả Tổng quan cho các Biến Định lượng Chính",
      col.names = c("Tên Biến", "Min", "Q1", "Median", "Mean", "Q3", "Max"), # Đặt tên cột rõ ràng
      format = "pipe",
      align = "l")
Bảng 1.3.1: Thống kê Mô tả Tổng quan cho các Biến Định lượng Chính
Tên Biến Min Q1 Median Mean Q3 Max
Current 0.610 0.980 1.220 2.173 1.790 13.560
ESG 12.000 16.300 25.100 22.571 27.900 31.600
Horizon 1.000 15.000 90.000 187.085 300.000 720.000
Leverage 1.103 2.486 3.439 5.212 6.692 34.545
Log 1.131 2.383 2.686 2.879 3.211 7.018
NetProfitMargin -24.630 2.620 7.700 9.205 15.770 62.000
Nominal -0.872 -0.028 0.014 0.071 0.111 8.847
PB 0.000 1.220 3.050 4.688 5.230 47.620
PS 0.160 0.470 1.710 2.725 3.180 24.490
ROA -12.990 1.740 5.710 5.596 7.990 38.130
ROE -99.490 8.830 16.100 15.644 26.030 57.250
Real -0.952 -0.621 0.167 0.087 0.486 16.353
Sharpe 0.090 0.185 0.232 0.254 0.307 0.698
Volatility 0.090 0.185 0.232 0.254 0.307 0.698
amount 50.000 400.000 2000.000 8108.475 10000.000 50000.000

Nhận xét phân tích 1.3.1.1: Bảng 1.3.1 cung cấp một cái nhìn tổng thể chi tiết về phân bố của 15 biến định lượng chính đã được chọn lọc và xử lý (từ nyse_clean_core):

  • Xu hướng Trung tâm:

    • Lợi suất: Lợi suất Thực tế (Real_Return) có Median = 0.167 (16.7%), cao hơn đáng kể so với Mean = 0.087 (8.7%), cho thấy phân bố lệch trái mạnh ở phần âm (do các khoản lỗ lớn). Lợi suất Danh nghĩa (Nominal_Return) cũng tương tự (Median=0.014, Mean=0.071).

    • Quy mô & Thời gian: Khoản đầu tư amount phổ biến (Median) là 2000 USD, nhưng Mean (8108 USD) cao hơn nhiều do các khoản đầu tư lớn. Thời gian nắm giữ Horizon_Days phổ biến (Median) là 90 ngày (3 tháng), Mean là 187 ngày (~6 tháng).

    • Định giá: Log_PE (đã chuẩn hóa) có Median = 2.686 (tương đương P/E ~14.7) và Mean = 2.879, khá gần nhau, xác nhận hiệu quả chuẩn hóa. PB (Giá/Giá trị sổ sách) có Median = 3.05, Mean = 4.69. PS (Giá/Doanh thu) có Median = 1.71, Mean = 2.73. Cả PBPS đều lệch phải.

    • Hiệu quả HĐ: ROEMedian = 16.1%, Mean = 15.6%. ROAMedian = 5.7%, Mean = 5.6%. NetProfitMarginMedian = 7.7%, Mean = 9.2%. Các chỉ số hiệu quả này cho thấy mức sinh lời trung bình khá, với ROE có vẻ đối xứng hơn ROANetProfitMargin.

    • Rủi ro & Các chỉ số khác: Volatility_BuySharpe_RatioMedianMean rất gần nhau (lần lượt ~0.23/0.25 và ~0.23/0.25), cho thấy phân bố tương đối đối xứng. Leverage_Ratio lệch phải (Median=3.4, Mean=5.2). Current_Ratio lệch phải mạnh (Median=1.2, Mean=2.2). ESG gần đối xứng (Median=25.1, Mean=22.6).

  • Độ Phân tán:

    • Khoảng Min-Max cực lớn của Real_Return (-0.952 đến 16.353) và Nominal_Return (-0.872 đến 8.847) khẳng định rủi ro và tiềm năng lợi nhuận/thua lỗ rất cao.

    • Các chỉ số định giá PB (0 đến 47.6) và PS (0.16 đến 24.5) cũng có biên độ rất rộng.

    • ROE có biên độ rất lớn (-99.5% đến 57.3%), trong khi ROA hẹp hơn (-13.0% đến 38.1%).

    • Leverage_Ratio (1.1 đến 34.5) và Current_Ratio (0.6 đến 13.6) cũng cho thấy sự khác biệt lớn về cấu trúc tài chính giữa các công ty.

  • Kết luận Sơ bộ: Bộ dữ liệu phản ánh một thị trường đầu tư năng động với sự đa dạng lớn về lợi suất, rủi ro, định giá và hiệu quả hoạt động. Sự tồn tại của các phân bố lệch và biên độ dao động rộng cho thấy tầm quan trọng của việc phân tích sâu hơn về outliers, hình dạng phân phối và kiểm định sự khác biệt giữa các nhóm để rút ra kết luận đáng tin cậy.

1.3.1.2. Tính toán độ lệch chuẩn

# 1. Tính toán độ lệch chuẩn (SD) cho các biến đã chọn ở trên
# Sử dụng summarise() và across() để tính SD cho nhiều cột
sd_stats <- nyse_clean_core %>%
  summarise(across(all_of(vars_to_summarize),
                   ~ sd(.x, na.rm = TRUE), # Hàm tính SD, bỏ qua NA
                   .names = "SD_{.col}")) # Đặt tên cột kết quả là SD_TênBiến

# 2. Chuyển kết quả sang dạng dài để trình bày bằng kable
sd_table <- sd_stats %>%
  tidyr::pivot_longer(everything(), names_to = "Variable", values_to = "Standard_Deviation") %>%
  # Làm tròn giá trị SD
  mutate(Standard_Deviation = round(Standard_Deviation, 3)) %>%
  # Sắp xếp theo tên biến cho dễ theo dõi
  arrange(Variable)

# 3. Trình bày bảng Độ lệch chuẩn
cat("\n 1.3.1.2: Tính toán Độ lệch chuẩn \n")
## 
##  1.3.1.2: Tính toán Độ lệch chuẩn
kable(sd_table,
      caption = "Bảng 1.3.2: Độ lệch chuẩn của các Biến Định lượng Chính",
      col.names = c("Tên Biến (Đã chuẩn hóa)", "Độ lệch chuẩn (SD)"),
      format = "pipe",
      align = "l")
Bảng 1.3.2: Độ lệch chuẩn của các Biến Định lượng Chính
Tên Biến (Đã chuẩn hóa) Độ lệch chuẩn (SD)
SD_Current_Ratio 2.564
SD_ESG 6.510
SD_Horizon_Days 210.703
SD_Leverage_Ratio 4.986
SD_Log_PE 0.845
SD_NetProfitMargin 10.407
SD_Nominal_Return 0.299
SD_PB 5.909
SD_PS 3.601
SD_ROA 5.978
SD_ROE 17.479
SD_Real_Return 0.774
SD_Sharpe_Ratio 0.098
SD_Volatility_Buy 0.098
SD_amount 12774.429

Nhận xét phân tích 1.3.1.2:

Bảng 1.3.2 định lượng mức độ phân tán (biến động) tuyệt đối của từng biến thông qua Độ lệch chuẩn (SD):

  • Rủi ro/Biến động Lợi suất: Real_Return (SD = 0.774) và Nominal_Return (SD = 0.299) có độ lệch chuẩn rất lớn so với giá trị trung bình tương ứng (Mean Real_Return = 0.087, Mean Nominal_Return = 0.071 từ Bảng 1.3.1). Điều này tái khẳng định mức độ rủi ro và sự biến động cực kỳ cao của lợi suất đầu tư trên thị trường cổ phiếu NYSE trong mẫu dữ liệu này.

  • Biến động Quy mô & Thời gian: amount (SD = 12,774 USD) có độ lệch chuẩn thậm chí còn lớn hơn giá trị trung bình (Mean = 8,108 USD), cho thấy sự phân tán cực mạnh trong quy mô các khoản đầu tư. Horizon_Days (SD = 210.7 ngày) cũng có độ biến động đáng kể so với trung bình (Mean = 187 ngày).

  • Biến động Rủi ro (Volatility): Volatility_Buy (SD = 0.098) cho thấy mức độ rủi ro (đo bằng Volatility) cũng có sự khác biệt đáng kể giữa các cổ phiếu/thời điểm mua, mặc dù SD tương đối nhỏ hơn so với giá trị trung bình (Mean = 0.254).

  • Biến động Định giá: Log_PE (SD = 0.845) có độ lệch chuẩn tương đối nhỏ so với giá trị trung bình (Mean = 2.88), cho thấy sau khi chuẩn hóa logarit, mức độ biến động tương đối của định giá P/E đã giảm bớt và tập trung hơn. Ngược lại, các chỉ số định giá gốc như PB (SD = 5.91) và PS (SD = 3.60) vẫn cho thấy sự phân tán tuyệt đối rất lớn.

  • Biến động Hiệu quả HĐ: ROE (SD = 17.48) có độ lệch chuẩn rất cao, thậm chí lớn hơn giá trị trung bình (Mean = 15.6), phản ánh sự khác biệt cực lớn về hiệu quả sinh lời giữa các công ty/giai đoạn. ROA (SD = 5.98) và NetProfitMargin (SD = 10.41) cũng có độ lệch chuẩn đáng kể so với trung bình tương ứng (Mean ROA = 5.6, Mean NetProfitMargin = 9.2).

  • Độ ổn định tương đối: Các biến như Sharpe_Ratio (SD = 0.098) và ESG (SD = 6.51) có độ lệch chuẩn tương đối nhỏ hơn so với giá trị trung bình của chúng, cho thấy mức độ biến động thấp hơn so với các chỉ số lợi suất hay hiệu quả hoạt động. Current_Ratio (SD = 2.56) và Leverage_Ratio (SD = 4.99) cũng có độ lệch chuẩn đáng kể.

  • Kết luận: Độ lệch chuẩn xác nhận mức độ biến động cao và rủi ro đáng kể đối với các biến liên quan đến lợi suất, quy mô đầu tư và hiệu quả hoạt động. Các chỉ số định giá (trừ Log_PE) cũng phân tán mạnh. Các yếu tố như Sharpe Ratio và ESG có vẻ ổn định hơn trong bộ dữ liệu này.

1.3.2. Phân tích tần suất và phân vị

1.3.2.1. Bảng tần suất biến phân loại

# 1. Tải các thư viện cần thiết
library(dplyr)
library(knitr)
library(tidyr) 

# 3. Tính toán và trình bày bảng tần suất cho từng biến Factor quan trọng
cat("1.3.2.1: Bảng Tần suất Biến Phân loại\n")
## 1.3.2.1: Bảng Tần suất Biến Phân loại
# Hàm trợ giúp để tạo bảng tần suất đẹp
create_freq_table <- function(data, var_name, caption_text) {
  var_sym <- sym(var_name) # Chuyển tên biến (chuỗi) thành biểu tượng
  
  freq_table <- data %>%
    count({{ var_sym }}, name = "SoLuong") %>% # Đếm số lượng theo biến
    # Kiểm tra xem có NA không, nếu có thì báo cáo
    mutate(TyLe_PhanTram = round((SoLuong / sum(SoLuong)) * 100, 2)) %>% # Tính tỷ lệ %
    arrange(desc(SoLuong)) # Sắp xếp giảm dần theo số lượng
    
  # In bảng bằng kable
  print(kable(freq_table,
              caption = caption_text,
              col.names = c(var_name, "Số lượng", "Tỷ lệ (%)"),
              format = "pipe", align = "l"))
  cat("\n") # Thêm dòng trống
}

# 4. Áp dụng hàm cho các biến Factor đã tạo/chuẩn hóa
create_freq_table(nyse_clean_core, "sector", "Bảng 1.3.3: Phân bổ Giao dịch theo Ngành")
## 
## 
## Table: Bảng 1.3.3: Phân bổ Giao dịch theo Ngành
## 
## |sector |Số lượng |Tỷ lệ (%) |
## |:------|:--------|:---------|
## |RETAIL |96269    |23.75     |
## |TECH   |92401    |22.80     |
## |BANK   |84757    |20.91     |
## |AUTO   |79836    |19.70     |
## |FMCG   |51995    |12.83     |
create_freq_table(nyse_clean_core, "investment", "Bảng 1.3.4: Phân bổ Giao dịch theo Kết quả Đầu tư")
## 
## 
## Table: Bảng 1.3.4: Phân bổ Giao dịch theo Kết quả Đầu tư
## 
## |investment |Số lượng |Tỷ lệ (%) |
## |:----------|:--------|:---------|
## |BAD        |264440   |65.25     |
## |GOOD       |140818   |34.75     |
create_freq_table(nyse_clean_core, "Holding_Period", "Bảng 1.3.5: Phân bổ Giao dịch theo Thời gian Nắm giữ")
## 
## 
## Table: Bảng 1.3.5: Phân bổ Giao dịch theo Thời gian Nắm giữ
## 
## |Holding_Period     |Số lượng |Tỷ lệ (%) |
## |:------------------|:--------|:---------|
## |Long-term (>180d)  |147526   |36.40     |
## |Short-term (<=30d) |135001   |33.31     |
## |Mid-term (31-180d) |122731   |30.28     |
create_freq_table(nyse_clean_core, "Risk_Level", "Bảng 1.3.6: Phân bổ Giao dịch theo Mức độ Rủi ro")
## 
## 
## Table: Bảng 1.3.6: Phân bổ Giao dịch theo Mức độ Rủi ro
## 
## |Risk_Level |Số lượng |Tỷ lệ (%) |
## |:----------|:--------|:---------|
## |High       |137771   |34        |
## |Medium     |133747   |33        |
## |Low        |133740   |33        |
create_freq_table(nyse_clean_core, "Amount_Level", "Bảng 1.3.7: Phân bổ Giao dịch theo Quy mô Đầu tư")
## 
## 
## Table: Bảng 1.3.7: Phân bổ Giao dịch theo Quy mô Đầu tư
## 
## |Amount_Level |Số lượng |Tỷ lệ (%) |
## |:------------|:--------|:---------|
## |Medium       |143246   |35.35     |
## |Small        |142692   |35.21     |
## |Large        |119320   |29.44     |

Nhận xét phän tích 1.3.2.1:

  • Phân bổ theo Ngành (sector - Bảng 1.3.3):

    • Kết quả cho thấy sự tập trung đáng kể vào ba ngành chính: RETAIL (Bán lẻ - 23.75%), TECH (Công nghệ - 22.80%), và BANK (Ngân hàng - 20.91%). Ba ngành này chiếm gần 2/3 tổng số giao dịch (∼67.4%).

    • Ngành AUTO (Ô tô - 19.70%) cũng có tỷ trọng đáng kể.

    • Ngành FMCG (Hàng tiêu dùng nhanh - 12.83%) có tần suất thấp nhất.

    • Sự phân bổ này cho thấy bộ dữ liệu có tính đại diện cho các lĩnh vực kinh tế chính của thị trường NYSE, đặc biệt là các ngành dịch vụ, công nghệ và tài chính, nhưng ngành FMCG có thể ít được đại diện hơn.

  • Phân bổ theo Kết quả Đầu tư (investment - Bảng 1.3.4):

    • Bảng này cho thấy sự mất cân bằng lớp (class imbalance) rất rõ rệt. Các khoản đầu tư được phân loại là BAD (Thua lỗ/Kém hiệu quả) chiếm tỷ trọng áp đảo với 65.25%, gấp gần đôi so với nhóm GOOD (Sinh lời/Hiệu quả) chỉ chiếm 34.75%.

    • Điều này phản ánh thực tế rằng việc đạt được lợi nhuận thực tế vượt trội (định nghĩa của GOOD) trên thị trường chứng khoán là một thách thức, và số lượng giao dịch không thành công thường nhiều hơn. Sự mất cân bằng này cần được lưu ý khi xây dựng các mô hình dự đoán biến investment.

  • Phân bổ theo Thời gian Nắm giữ (Holding_Period - Bảng 1.3.5):

    • Kết quả tái khẳng định sự phân bổ tương đối đồng đều giữa ba chiến lược đã tạo ra ở Mục 1.1.3.6: Long-term (>180d) chiếm tỷ trọng lớn nhất (36.40%), tiếp theo là Short-term (<=30d) (33.31%) và Mid-term (31-180d) (30.28%).

    • Mặc dù Long-term chiếm ưu thế nhẹ, sự hiện diện đáng kể của cả ba nhóm cho phép phân tích so sánh hiệu quả của các chiến lược thời gian khác nhau.

  • Phân bổ theo Mức độ Rủi ro (Risk_Level - Bảng 1.3.6):

    • Do biến Risk_Level được tạo ra dựa trên phân vị (terciles - chia 3 phần bằng nhau), kết quả tần suất cho thấy sự phân bổ cực kỳ đồng đều giữa ba nhóm: High (34%), Medium (33%), và Low (33%).

    • Điều này đảm bảo rằng khi chúng ta so sánh hiệu suất giữa các nhóm rủi ro, mỗi nhóm đều có số lượng quan sát đủ lớn và tương đương nhau, giúp kết quả so sánh đáng tin cậy hơn.

  • Phân bổ theo Quy mô Đầu tư (Amount_Level - Bảng 1.3.7):

    • Tương tự như Risk_Level, biến Amount_Level cũng được tạo từ phân vị. Kết quả cho thấy nhóm Medium (35.35%) và Small (35.21%) có tỷ trọng lớn hơn một chút so với nhóm Large (29.44%).

    • Sự phân bổ này vẫn đủ cân bằng để phân tích ảnh hưởng của quy mô giao dịch lên các yếu tố khác. Việc nhóm Large có tỷ lệ thấp hơn một chút có thể phản ánh thực tế rằng các giao dịch với số tiền rất lớn (>5000 USD theo ngưỡng phân vị) ít phổ biến hơn.

Kết luận: Phân tích tần suất các biến phân loại cho thấy bộ dữ liệu có tính đa dạng về ngành nghề và chiến lược đầu tư. Tuy nhiên, có sự mất cân bằng đáng kể về kết quả đầu tư (đa số là BAD). Các biến phân loại dựa trên phân vị (Risk_Level, Amount_Level) có sự phân bổ đồng đều, thuận lợi cho các phân tích so sánh nhóm sau này.

1.3.2.2. Phân tích phân vị biến định lượng

# 1. Chọn các biến định lượng quan trọng cần phân tích phân vị
vars_for_quantile <- c("Real_Return", "amount", "Volatility_Buy", 
                       "Log_PE", "Leverage_Ratio", "Sharpe_Ratio")

# 2. Tính toán các phân vị thường dùng (0%, 25%, 50%, 75%, 100%)
# Sử dụng sapply để áp dụng hàm quantile cho từng cột đã chọn
quantile_results <- sapply(nyse_clean_core[vars_for_quantile], 
                           quantile, 
                           probs = c(0, 0.25, 0.5, 0.75, 1), 
                           na.rm = TRUE) # Bỏ qua NA

# 3. Làm tròn kết quả và chuyển đổi thành data frame để trình bày
quantile_df <- as.data.frame(round(quantile_results, 3))

# Thêm cột tên Phân vị (0%, 25%...)
quantile_df <- tibble::rownames_to_column(quantile_df, var = "Percentile")

# 4. Trình bày bảng Phân vị bằng kable
cat("\n--- 1.3.2.2: Phân tích Phân vị Biến Định lượng ---\n")
## 
## --- 1.3.2.2: Phân tích Phân vị Biến Định lượng ---
kable(quantile_df,
      caption = "Bảng 1.3.8: Các điểm phân vị của các Biến Định lượng Chính",
      # Tên cột sẽ là tên biến, hàng là tên phân vị
      format = "pipe",
      align = "l")
Bảng 1.3.8: Các điểm phân vị của các Biến Định lượng Chính
Percentile Real_Return amount Volatility_Buy Log_PE Leverage_Ratio Sharpe_Ratio
0% -0.952 50 0.090 1.131 1.103 0.090
25% -0.621 400 0.185 2.383 2.486 0.185
50% 0.167 2000 0.232 2.686 3.439 0.232
75% 0.486 10000 0.307 3.211 6.692 0.307
100% 16.353 50000 0.698 7.018 34.545 0.698

Nhận xét Phân tích 1.3.2.2:

  • Lợi suất Thực tế (Real_Return):

    • Phạm vi cực đoan: Từ -0.952 (-95.2%) đến 16.353 (+1635.3%).

    • Tập trung chính: 50% dữ liệu ở giữa (IQR) nằm trong khoảng khá rộng từ -0.621 (Q1) đến 0.486 (Q3).

    • Điểm giữa (Median): 0.167 (16.7%), xác nhận đa số giao dịch có lãi thực.

  • Quy mô Giao dịch (amount):

    • Phạm vi: Từ 50 USD đến 50,000 USD.

    • Tập trung chính: 50% giao dịch ở giữa có quy mô từ 400 USD (Q1) đến 10,000 USD (Q3).

    • Điểm giữa (Median): 2,000 USD. Điều này cho thấy đa số giao dịch có quy mô nhỏ đến trung bình.

  • Rủi ro (Volatility_Buy):

    • Phạm vi: Từ 0.090 đến 0.698.

    • Tập trung chính: 50% giao dịch ở giữa có độ biến động từ 0.185 (Q1) đến 0.307 (Q3).

    • Điểm giữa (Median): 0.232. Phân bố tương đối hẹp và tập trung quanh mức rủi ro thấp đến trung bình.

  • Định giá (Log_PE):

    • Phạm vi (sau log): Từ 1.131 đến 7.018.

    • Tập trung chính: 50% ở giữa nằm từ 2.383 (Q1, P/E ~10.8) đến 3.211 (Q3, P/E ~24.8).

    • Điểm giữa (Median): 2.686 (P/E ~14.7). Phân bố khá tập trung sau khi chuẩn hóa.

  • Đòn bẩy (Leverage_Ratio):

    • Phạm vi: Từ 1.103 đến 34.545.

    • Tập trung chính: 50% ở giữa nằm từ 2.486 (Q1) đến 6.692 (Q3).

    • Điểm giữa (Median): 3.439. Cho thấy mức đòn bẩy phổ biến là khoảng 3.4 lần.

  • Hiệu quả Điều chỉnh Rủi ro (Sharpe_Ratio):

    • Phạm vi: Từ 0.090 đến 0.698 (luôn dương).

    • Tập trung chính: 50% ở giữa nằm trong khoảng hẹp từ 0.185 (Q1) đến 0.307 (Q3).

    • Điểm giữa (Median): 0.232. Phân bố rất tập trung.

Kết luận: Phân tích phân vị xác nhận lại biên độ dao động lớn của lợi suất và quy mô đầu tư. Các chỉ số như rủi ro (Volatility_Buy), định giá (Log_PE), và hiệu quả điều chỉnh rủi ro (Sharpe_Ratio) có phân bố tập trung hơn. Khoảng IQR cung cấp thước đo hữu ích về phạm vi bình thường của từng biến.

1.3.2.3. Tần suất lợi suất Dương/Âm

# 1. Tạo biến phân loại Lợi suất Dương/Âm
cat("\n 1.3.2.3: Tần suất Lợi suất Thực tế Dương/Âm \n")
## 
##  1.3.2.3: Tần suất Lợi suất Thực tế Dương/Âm
return_sign_freq <- nyse_clean_core %>%
  # Tạo biến mới 'Return_Sign' dựa trên Real_Return
  mutate(Return_Sign = case_when(
    Real_Return > 0 ~ "Lợi suất Dương (>0)",
    Real_Return <= 0 ~ "Lợi suất Âm (<=0)",
    TRUE ~ "NA" # Xử lý trường hợp Real_Return là NA (nếu có)
  )) %>%
  # Đếm tần suất theo biến mới tạo
  count(Return_Sign, name = "SoLuong") %>%
  # Tính tỷ lệ phần trăm
  mutate(TyLe_PhanTram = round((SoLuong / sum(SoLuong)) * 100, 2))

# 2. Trình bày bảng kết quả
kable(return_sign_freq,
      caption = "Bảng 1.3.9: Tần suất Giao dịch theo Dấu của Lợi suất Thực tế",
      col.names = c("Dấu Lợi suất Thực tế", "Số lượng", "Tỷ lệ (%)"),
      format = "pipe", align = "l")
Bảng 1.3.9: Tần suất Giao dịch theo Dấu của Lợi suất Thực tế
Dấu Lợi suất Thực tế Số lượng Tỷ lệ (%)
Lợi suất Dương (>0) 229767 56.7
Lợi suất Âm (<=0) 175491 43.3

Nhận xét phân tích 1.3.2.3:

Bảng 1.3.9 phân loại các giao dịch dựa trên dấu của Lợi suất Thực tế (Real_Return), cung cấp một góc nhìn trực diện về tỷ lệ thành công/thất bại sau khi đã điều chỉnh lạm phát:

  • Tỷ lệ Lãi/Lỗ Thực tế: Kết quả cho thấy có 56.7% (229,767 giao dịch) đạt được lợi suất thực tế dương (Real_Return > 0), nghĩa là làm tăng sức mua cho nhà đầu tư. Ngược lại, 43.3% (175,491 giao dịch) có lợi suất thực tế âm hoặc bằng không, tức là làm giảm hoặc không thay đổi sức mua.

  • So sánh với investment: Tỷ lệ lợi suất thực tế dương (56.7%) cao hơn đáng kể so với tỷ lệ các khoản đầu tư được phân loại là GOOD (34.75% - Bảng 1.3.4). Điều này cho thấy rằng tiêu chí để phân loại một khoản đầu tư là GOOD trong bộ dữ liệu này có thể khắt khe hơn, không chỉ đơn thuần là Real_Return > 0 mà có thể yêu cầu một mức lợi suất tối thiểu nào đó hoặc kết hợp thêm các yếu tố khác. Tuy nhiên, việc đa số giao dịch (56.7%) vẫn có lãi thực là một tín hiệu tích cực về tiềm năng sinh lời chung của thị trường được mô phỏng.

1.3.2.4. Tần suất đầu tư theo ngưỡng Rủi ro (Risk_Level)

# 1. Trình bày lại bảng tần suất cho Risk_Level (đã tính ở 1.1.3.8)
cat("\n 1.3.2.4: Tần suất Đầu tư theo Ngưỡng Rủi ro \n")
## 
##  1.3.2.4: Tần suất Đầu tư theo Ngưỡng Rủi ro
# (Biến risk_level_freq đã được tạo ở Mục 1.1.3.8)
# In lại bảng đó
if(exists("risk_level_freq")){
  kable(risk_level_freq,
        caption = "Bảng 1.3.10: Phân bổ Giao dịch theo Mức độ Rủi ro (Nhắc lại)",
        col.names = c("Mức Rủi ro", "Số lượng", "Tỷ lệ (%)"),
        format = "pipe", align = "l")
} else {
  cat("Biến risk_level_freq chưa được tạo. Vui lòng chạy lại Mục 1.1.3.8.\n")
}
Bảng 1.3.10: Phân bổ Giao dịch theo Mức độ Rủi ro (Nhắc lại)
Mức Rủi ro Số lượng Tỷ lệ (%)
Low 133740 33
Medium 133747 33
High 137771 34

Nhận xét phân tích 1.3.2.4:

Bảng 1.3.10 tái khẳng định sự phân bổ đồng đều của các giao dịch giữa ba nhóm rủi ro (Low, Medium, High) do biến Risk_Level được tạo ra dựa trên phân vị. Mỗi nhóm chiếm khoảng 1/3 tổng số quan sát, tạo điều kiện thuận lợi cho việc so sánh hiệu suất và đặc điểm giữa các nhóm rủi ro khác nhau trong các phân tích tiếp theo.

1.3.3. Phân tích hình dạng phân phối

1.3.3.1. Đo lường Độ xiên

# 1. Tải thư viện cần thiết
library(dplyr)
library(knitr)
library(moments) # Chứa hàm skewness() và kurtosis()

# 2. Chọn các biến để tính độ xiên
vars_for_shape <- c("Real_Return", "Nominal_Return", "amount", "Horizon_Days",
                    "Volatility_Buy", "Sharpe_Ratio", "Log_PE", "PB", "PS",
                    "ROE", "ROA", "NetProfitMargin", "Leverage_Ratio", 
                    "Current_Ratio", "ESG")

# 3. Tính toán Độ xiên (Skewness) cho từng biến
# Sử dụng sapply để áp dụng hàm skewness
skewness_values <- sapply(nyse_clean_core[vars_for_shape], 
                          skewness, 
                          na.rm = TRUE) # Bỏ qua NA

# 5. Tạo bảng kết quả độ xiên
skewness_table <- data.frame(
  Variable = names(skewness_values),
  Skewness = round(skewness_values, 3)
) %>% arrange(Variable) # Sắp xếp theo tên biến

# 6. Trình bày bảng Độ xiên
cat(" 1.3.3.1: Đo lường Độ xiên (Skewness) \n")
##  1.3.3.1: Đo lường Độ xiên (Skewness)
kable(skewness_table,
      caption = "Bảng 1.3.11: Độ xiên của các Biến Định lượng Chính",
      col.names = c("Tên Biến", "Độ xiên (Skewness)"),
      format = "pipe",
      align = "l")
Bảng 1.3.11: Độ xiên của các Biến Định lượng Chính
Tên Biến Độ xiên (Skewness)
Current_Ratio Current_Ratio 2.831
ESG ESG -0.246
Horizon_Days Horizon_Days 1.108
Leverage_Ratio Leverage_Ratio 2.747
Log_PE Log_PE 1.665
NetProfitMargin NetProfitMargin 0.199
Nominal_Return Nominal_Return 7.522
PB PB 3.075
PS PS 2.593
ROA ROA 0.958
ROE ROE -2.013
Real_Return Real_Return 2.752
Sharpe_Ratio Sharpe_Ratio 1.104
Volatility_Buy Volatility_Buy 1.104
amount amount 2.140
# 7. Diễn giải sơ bộ về độ xiên:
# Skewness = 0: Đối xứng hoàn hảo (như phân phối chuẩn)
# Skewness > 0: Lệch phải (đuôi kéo dài về phía giá trị lớn)
# Skewness < 0: Lệch trái (đuôi kéo dài về phía giá trị nhỏ)
# |Skewness| > 1: Độ lệch đáng kể

Nhận xét phân tích 1.3.3.1:

Bảng 1.3.11 định lượng mức độ đối xứng của phân phối cho các biến chính:

  • Lệch Phải Mạnh (|Skewness| > 1): Rất nhiều biến thể hiện độ lệch phải đáng kể, bao gồm Nominal_Return (7.52), PB (3.08), PS (2.59), amount (2.14), Leverage_Ratio (2.75), Current_Ratio (2.83), Real_Return (2.75), Log_PE (1.67), Horizon_Days (1.11), Sharpe_Ratio (1.10), và Volatility_Buy (1.10). Độ lệch phải dương cho thấy đuôi phân phối kéo dài về phía các giá trị lớn (ví dụ: các khoản lãi rất cao, P/E rất cao, số tiền đầu tư rất lớn), và phần lớn dữ liệu tập trung ở phía giá trị thấp hơn.

  • Lệch Trái Mạnh (|Skewness| <- 1): Chỉ có ROE (-2.01) thể hiện độ lệch trái đáng kể, cho thấy có một số công ty/giai đoạn với ROE cực kỳ thấp (âm sâu) kéo đuôi phân phối về phía giá trị nhỏ.

  • Gần Đối xứng : Các biến ROA (0.96), NetProfitMargin (0.20), và ESG (-0.25) có độ lệch thấp hơn, gần với phân phối đối xứng hơn, mặc dù ROA vẫn có độ lệch phải nhẹ đáng kể.

  • Kết luận: Hầu hết các biến quan trọng trong bộ dữ liệu đều có phân phối không đối xứng đáng kể, chủ yếu là lệch phải. Điều này vi phạm giả định về tính chuẩn và cần được lưu ý khi lựa chọn phương pháp phân tích hoặc cần xem xét các phép biến đổi dữ liệu bổ sung (ngoài Log_PE đã làm).

1.3.3.2. Đo lường Độ nhọn

# 1. Tính toán Độ nhọn (Kurtosis) cho các biến đã chọn
# Lưu ý: Hàm kurtosis() trong gói 'moments' tính Excess Kurtosis 
# (Kurtosis - 3). Giá trị > 0 nghĩa là nhọn hơn phân phối chuẩn.
cat("\n 1.3.3.2: Đo lường Độ nhọn (Kurtosis) \n")
## 
##  1.3.3.2: Đo lường Độ nhọn (Kurtosis)
kurtosis_values <- sapply(nyse_clean_core[vars_for_shape], 
                          kurtosis, 
                          na.rm = TRUE)

# 2. Tạo bảng kết quả độ nhọn
kurtosis_table <- data.frame(
  Variable = names(kurtosis_values),
  Excess_Kurtosis = round(kurtosis_values, 3)
) %>% arrange(Variable)

# 3. Trình bày bảng Độ nhọn
kable(kurtosis_table,
      caption = "Bảng 1.3.12: Độ nhọn (Excess Kurtosis) của các Biến Định lượng Chính",
      col.names = c("Tên Biến", "Độ nhọn (Kurtosis - 3)"),
      format = "pipe",
      align = "l")
Bảng 1.3.12: Độ nhọn (Excess Kurtosis) của các Biến Định lượng Chính
Tên Biến Độ nhọn (Kurtosis - 3)
Current_Ratio Current_Ratio 10.587
ESG ESG 1.553
Horizon_Days Horizon_Days 3.044
Leverage_Ratio Leverage_Ratio 11.590
Log_PE Log_PE 7.610
NetProfitMargin NetProfitMargin 4.563
Nominal_Return Nominal_Return 117.299
PB PB 14.988
PS PS 10.195
ROA ROA 7.187
ROE ROE 12.810
Real_Return Real_Return 31.866
Sharpe_Ratio Sharpe_Ratio 4.390
Volatility_Buy Volatility_Buy 4.390
amount amount 7.052
# 4. Diễn giải sơ bộ về độ nhọn (Excess Kurtosis):
# Kurtosis = 0: Độ nhọn tương tự phân phối chuẩn (Mesokurtic)
# Kurtosis > 0: Nhọn hơn phân phối chuẩn, đuôi dày hơn (Leptokurtic - rủi ro outlier cao)
# Kurtosis < 0: Bẹt hơn phân phối chuẩn, đuôi mỏng hơn (Platykurtic)

Nhận xét phân tích 1.3.3.2:

Bảng 1.3.12 đo lường độ “nhọn” của đỉnh và độ “dày” của đuôi phân phối so với phân phối chuẩn (Excess Kurtosis > 0 là nhọn hơn và đuôi dày hơn - Leptokurtic):

  • Độ nhọn Cực cao (Kurtosis >> 3): Nominal_Return (117.3) và Real_Return (31.9) có độ nhọn cực kỳ cao. Điều này cho thấy phân phối của lợi suất tập trung rất mạnh quanh giá trị trung tâm nhưng lại có phần đuôi rất “dày” (heavy tails), nghĩa là các sự kiện lợi nhuận/thua lỗ cực đoan (outliers) xảy ra thường xuyên hơn nhiều so với dự đoán của phân phối chuẩn. Đây là đặc điểm phổ biến của dữ liệu lợi suất tài chính.

  • Độ nhọn Cao (Kurtosis > 3): Nhiều biến khác cũng có độ nhọn cao hơn đáng kể so với phân phối chuẩn, bao gồm PB (15.0), Leverage_Ratio (11.6), Current_Ratio (10.6), PS (10.2), Log_PE (7.6), amount (7.1), ROA (7.2), ROE (12.8), NetProfitMargin (4.6), Volatility_Buy (4.4), Sharpe_Ratio (4.4), và Horizon_Days (3.0). Điều này cho thấy các biến này cũng có xu hướng tập trung quanh trung tâm và có đuôi dày hơn chuẩn.

  • Gần Chuẩn: Chỉ có ESG (1.55) có độ nhọn gần với phân phối chuẩn hơn cả.

  • Kết luận: Hầu hết các biến định lượng chính đều có phân phối Leptokurtic (nhọn hơn và đuôi dày hơn chuẩn). Điều này hàm ý rằng rủi ro xảy ra các giá trị cực đoan (outliers) là cao hơn so với giả định phân phối chuẩn, một yếu tố quan trọng cần xem xét trong quản lý rủi ro và mô hình hóa.

1.3.3.3. Kiểm định tính phân phối chuẩn

# 1. Lưu ý về kích thước mẫu:
# Các kiểm định chuẩn như Shapiro-Wilk rất nhạy với cỡ mẫu lớn.
# Với N > 400,000, kiểm định gần như chắc chắn sẽ bác bỏ giả thuyết H0 (phân phối chuẩn), ngay cả khi độ lệch không quá lớn về mặt thực tế.
# Do đó, ta sẽ thực hiện kiểm định trên một mẫu con nhỏ (ví dụ: 5000)
# để có đánh giá sơ bộ, kết hợp với phân tích Skewness, Kurtosis và QQ-Plot.
cat("\n 1.3.3.3: Kiểm định Tính Phân phối Chuẩn (trên mẫu con) \n")
## 
##  1.3.3.3: Kiểm định Tính Phân phối Chuẩn (trên mẫu con)
set.seed(123) # Đảm bảo tính lặp lại của mẫu ngẫu nhiên
sample_size <- 5000 
if (nrow(nyse_clean_core) >= sample_size) {
  nyse_sample <- nyse_clean_core %>% sample_n(sample_size)
  
# 2. Thực hiện Shapiro-Wilk test cho Real_Return và Log_PE trên mẫu con
# Giả thuyết H0: Dữ liệu tuân theo phân phối chuẩn
# Nếu p-value < 0.05, bác bỏ H0
  
# Kiểm định cho Real_Return (loại bỏ NA nếu có)
  shapiro_test_real_return <- shapiro.test(na.omit(nyse_sample$Real_Return))
  cat("Kết quả Shapiro-Wilk Test cho Real_Return (mẫu N=5000):\n")
  print(shapiro_test_real_return)
  
# Kiểm định cho Log_PE (loại bỏ NA nếu có)
  shapiro_test_log_pe <- shapiro.test(na.omit(nyse_sample$Log_PE))
  cat("\nKết quả Shapiro-Wilk Test cho Log_PE (mẫu N=5000):\n")
  print(shapiro_test_log_pe)
  
} else {
  cat("Kích thước mẫu gốc nhỏ hơn 5000, không thể lấy mẫu con.\n")
}
## Kết quả Shapiro-Wilk Test cho Real_Return (mẫu N=5000):
## 
##  Shapiro-Wilk normality test
## 
## data:  na.omit(nyse_sample$Real_Return)
## W = 0.77222, p-value < 2.2e-16
## 
## 
## Kết quả Shapiro-Wilk Test cho Log_PE (mẫu N=5000):
## 
##  Shapiro-Wilk normality test
## 
## data:  na.omit(nyse_sample$Log_PE)
## W = 0.87725, p-value < 2.2e-16
# 3. Kết luận sơ bộ từ p-value:
# Nếu p-value rất nhỏ (thường < 2.2e-16), có bằng chứng mạnh mẽ để bác bỏ giả thuyết phân phối chuẩn.

Nhận xét phân tích 1.3.3.3:

Kết quả kiểm định Shapiro-Wilk trên mẫu con (N=5000) cho cả Real_ReturnLog_PE đều cho giá trị p-value cực kỳ nhỏ (< 2.2e-16).

  • Bác bỏ Giả thuyết Chuẩn: Với p-value nhỏ hơn mức ý nghĩa thông thường (ví dụ: 0.05), chúng ta có bằng chứng thống kê rất mạnh mẽ để bác bỏ giả thuyết H0 rằng dữ liệu của Real_ReturnLog_PE (ngay cả sau khi biến đổi log) tuân theo phân phối chuẩn.

  • Kết hợp với Skewness & Kurtosis: Kết quả kiểm định này hoàn toàn phù hợp với các giá trị Skewness và Kurtosis đáng kể đã tính toán ở hai mục trước. Mặc dù Log_PE đã đối xứng hơn PE gốc, nó vẫn chưa đủ “chuẩn” theo tiêu chuẩn thống kê chặt chẽ.

  • Kết luận: Các biến định lượng quan trọng trong bộ dữ liệu này không tuân theo phân phối chuẩn. Điều này hàm ý rằng: (1) Các phương pháp thống kê giả định tính chuẩn (như t-test, ANOVA) cần được sử dụng thận trọng và kiểm tra các giả định khác (như phương sai đồng nhất); (2) Các phương pháp phi tham số hoặc các mô hình tổng quát hơn có thể phù hợp hơn cho phân tích suy luận sâu hơn.

1.3.3.4. Trực quan hóa sơ bộ bằng QQ-Plot

# 1. Tải thư viện ggplot2
library(ggplot2)

cat("\n 1.3.3.4: Trực quan hóa Sơ bộ bằng QQ-Plot \n")
## 
##  1.3.3.4: Trực quan hóa Sơ bộ bằng QQ-Plot
# 2. Vẽ QQ-Plot cho Real_Return (trên mẫu con để tránh quá tải)
# QQ-Plot so sánh phân vị của dữ liệu với phân vị lý thuyết của phân phối chuẩn
# Nếu các điểm nằm sát đường thẳng => Gần phân phối chuẩn
cat("Đang vẽ QQ-Plot cho Real_Return (mẫu N=5000)...\n")
## Đang vẽ QQ-Plot cho Real_Return (mẫu N=5000)...
if (exists("nyse_sample")) {
  qq_plot_real_return <- ggplot(nyse_sample, aes(sample = Real_Return)) +
    geom_qq(color = "blue", alpha = 0.5) +          # Vẽ các điểm phân vị
    geom_qq_line(color = "red", linetype = "dashed") + # Vẽ đường chuẩn lý thuyết
    labs(title = "Biểu đồ 1.3.1: QQ-Plot của Lợi suất Thực tế (Real_Return)",
         subtitle = "So sánh với Phân phối Chuẩn (trên mẫu N=5000)",
         x = "Phân vị Lý thuyết (Chuẩn)",
         y = "Phän vị Mẫu (Real_Return)") +
    theme_minimal()
  print(qq_plot_real_return)
} else {
  cat("Biến nyse_sample chưa được tạo.\n")
}

# 3. Vẽ QQ-Plot cho Log_PE (trên mẫu con)
cat("\nĐang vẽ QQ-Plot cho Log_PE (mẫu N=5000)...\n")
## 
## Đang vẽ QQ-Plot cho Log_PE (mẫu N=5000)...
if (exists("nyse_sample")) {
  qq_plot_log_pe <- ggplot(nyse_sample, aes(sample = Log_PE)) + # Sử dụng tên biến mới
    geom_qq(color = "darkgreen", alpha = 0.5) +
    geom_qq_line(color = "red", linetype = "dashed") +
    labs(title = "Biểu đồ 1.3.2: QQ-Plot của Log(PE) (Log_PE)",
         subtitle = "So sánh với Phân phối Chuẩn (trên mẫu N=5000, đã lọc NA)",
         x = "Phân vị Lý thuyết (Chuẩn)",
         y = "Phân vị Mẫu (Log_PE)") +
    theme_minimal()
  print(qq_plot_log_pe)
} else {
  cat("Biến nyse_sample chưa được tạo.\n")
}

Nhận xét phân tích tổng hợp Mục 1.3.3:

  • Độ xiên (Skewness - Mục 1.3.3.1): Kết quả (Bảng 1.3.11) cho thấy hầu hết các biến quan trọng (Nominal_Return, Real_Return, amount, PB, PS, Leverage_Ratio, Current_Ratio, Log_PE…) đều có độ lệch phải đáng kể (Skewness > 1), chỉ có ROE lệch trái mạnh. Điều này cho thấy sự thiếu đối xứng nghiêm trọng trong dữ liệu.

  • Độ nhọn (Kurtosis - Mục 1.3.3.2): Kết quả (Bảng 1.3.12) cho thấy hầu hết các biến đều có Excess Kurtosis > 0, đặc biệt là Nominal_Return (117.3) và Real_Return (31.9). Điều này chứng tỏ các phân phối này nhọn hơn và có đuôi dày hơn so với phân phối chuẩn, hàm ý rủi ro xảy ra các giá trị cực đoan (outliers) cao hơn.

  • Kiểm định Chuẩn (Normality Test - Mục 1.3.3.3): Kiểm định Shapiro-Wilk trên mẫu con cho cả Real_ReturnLog_PE đều cho p-value cực kỳ nhỏ (< 2.2e-16). Điều này cung cấp bằng chứng thống kê mạnh mẽ để bác bỏ giả thuyết rằng các biến này (ngay cả Log_PE sau khi chuẩn hóa) tuân theo phân phối chuẩn.

  • Trực quan hóa QQ-Plot (Mục 1.3.3.4):

    • QQ-Plot Real_Return: Các điểm dữ liệu (màu xanh) lệch rất xa khỏi đường chuẩn lý thuyết (màu đỏ). Đặc biệt ở hai đầu (đuôi), các điểm cong vồng lên ở phía dương và cong xuống ở phía âm, tạo thành hình chữ “S”. Điều này trực quan hóa mạnh mẽ kết luận từ Skewness, Kurtosis và Shapiro Test: Real_Return hoàn toàn không tuân theo phân phối chuẩn, với phần đuôi dày.

    • QQ-Plot Log_PE: Mặc dù các điểm dữ liệu (màu xanh lá) bám sát đường chuẩn lý thuyết (màu đỏ) tốt hơn nhiều so với Real_Return ở phần trung tâm, nhưng chúng vẫn lệch ra đáng kể ở hai đầu đuôi. Các điểm ở đuôi trên (giá trị Log_PE cao) nằm cao hơn đường thẳng, và các điểm ở đuôi dưới (giá trị Log_PE thấp) nằm thấp hơn đường thẳng. Điều này cho thấy, mặc dù phép biến đổi logarit đã cải thiện tính đối xứng, phân phối của Log_PE vẫn có đuôi dày hơn so với phân phối chuẩn và không hoàn toàn chuẩn.

  • Kết luận: Cả bằng chứng định lượng (Skewness, Kurtosis, Shapiro Test) và trực quan (QQ-Plot) đều đi đến cùng một kết luận: Các biến định lượng quan trọng trong bộ dữ liệu NYSE này không tuân theo phân phối chuẩn. Chúng thường bị lệch và có đuôi dày. Điều này là đặc điểm phổ biến của dữ liệu tài chính và cần được xem xét cẩn thận khi lựa chọn các mô hình thống kê và diễn giải kết quả ở các mục sau. Việc sử dụng các phương pháp phi tham số hoặc các mô hình robust với outliers có thể là cần thiết.

1.3.4. Phân tích tương quan tuyến tính

Nhằm đo lường mức độ và chiều hướng của mối quan hệ tuyến tính giữa các cặp biến định lượng quan trọng. Hệ số tương quan Pearson (r) dao động từ -1 đến +1, trong đó:

  • r = +1: Tương quan dương hoàn hảo.
  • r = -1: Tương quan âm hoàn hảo.
  • r = 0: Không có tương quan tuyến tính.
  • Giá trị tuyệt đối |r| càng gần 1, mối quan hệ tuyến tính càng mạnh.

1.3.4.1. Tính toán ma trận tương quan

# 1. Tải thư viện cần thiết
library(dplyr)
library(knitr)
library(reshape2) # Cần cho việc xử lý ma trận sau này

# 3. Chọn các biến định lượng chính để tính tương quan
# (Bao gồm lợi suất, rủi ro, định giá, hiệu quả, quy mô...)
# Lựa chọn cẩn thận để tránh đưa vào quá nhiều biến gây nhiễu
vars_for_cor <- c("Real_Return", "Nominal_Return", "amount", "Horizon_Days",
                  "Volatility_Buy", "Sharpe_Ratio",
                  "Log_PE", "PB", "PS",
                  "ROE", "ROA", "NetProfitMargin",
                  "Leverage_Ratio", "Current_Ratio", "ESG")

# 4. Tạo data frame con chỉ chứa các biến này và xử lý NA/Inf
# Hàm cor() yêu cầu dữ liệu numeric và không có NA/Inf
cor_data_input <- nyse_clean_core %>%
  select(all_of(vars_for_cor)) %>%
  # Xử lý Inf/NaN một lần nữa cho chắc chắn
  mutate(across(everything(), ~ ifelse(is.finite(.x), .x, NA))) %>%
  # Loại bỏ các hàng có bất kỳ giá trị NA nào trong các cột đã chọn
  # 'pairwise.complete.obs' trong cor() có thể xử lý NA, nhưng lọc trước rõ ràng hơn
  na.omit() 

# Kiểm tra số lượng quan sát còn lại sau khi lọc NA
n_obs_cor <- nrow(cor_data_input)
cat("1.3.4.1: Tính toán Ma trận Tương quan \n")
## 1.3.4.1: Tính toán Ma trận Tương quan
cat("Số lượng quan sát hợp lệ (không NA/Inf) để tính tương quan:", format(n_obs_cor, big.mark = ","), "\n")
## Số lượng quan sát hợp lệ (không NA/Inf) để tính tương quan: 364,662
# 5. Tính toán ma trận tương quan Pearson
# use = "pairwise.complete.obs" xử lý NA bằng cách tính tương quan cho từng cặp biến dựa trên các quan sát hoàn chỉnh của cặp đó
# method = "pearson" là mặc định
cor_matrix <- cor(cor_data_input, method = "pearson", use = "pairwise.complete.obs")

# 6. Hiển thị ma trận tương quan (làm tròn để dễ đọc)
cat("\nMa trận Tương quan Pearson (làm tròn 2 chữ số):\n")
## 
## Ma trận Tương quan Pearson (làm tròn 2 chữ số):
print(round(cor_matrix, 2))
##                 Real_Return Nominal_Return amount Horizon_Days Volatility_Buy
## Real_Return            1.00           0.49      0         0.13           0.06
## Nominal_Return         0.49           1.00      0         0.31           0.13
## amount                 0.00           0.00      1         0.00           0.00
## Horizon_Days           0.13           0.31      0         1.00           0.00
## Volatility_Buy         0.06           0.13      0         0.00           1.00
## Sharpe_Ratio           0.06           0.13      0         0.00           1.00
## Log_PE                -0.01           0.10      0         0.00          -0.07
## PB                    -0.10           0.09      0         0.00          -0.01
## PS                    -0.02           0.08      0         0.00           0.13
## ROE                   -0.10          -0.03      0         0.00          -0.06
## ROA                   -0.02           0.07      0         0.00           0.06
## NetProfitMargin       -0.02           0.06      0         0.00          -0.02
## Leverage_Ratio        -0.07          -0.13      0         0.00           0.03
## Current_Ratio          0.06           0.08      0         0.00           0.21
## ESG                   -0.03          -0.10      0         0.00          -0.26
##                 Sharpe_Ratio Log_PE    PB    PS   ROE   ROA NetProfitMargin
## Real_Return             0.06  -0.01 -0.10 -0.02 -0.10 -0.02           -0.02
## Nominal_Return          0.13   0.10  0.09  0.08 -0.03  0.07            0.06
## amount                  0.00   0.00  0.00  0.00  0.00  0.00            0.00
## Horizon_Days            0.00   0.00  0.00  0.00  0.00  0.00            0.00
## Volatility_Buy          1.00  -0.07 -0.01  0.13 -0.06  0.06           -0.02
## Sharpe_Ratio            1.00  -0.07 -0.01  0.13 -0.06  0.06           -0.02
## Log_PE                 -0.07   1.00  0.75  0.50 -0.20  0.10            0.05
## PB                     -0.01   0.75  1.00  0.40  0.31  0.35            0.10
## PS                      0.13   0.50  0.40  1.00  0.04  0.51            0.71
## ROE                    -0.06  -0.20  0.31  0.04  1.00  0.63            0.25
## ROA                     0.06   0.10  0.35  0.51  0.63  1.00            0.58
## NetProfitMargin        -0.02   0.05  0.10  0.71  0.25  0.58            1.00
## Leverage_Ratio          0.03  -0.12 -0.24 -0.27 -0.26 -0.55           -0.13
## Current_Ratio           0.21   0.30  0.20  0.83  0.04  0.48            0.55
## ESG                    -0.26   0.12 -0.06  0.15 -0.44 -0.35            0.04
##                 Leverage_Ratio Current_Ratio   ESG
## Real_Return              -0.07          0.06 -0.03
## Nominal_Return           -0.13          0.08 -0.10
## amount                    0.00          0.00  0.00
## Horizon_Days              0.00          0.00  0.00
## Volatility_Buy            0.03          0.21 -0.26
## Sharpe_Ratio              0.03          0.21 -0.26
## Log_PE                   -0.12          0.30  0.12
## PB                       -0.24          0.20 -0.06
## PS                       -0.27          0.83  0.15
## ROE                      -0.26          0.04 -0.44
## ROA                      -0.55          0.48 -0.35
## NetProfitMargin          -0.13          0.55  0.04
## Leverage_Ratio            1.00         -0.27  0.30
## Current_Ratio            -0.27          1.00  0.12
## ESG                       0.30          0.12  1.00

Nhận xét

  • Ma trận Tương quan tổng thể:

    • Vấn đề đa cộng tuyến: Phát hiện quan trọng nhất là tương quan dương hoàn hảo (r=1.00) giữa Volatility_BuySharpe_Ratio. Điều này cho thấy hai biến này đo lường gần như cùng một khái niệm trong bộ dữ liệu này hoặc có thể có lỗi trong cách tính/định nghĩa Sharpe_Ratio gốc. Chỉ giữ lại một trong hai biến (Volatility_Buy là lựa chọn tốt hơn vì nó là chỉ số rủi ro gốc) trong các mô hình hồi quy sau này để tránh đa cộng tuyến hoàn hảo.

    • Tương quan lợi suất: Real_ReturnNominal_Return có tương quan dương trung bình (r=0.49), xác nhận tác động của biến inflation đã làm giảm mối liên hệ trực tiếp. Cả hai loại lợi suất đều có tương quan rất yếu với hầu hết các chỉ số tài chính, định giá và rủi ro khác. Ví dụ, Real_Return gần như không tương quan tuyến tính với amount (r=0.00), Log_PE (r=-0.01), PS (r=-0.02), ROA (r=-0.02), NetProfitMargin (r=-0.02), ESG (r=-0.03). Tương quan yếu với Volatility_Buy (r=0.06), Leverage_Ratio (r=-0.07), PB (r=-0.10), ROE (r=-0.10). Tương quan dương yếu nhất là với Horizon_Days (r=0.13).

    • Tương quan nội tại mạnh (khác):

      • Định giá: Log_PE tương quan dương mạnh với PB (r=0.75) và PS (r=0.50).

      • Hiệu quả HĐ & Thanh khoản: PS tương quan rất mạnh với Current_Ratio (r=0.83) và NetProfitMargin (r=0.71). NetProfitMargin cũng tương quan khá mạnh với Current_Ratio (r=0.55) và ROA (r=0.58). ROEROA tương quan dương mạnh (r=0.63).

    • Tương quan âm đáng chú ý (khác):

      • Leverage_Ratio có tương quan âm mạnh nhất với ROA (r=-0.55), tiếp tục củng cố nhận định rằng các công ty có hiệu quả tài sản cao hơn thường dùng ít nợ hơn. Nó cũng tương quan âm với PS (r=-0.27), Current_Ratio (r=-0.27), ROE (r=-0.26), PB (r=-0.24).

      • ESG có tương quan âm mạnh nhất với ROE (r=-0.44) và ROA (r=-0.35), cho thấy các công ty có xếp hạng ESG cao hơn có xu hướng hiệu quả sinh lời trên vốn/tài sản thấp hơn trong mẫu này. ESG cũng tương quan âm với Volatility_Buy (r=-0.26), gợi ý rằng các công ty ESG cao hơn có thể có rủi ro thấp hơn.

    • Biến gần như Độc lập: amountHorizon_Days tiếp tục cho thấy tương quan gần bằng 0 với hầu hết các biến tài chính và rủi ro.

1.3.4.2. Xác định và báo cáo các cặp tương quan mạnh

# 1. Chuyển đổi ma trận tương quan thành dạng dài (Var1, Var2, Correlation)
cat("\n 1.3.4.2: Xác định các cặp tương quan mạnh \n")
## 
##  1.3.4.2: Xác định các cặp tương quan mạnh
# Sử dụng melt từ reshape2 hoặc pivot_longer từ tidyr
melted_cor <- melt(cor_matrix, na.rm = TRUE) # na.rm loại bỏ NA nếu có

# 2. Loại bỏ các cặp trùng lặp (vd: A vs B và B vs A) và tự tương quan (A vs A)
# Chỉ giữ lại phần tam giác trên hoặc dưới của ma trận
melted_cor_unique <- melted_cor %>%
  filter(as.character(Var1) < as.character(Var2)) # Chỉ giữ Var1 < Var2 (theo thứ tự alphabet)

# 3. Sắp xếp theo giá trị tương quan tuyệt đối giảm dần
strongest_cor <- melted_cor_unique %>%
  arrange(desc(abs(value))) # Sắp xếp theo giá trị tuyệt đối |r|

# 4. Hiển thị Top 10 cặp tương quan mạnh (cả dương và âm)
cat("Top 10 cặp biến có tương quan tuyến tính mạnh (Tuyệt đối |r|):\n")
## Top 10 cặp biến có tương quan tuyến tính mạnh (Tuyệt đối |r|):
top_10_cor <- head(strongest_cor, 10) %>%
              mutate(value = round(value, 3)) # Làm tròn kết quả

kable(top_10_cor,
      caption = "Bảng 1.3.14: Top 10 Cặp Tương quan Tuyến tính Mạnh nhất",
      col.names = c("Biến 1", "Biến 2", "Hệ số Tương quan (r)"),
      format = "pipe", align = "l")
Bảng 1.3.14: Top 10 Cặp Tương quan Tuyến tính Mạnh nhất
Biến 1 Biến 2 Hệ số Tương quan (r)
Sharpe_Ratio Volatility_Buy 1.000
Current_Ratio PS 0.833
Log_PE PB 0.752
NetProfitMargin PS 0.708
ROA ROE 0.628
NetProfitMargin ROA 0.577
Current_Ratio NetProfitMargin 0.554
Leverage_Ratio ROA -0.548
PS ROA 0.512
Log_PE PS 0.495
# 5. Hiển thị Top 5 cặp tương quan DƯƠNG mạnh nhất
cat("\nTop 5 cặp biến có tương quan DƯƠNG mạnh nhất (r > 0):\n")
## 
## Top 5 cặp biến có tương quan DƯƠNG mạnh nhất (r > 0):
top_5_pos_cor <- strongest_cor %>%
                 filter(value > 0) %>% # Chỉ lấy r dương
                 head(5) %>%
                 mutate(value = round(value, 3))

kable(top_5_pos_cor,
      caption = "Bảng 1.3.15: Top 5 Cặp Tương quan Dương Mạnh nhất",
      col.names = c("Biến 1", "Biến 2", "Hệ số Tương quan (r)"),
      format = "pipe", align = "l")
Bảng 1.3.15: Top 5 Cặp Tương quan Dương Mạnh nhất
Biến 1 Biến 2 Hệ số Tương quan (r)
Sharpe_Ratio Volatility_Buy 1.000
Current_Ratio PS 0.833
Log_PE PB 0.752
NetProfitMargin PS 0.708
ROA ROE 0.628
# 6. Hiển thị Top 5 cặp tương quan ÂM mạnh nhất
cat("\nTop 5 cặp biến có tương quan ÂM mạnh nhất (r < 0):\n")
## 
## Top 5 cặp biến có tương quan ÂM mạnh nhất (r < 0):
top_5_neg_cor <- strongest_cor %>%
                 filter(value < 0) %>% # Chỉ lấy r âm
                 # Sắp xếp lại theo giá trị âm nhỏ nhất (tức là âm mạnh nhất)
                 arrange(value) %>% 
                 head(5) %>%
                 mutate(value = round(value, 3))

kable(top_5_neg_cor,
      caption = "Bảng 1.3.16: Top 5 Cặp Tương quan Âm Mạnh nhất",
      col.names = c("Biến 1", "Biến 2", "Hệ số Tương quan (r)"),
      format = "pipe", align = "l")
Bảng 1.3.16: Top 5 Cặp Tương quan Âm Mạnh nhất
Biến 1 Biến 2 Hệ số Tương quan (r)
Leverage_Ratio ROA -0.548
ESG ROE -0.440
ESG ROA -0.349
Current_Ratio Leverage_Ratio -0.274
Leverage_Ratio PS -0.272
  • Các cặp tương quan mạnh:

    • Bảng Top 10/Top 5 xác nhận lại các mối quan hệ mạnh nhất đã nêu trên, đặc biệt là tương quan hoàn hảo giữa Sharpe_RatioVolatility_Buy, tương quan rất mạnh giữa Current_RatioPS, và các tương quan nội tại khác trong nhóm định giá và hiệu quả.

    • Tương quan âm mạnh nhất được xác nhận là giữa Leverage_RatioROA.

1.3.4.3. Kiểm định ý nghĩa thống kê của các tương quan chính

# 1. Chọn các cặp biến quan trọng để kiểm định
# Ví dụ: Mối quan hệ giữa Lợi suất và các yếu tố Rủi ro, Định giá
cat("\n 1.3.4.3: Kiểm định ý nghĩa thống kê của tương quan chính \n")
## 
##  1.3.4.3: Kiểm định ý nghĩa thống kê của tương quan chính
pairs_to_test <- list(
  c("Real_Return", "Volatility_Buy"),
  c("Real_Return", "Log_PE"),
  c("Real_Return", "Sharpe_Ratio"),
  c("Volatility_Buy", "Sharpe_Ratio"), # Cặp tương quan dương mạnh bất thường
  c("ROA", "Leverage_Ratio")           # Cặp tương quan âm mạnh bất thường
)

# 2. Thực hiện kiểm định cor.test() cho từng cặp
# Giả thuyết H0: Hệ số tương quan bằng 0 (không có tương quan tuyến tính)
# Nếu p-value < 0.05, bác bỏ H0, kết luận tương quan có ý nghĩa thống kê
results_cor_test <- list() # Tạo list để lưu kết quả

for (pair in pairs_to_test) {
  var1 <- pair[1]
  var2 <- pair[2]
  
  # Thực hiện kiểm định, xử lý lỗi nếu có (có thể do NA)
  test_result <- tryCatch({
    # Sử dụng dữ liệu đã lọc NA 'cor_data_input'
    cor.test(cor_data_input[[var1]], cor_data_input[[var2]], method = "pearson")
  }, error = function(e) {
    # Trả về NA nếu có lỗi
    list(estimate = NA, p.value = NA, parameter = list(df = NA)) 
  })
  
  # Lưu kết quả vào list
  results_cor_test[[paste(var1, "vs", var2)]] <- list(
    correlation = round(test_result$estimate, 3),
    p_value = test_result$p.value, # Giữ nguyên p-value để đánh giá
    df = test_result$parameter # Bậc tự do (n-2)
  )
}

# 3. Chuyển kết quả kiểm định thành data frame để trình bày
cor_test_df <- do.call(rbind, lapply(results_cor_test, function(x) data.frame(Correlation = x$correlation, P_Value = x$p_value, DF = x$df)))
cor_test_df <- tibble::rownames_to_column(cor_test_df, var = "Pair")

# Định dạng lại P-value cho dễ đọc
cor_test_df <- cor_test_df %>%
  mutate(P_Value_Formatted = format.pval(P_Value, digits = 3, eps = 0.001), # Hiển thị <0.001 nếu quá nhỏ
         Significance = ifelse(P_Value < 0.05, "Có ý nghĩa (p < 0.05)", "Không ý nghĩa (p >= 0.05)"))


# 4. Trình bày bảng kết quả kiểm định
kable(cor_test_df %>% select(Pair, Correlation, P_Value_Formatted, Significance, DF),
      caption = "Bảng 1.3.17: Kết quả Kiểm định Ý nghĩa Thống kê cho các Tương quan Chính",
      col.names = c("Cặp Biến", "Hệ số r", "P-value", "Kết luận", "Bậc tự do (df)"),
      format = "pipe", align = "l")
Bảng 1.3.17: Kết quả Kiểm định Ý nghĩa Thống kê cho các Tương quan Chính
Cặp Biến Hệ số r P-value Kết luận Bậc tự do (df)
Real_Return vs Volatility_Buy 0.057 <0.001 Có ý nghĩa (p < 0.05) 364660
Real_Return vs Log_PE -0.006 <0.001 Có ý nghĩa (p < 0.05) 364660
Real_Return vs Sharpe_Ratio 0.057 <0.001 Có ý nghĩa (p < 0.05) 364660
Volatility_Buy vs Sharpe_Ratio 1.000 <0.001 Có ý nghĩa (p < 0.05) 364660
ROA vs Leverage_Ratio -0.548 <0.001 Có ý nghĩa (p < 0.05) 364660
  • Kiểm định ý nghĩa thống kê:

    * Đúng như dự đoán, với cỡ mẫu cực lớn (df ≈ 364,660), tất cả các hệ số tương quan được kiểm định (bao gồm cả những hệ số rất nhỏ như r=-0.006 giữa `Real_Return` và `Log_PE`) đều có **p-value < 0.001**. Do đó, tất cả các mối quan hệ này đều "có ý nghĩa thống kê".
    
    * Tuy nhiên, ý nghĩa thực tiễn mới là quan trọng. Kết quả kiểm định tái khẳng định rằng mặc dù có ý nghĩa thống kê, mối quan hệ tuyến tính giữa `Real_Return` với `Volatility_Buy` (r=0.057) và `Log_PE` (r=-0.006) là **quá yếu** để có thể coi là có ý nghĩa thực tiễn hoặc giá trị dự báo đáng kể. Ngược lại, các mối quan hệ mạnh hơn như `Volatility_Buy` vs `Sharpe_Ratio` (r=1.000) và `ROA` vs `Leverage_Ratio` (r=-0.548) vừa có ý nghĩa thống kê, vừa có ý nghĩa thực tiễn (mặc dù mối quan hệ r=1 cần được xử lý).

Kết luận tổng hợp mục 1.3.4: Phân tích tương quan cho thấy các mối liên kết nội tại mạnh mẽ giữa các nhóm chỉ số tài chính (định giá, hiệu quả, thanh khoản), nhưng lại bộc lộ mối quan hệ tuyến tính rất yếu giữa hầu hết các yếu tố này với lợi suất thực tế (Real_Return). Phát hiện này đặt ra câu hỏi về tính hiệu quả của thị trường hoặc tính phù hợp của các mô hình tuyến tính đơn giản trong việc giải thích lợi suất. Vấn đề tương quan hoàn hảo giữa Volatility_BuySharpe_Ratio cần được giải quyết bằng cách loại bỏ một biến. Các mối tương quan âm đáng chú ý (như ROA vs Leverage, ESG vs ROE/ROA) cung cấp những hiểu biết có giá trị về đặc điểm của các công ty trong mẫu.

1.3.5. Kiểm định giả thuyết về sự khác biệt trung bình giữa các nhóm

Sau khi mô tả phân bố và tương quan, mục này sử dụng thống kê suy luận để kiểm tra xem liệu có sự khác biệt có ý nghĩa thống kê về giá trị trung bình của các biến định lượng giữa các nhóm được xác định bởi các biến phân loại hay không. Giả thuyết gốc (H0) thường là “không có sự khác biệt trung bình giữa các nhóm”. Nếu p-value < 0.05, chúng ta bác bỏ H0 và kết luận có sự khác biệt ý nghĩa.

1.3.5.1. So sánh Real_Return theo investment (GOOD/BAD)

# Tính toán t-test
t_test_inv_rr <- run_t_test_calc(nyse_clean_finite, Real_Return ~ investment)
# Hiển thị kết quả
display_t_test_result(t_test_inv_rr, "Lợi suất Thực tế", "Kết quả Đầu tư")
## 
## --- So sánh Lợi suất Thực tế theo Kết quả Đầu tư (t-test) ---
## 
## 
## Table: Bảng: Kết quả Welch t-test cho Lợi suất Thực tế theo Kết quả Đầu tư
## 
## |T-statistic |P-value |Mean Grp1 |Mean Grp2 |Chênh lệch |95% CI Low |95% CI High |
## |:-----------|:-------|:---------|:---------|:----------|:----------|:-----------|
## |-425.525    |0       |-0.248    |0.715     |-0.963     |-0.968     |-0.959      |
## Kết luận: Có sự khác biệt trung bình ý nghĩa thống kê (p < 0.05).

Nhận xét 1.3.5:

Mục này sử dụng các kiểm định t-test (so sánh 2 nhóm) và ANOVA (so sánh >= 3 nhóm) để kiểm tra xem có sự khác biệt ý nghĩa thống kê về giá trị trung bình của các biến định lượng giữa các nhóm phân loại hay không. Kết quả được diễn giải dưới đây:

  • 1.3.5.1. So sánh Real_Return theo investment (GOOD/BAD):

    • Kết quả Welch t-test cho thấy giá trị p-value = 0 (nhỏ hơn 0.05).

    • Kết luận: Có sự khác biệt trung bình rất có ý nghĩa thống kê về Lợi suất Thực tế giữa nhóm GOODBAD. Trung bình Real_Return của nhóm GOOD (Mean Grp2 = 0.715, tức 71.5%) cao hơn đáng kể so với nhóm BAD (Mean Grp1 = -0.248, tức -24.8%). Chênh lệch trung bình ước tính là 0.963 (96.3%). Điều này khẳng định biến investment phân loại rất hiệu quả dựa trên lợi suất.

1.3.5.2. So sánh Real_Return theo sector

# Tính toán ANOVA
anova_sec_rr <- run_anova_calc(nyse_clean_finite, Real_Return ~ sector)
# Hiển thị kết quả
display_anova_result(anova_sec_rr, "Lợi suất Thực tế", "Ngành")
## 
##  So sánh Lợi suất Thực tế theo Ngành (ANOVA)
## 
## 
## Table: Bảng: Kết quả ANOVA cho Lợi suất Thực tế theo Ngành
## 
## |Nguồn Biến đổi |df     |SS         |MS       |F-statistic |P-value |
## |:--------------|:------|:----------|:--------|:-----------|:-------|
## |sector         |4      |4131.683   |1032.921 |1751.865    |0       |
## |Residuals      |405253 |238942.110 |0.590    |NA          |NA      |
## Kết luận ANOVA: Không thể xác định p-value (NA).
tukey_rr_sector <- TukeyHSD(anova_sec_rr)
print(tukey_rr_sector)
##   Tukey multiple comparisons of means
##     95% family-wise confidence level
## 
## Fit: aov(formula = formula, data = data)
## 
## $sector
##                     diff          lwr          upr     p adj
## BANK-AUTO   -0.027029578 -0.037359812 -0.016699343 0.0000000
## FMCG-AUTO   -0.019380871 -0.031184628 -0.007577113 0.0000735
## RETAIL-AUTO  0.028849231  0.018823064  0.038875397 0.0000000
## TECH-AUTO    0.234274372  0.224153517  0.244395226 0.0000000
## FMCG-BANK    0.007648707 -0.004019119  0.019316533 0.3804336
## RETAIL-BANK  0.055878809  0.046013035  0.065744582 0.0000000
## TECH-BANK    0.261303950  0.251341963  0.271265936 0.0000000
## RETAIL-FMCG  0.048230101  0.036830609  0.059629594 0.0000000
## TECH-FMCG    0.253655242  0.242172381  0.265138104 0.0000000
## TECH-RETAIL  0.205425141  0.195778824  0.215071458 0.0000000
  • 1.3.5.2. So sánh Real_Return theo sector:

    • Kết quả ANOVA cho thấy p-value = 0 (nhỏ hơn 0.05) đối với yếu tố sector.

    • Kết luận ANOVA: Có sự khác biệt trung bình rất có ý nghĩa thống kê về Lợi suất Thực tế giữa ít nhất hai ngành.

    • Phân tích TukeyHSD:

      • Kiểm định post-hoc cho thấy sự khác biệt rất rõ ràng về lợi suất thực tế trung bình giữa các ngành.

      • Ngành TECH có lợi suất trung bình cao nhất, vượt trội đáng kể so với tất cả các ngành còn lại (tất cả các so sánh TECH- đều có p adj = 0).

      • Ngành RETAIL đứng thứ hai, có lợi suất trung bình cao hơn đáng kể so với AUTO, FMCG, và BANK.

      • Các ngành BANKFMCG có lợi suất trung bình thấp nhất, và sự khác biệt giữa hai ngành này là không có ý nghĩa thống kê (FMCG-BANKp adj = 0.38).

      • Thứ tự lợi suất trung bình (từ cao đến thấp) là: TECH > RETAIL > AUTO > FMCG \(\approx\) BANK.

1.3.5.3. So sánh Real_Return theo Holding_Period

# Tính toán ANOVA
anova_hp_rr <- run_anova_calc(nyse_clean_finite, Real_Return ~ Holding_Period)
# Hiển thị kết quả
display_anova_result(anova_hp_rr, "Lợi suất Thực tế", "Thời gian Nắm giữ")
## 
##  So sánh Lợi suất Thực tế theo Thời gian Nắm giữ (ANOVA)
## 
## 
## Table: Bảng: Kết quả ANOVA cho Lợi suất Thực tế theo Thời gian Nắm giữ
## 
## |Nguồn Biến đổi |df     |SS         |MS       |F-statistic |P-value |
## |:--------------|:------|:----------|:--------|:-----------|:-------|
## |Holding_Period |2      |2441.686   |1220.843 |2056.055    |0       |
## |Residuals      |405255 |240632.106 |0.594    |NA          |NA      |
## Kết luận ANOVA: Không thể xác định p-value (NA).
tukey_rr_hp <- TukeyHSD(anova_hp_rr)
print(tukey_rr_hp)
##   Tukey multiple comparisons of means
##     95% family-wise confidence level
## 
## Fit: aov(formula = formula, data = data)
## 
## $Holding_Period
##                                             diff       lwr        upr p adj
## Mid-term (31-180d)-Short-term (<=30d) 0.02196404 0.0148412 0.02908688     0
## Long-term (>180d)-Short-term (<=30d)  0.17075291 0.1639508 0.17755500     0
## Long-term (>180d)-Mid-term (31-180d)  0.14878887 0.1418115 0.15576624     0

Nhận xét:

  • Kết quả ANOVA: Bảng ANOVA cho thấy p-value = 0 (nhỏ hơn 0.05) đối với yếu tố Holding_Period. Điều này khẳng định có sự khác biệt trung bình rất có ý nghĩa thống kê về Lợi suất Thực tế (Real_Return) giữa ít nhất hai trong ba chiến lược thời gian nắm giữ (Ngắn hạn, Trung hạn, Dài hạn).

  • Kiểm định Post-hoc TukeyHSD: Bảng kết quả TukeyHSD cho thấy p adj = 0 (nhỏ hơn 0.05) cho tất cả ba cặp so sánh:

    • Mid-term vs. Short-term: Có khác biệt ý nghĩa (diff = 0.022).
    • Long-term vs. Short-term: Có khác biệt ý nghĩa (diff = 0.171).
    • Long-term vs. Mid-term: Có khác biệt ý nghĩa (diff = 0.149).
  • Diễn giải sự khác biệt:

    • Chênh lệch (diff) dương cho thấy nhóm thứ nhất có trung bình cao hơn nhóm thứ hai.
    • Long-termMean(Real_Return) cao hơn đáng kể so với cả Short-term (cao hơn 0.171 hay 17.1%) và Mid-term (cao hơn 0.149 hay 14.9%).
    • Mid-term cũng có Mean(Real_Return) cao hơn một chút so với Short-term (cao hơn 0.022 hay 2.2%).
  • Kết luận: Trái ngược với dự đoán ban đầu dựa trên Median, kiểm định TukeyHSD trên trung bình (Mean) cho thấy một kết quả phù hợp hơn với lý thuyết đầu tư dài hạn: Chiến lược Long-term (>180 ngày) có lợi suất thực tế trung bình cao nhất, cao hơn đáng kể so với Mid-termShort-term. Chiến lược Mid-term cũng hiệu quả hơn Short-term một chút. Điều này gợi ý rằng, trung bình, việc nắm giữ cổ phiếu lâu hơn trong bộ dữ liệu này mang lại lợi suất thực tế tốt hơn, mặc dù có thể đi kèm với biến động lớn hơn (như đã thấy trong boxplot).

1.3.5.4. So sánh Volatility_Buy theo sector

# Tính toán ANOVA
anova_sec_vol <- run_anova_calc(nyse_clean_finite, Volatility_Buy ~ sector)
# Hiển thị kết quả
display_anova_result(anova_sec_vol, "Độ biến động", "Ngành")
## 
##  So sánh Độ biến động theo Ngành (ANOVA)
## 
## 
## Table: Bảng: Kết quả ANOVA cho Độ biến động theo Ngành
## 
## |Nguồn Biến đổi |df     |SS       |MS      |F-statistic |P-value |
## |:--------------|:------|:--------|:-------|:-----------|:-------|
## |sector         |4      |660.544  |165.136 |20634.03    |0       |
## |Residuals      |405253 |3243.275 |0.008   |NA          |NA      |
## Kết luận ANOVA: Không thể xác định p-value (NA).
tukey_vol_sec <- TukeyHSD(anova_sec_vol)
print(tukey_vol_sec)
##   Tukey multiple comparisons of means
##     95% family-wise confidence level
## 
## Fit: aov(formula = formula, data = data)
## 
## $sector
##                     diff          lwr           upr     p adj
## BANK-AUTO   -0.011519269 -0.012722796 -0.0103157426 0.0000000
## FMCG-AUTO   -0.127787130 -0.129162330 -0.1264119305 0.0000000
## RETAIL-AUTO -0.008612833 -0.009780934 -0.0074447323 0.0000000
## TECH-AUTO   -0.009721902 -0.010901034 -0.0085427688 0.0000000
## FMCG-BANK   -0.116267861 -0.117627224 -0.1149084980 0.0000000
## RETAIL-BANK  0.002906436  0.001757021  0.0040558503 0.0000000
## TECH-BANK    0.001797368  0.000636744  0.0029579914 0.0002323
## RETAIL-FMCG  0.119174297  0.117846196  0.1205023977 0.0000000
## TECH-FMCG    0.118065229  0.116727415  0.1194030424 0.0000000
## TECH-RETAIL -0.001109068 -0.002232915  0.0000147784 0.0551339

Nhận xét:

  • Kết quả ANOVA: Bảng ANOVA cho thấy p-value = 0 (nhỏ hơn 0.05) đối với yếu tố sector. Điều này khẳng định có sự khác biệt trung bình rất có ý nghĩa thống kê về Mức độ Rủi ro (Volatility_Buy) giữa các ngành.

  • Kiểm định Post-hoc TukeyHSD: Bảng kết quả TukeyHSD cho thấy hầu hết các cặp ngành đều có sự khác biệt ý nghĩa thống kê về Volatility_Buy trung bình (p adj = 0.0000000), ngoại trừ cặp TECH-RETAIL (p adj = 0.055, không có ý nghĩa ở mức 5%).

  • Diễn giải sự khác biệt (Dựa trên cột diff):

    • Ngành Rủi ro Thấp nhất: FMCGVolatility_Buy trung bình thấp hơn đáng kể so với tất cả các ngành khác (ví dụ: FMCG-AUTO diff = -0.128, nghĩa là FMCG thấp hơn AUTO khoảng 0.128). Điều này phù hợp với đặc tính phòng thủ, ổn định của ngành hàng tiêu dùng nhanh.

    • Nhóm Rủi ro Cao: Các ngành AUTO, BANK, RETAIL, TECH có mức Volatility_Buy trung bình cao hơn và khá tương đồng nhau. Kết quả so sánh giữa các cặp trong nhóm này cho thấy:

      • BANK, RETAIL, TECH đều có rủi ro thấp hơn AUTO một chút (diff âm).

      • RETAILTECH có rủi ro cao hơn BANK một chút (diff dương).

      • TECHRETAIL có mức rủi ro gần như tương đương (p adj > 0.05).

  • Kết luận: Có sự khác biệt rõ rệt về mức độ rủi ro giữa các ngành. Ngành FMCG là ngành có rủi ro (biến động giá) thấp nhất. Bốn ngành còn lại (AUTO, BANK, RETAIL, TECH) có mức rủi ro cao hơn đáng kể và tương đối gần nhau, trong đó AUTO có vẻ là ngành có rủi ro cao nhất trong nhóm này.

1.3.5.5. So sánh Log_PE theo sector

# Tính toán ANOVA
anova_sec_logpe <- run_anova_calc(nyse_clean_finite, Log_PE ~ sector)
# Hiển thị kết quả
display_anova_result(anova_sec_logpe, "Log(PE)", "Ngành")
## 
##  So sánh Log(PE) theo Ngành (ANOVA)
## 
## 
## Table: Bảng: Kết quả ANOVA cho Log(PE) theo Ngành
## 
## |Nguồn Biến đổi |df     |SS        |MS        |F-statistic |P-value |
## |:--------------|:------|:---------|:---------|:-----------|:-------|
## |sector         |4      |93979.78  |23494.944 |51492.87    |0       |
## |Residuals      |365502 |166769.66 |0.456     |NA          |NA      |
## Kết luận ANOVA: Không thể xác định p-value (NA).
tukey_logpe_sec <- TukeyHSD(anova_sec_logpe)
print(tukey_logpe_sec)
##   Tukey multiple comparisons of means
##     95% family-wise confidence level
## 
## Fit: aov(formula = formula, data = data)
## 
## $sector
##                    diff         lwr         upr p adj
## BANK-AUTO    0.31693813  0.30686149  0.32701477     0
## FMCG-AUTO    0.88127613  0.87013495  0.89241732     0
## RETAIL-AUTO  0.33984960  0.33025857  0.34944063     0
## TECH-AUTO    1.39166851  1.38200806  1.40132895     0
## FMCG-BANK    0.56433800  0.55360405  0.57507195     0
## RETAIL-BANK  0.02291147  0.01379668  0.03202625     0
## TECH-BANK    1.07473037  1.06554257  1.08391818     0
## RETAIL-FMCG -0.54142654 -0.55170597 -0.53114710     0
## TECH-FMCG    0.51039237  0.50004814  0.52073661     0
## TECH-RETAIL  1.05181891  1.04316645  1.06047136     0

Nhận xét:

  • Kết quả ANOVA: Bảng ANOVA cho thấy p-value = 0 (nhỏ hơn 0.05) đối với yếu tố sector. Điều này khẳng định có sự khác biệt trung bình rất có ý nghĩa thống kê về Mức định giá (Log_PE) giữa các ngành.

  • Kiểm định Post-hoc TukeyHSD: Bảng kết quả TukeyHSD cho thấy tất cả các cặp ngành đều có sự khác biệt ý nghĩa thống kê về Log_PE trung bình (tất cả p adj đều bằng 0).

  • Diễn giải sự khác biệt (Dựa trên cột diff - chênh lệch Log_PE trung bình):

    • Ngành Định giá Cao nhất: TECHLog_PE trung bình cao nhất, cao hơn đáng kể so với tất cả các ngành khác (ví dụ: TECH-AUTO diff = 1.39, TECH-BANK diff = 1.07, TECH-FMCG diff = 0.51, TECH-RETAIL diff = 1.05). Điều này phản ánh kỳ vọng tăng trưởng cao mà thị trường đặt vào ngành công nghệ.

    • Ngành Định giá Cao thứ hai: FMCGLog_PE trung bình cao thứ hai (FMCG-AUTO diff = 0.88, FMCG-BANK diff = 0.56). Ngành hàng tiêu dùng nhanh thường được coi là ổn định và có thể được định giá cao hơn các ngành chu kỳ như AUTO hay BANK.

    • Nhóm Định giá Thấp hơn: BANKRETAILLog_PE trung bình khá tương đồng (RETAIL-BANK diff = 0.02, chênh lệch rất nhỏ) và thấp hơn đáng kể so với TECH và FMCG.

    • Ngành Định giá Thấp nhất: AUTOLog_PE trung bình thấp nhất trong 5 ngành (ví dụ: BANK-AUTO diff = 0.32, RETAIL-AUTO diff = 0.34). Điều này có thể phản ánh tính chu kỳ cao và rủi ro của ngành ô tô.

  • Kết luận: Có sự phân hóa rất rõ ràng về mức định giá P/E (đã chuẩn hóa logarit) giữa các ngành. Ngành TECH được thị trường định giá cao nhất, tiếp theo là FMCG. Các ngành BANKRETAIL có mức định giá tương đương và thấp hơn, trong khi ngành AUTO có mức định giá thấp nhất. Sự khác biệt này phản ánh kỳ vọng tăng trưởng và mức độ rủi ro khác nhau giữa các ngành.

1.3.5.6. So sánh Leverage_Ratio theo sector

# Tính toán ANOVA
anova_sec_lev <- run_anova_calc(nyse_clean_finite, Leverage_Ratio ~ sector)
# Hiển thị kết quả
display_anova_result(anova_sec_lev, "Đòn bẩy Tài chính", "Ngành")
## 
##  So sánh Đòn bẩy Tài chính theo Ngành (ANOVA)
## 
## 
## Table: Bảng: Kết quả ANOVA cho Đòn bẩy Tài chính theo Ngành
## 
## |Nguồn Biến đổi |df     |SS      |MS         |F-statistic |P-value |
## |:--------------|:------|:-------|:----------|:-----------|:-------|
## |sector         |4      |5814373 |1453593.19 |139499.5    |0       |
## |Residuals      |402785 |4197043 |10.42      |NA          |NA      |
## Kết luận ANOVA: Không thể xác định p-value (NA).
tukey_lev_sector <- TukeyHSD(anova_sec_lev)
print(tukey_lev_sector)
##   Tukey multiple comparisons of means
##     95% family-wise confidence level
## 
## Fit: aov(formula = formula, data = data)
## 
## $sector
##                    diff         lwr         upr p adj
## BANK-AUTO     7.4731534   7.4294114   7.5168953     0
## FMCG-AUTO    -1.6609884  -1.7106101  -1.6113666     0
## RETAIL-AUTO  -1.8981419  -1.9402908  -1.8559929     0
## TECH-AUTO    -2.8407324  -2.8832794  -2.7981853     0
## FMCG-BANK    -9.1341417  -9.1834709  -9.0848125     0
## RETAIL-BANK  -9.3712952  -9.4130993  -9.3294911     0
## TECH-BANK   -10.3138857 -10.3560911 -10.2716803     0
## RETAIL-FMCG  -0.2371535  -0.2850757  -0.1892312     0
## TECH-FMCG    -1.1797440  -1.2280167  -1.1314712     0
## TECH-RETAIL  -0.9425905  -0.9831426  -0.9020384     0

Nhận xét:

  • Kết quả ANOVA: Bảng ANOVA cho thấy p-value = 0 (nhỏ hơn 0.05) đối với yếu tố sector. Điều này khẳng định có sự khác biệt trung bình rất có ý nghĩa thống kê về Mức độ Đòn bẩy (Leverage_Ratio) giữa các ngành.

  • Kiểm định Post-hoc TukeyHSD: Bảng kết quả TukeyHSD cho thấy tất cả các cặp ngành đều có sự khác biệt ý nghĩa thống kê về Leverage_Ratio trung bình (tất cả p adj đều bằng 0).

  • Diễn giải sự khác biệt (Dựa trên cột diff - chênh lệch Leverage_Ratio trung bình):

    • Ngành Đòn bẩy Cao nhất: BANKLeverage_Ratio trung bình cao nhất, cao hơn rất đáng kể so với tất cả các ngành khác (ví dụ: BANK-AUTO diff = 7.47; BANK-FMCG diff = 9.13; BANK-RETAIL diff = 9.37; BANK-TECH diff = 10.31). Điều này hoàn toàn phù hợp với bản chất hoạt động kinh doanh của ngành ngân hàng, vốn sử dụng đòn bẩy tài chính rất cao (huy động vốn để cho vay).

    • Ngành Đòn bẩy Cao thứ hai: AUTOLeverage_Ratio trung bình cao thứ hai, nhưng thấp hơn đáng kể so với BANK (diff = -7.47).

    • Nhóm Đòn bẩy Thấp: Các ngành FMCG, RETAIL, và TECH có mức đòn bẩy trung bình thấp hơn và khá gần nhau. Thứ tự từ cao xuống thấp trong nhóm này là FMCG > RETAIL > TECH (ví dụ: FMCG-RETAIL diff = 0.24, FMCG-TECH diff = 1.18, RETAIL-TECH diff = 0.94). Ngành TECH có mức đòn bẩy trung bình thấp nhất.

  • Kết luận: Có sự phân hóa cực kỳ rõ ràng về việc sử dụng đòn bẩy tài chính giữa các ngành. Ngành BANK nổi bật với mức đòn bẩy cao nhất do đặc thù ngành. Ngành AUTO cũng sử dụng đòn bẩy tương đối cao. Các ngành FMCG, RETAIL, và đặc biệt là TECH có xu hướng sử dụng ít đòn bẩy hơn đáng kể, có thể do cấu trúc tài sản khác biệt hoặc chính sách tài trợ thận trọng hơn.

1.3.5.7. So sánh Sharpe_Ratio theo investment (GOOD/BAD)

# Tính toán t-test
t_test_inv_sharpe <- run_t_test_calc(nyse_clean_finite, Sharpe_Ratio ~ investment)
# Hiển thị kết quả
display_t_test_result(t_test_inv_sharpe, "Tỷ suất Sharpe", "Kết quả Đầu tư")
## 
## --- So sánh Tỷ suất Sharpe theo Kết quả Đầu tư (t-test) ---
## 
## 
## Table: Bảng: Kết quả Welch t-test cho Tỷ suất Sharpe theo Kết quả Đầu tư
## 
## |T-statistic |P-value |Mean Grp1 |Mean Grp2 |Chênh lệch |95% CI Low |95% CI High |
## |:-----------|:-------|:---------|:---------|:----------|:----------|:-----------|
## |-29.962     |0       |0.251     |0.261     |-0.01      |-0.01      |-0.009      |
## Kết luận: Có sự khác biệt trung bình ý nghĩa thống kê (p < 0.05).
  • 1.3.5.7. So sánh Sharpe_Ratio theo investment (GOOD/BAD):

    • Kết quả Welch t-test cho thấy p-value = 0 (nhỏ hơn 0.05).

    • Kết luận: Có sự khác biệt trung bình rất có ý nghĩa thống kê về Tỷ suất Sharpe giữa nhóm GOODBAD. Trung bình Sharpe_Ratio của nhóm GOOD (Mean Grp2 = 0.261) cao hơn một chút so với nhóm BAD (Mean Grp1 = 0.251). Mặc dù khác biệt có ý nghĩa thống kê (do cỡ mẫu lớn), chênh lệch tuyệt đối (difference = 0.01) là rất nhỏ, cho thấy Sharpe_Ratio không phải là yếu tố phân biệt mạnh mẽ giữa hai nhóm này.

1.3.5.8. So sánh amount theo sector

# Tính toán ANOVA
anova_sec_amt <- run_anova_calc(nyse_clean_finite, amount ~ sector)
# Hiển thị kết quả ANOVA và TukeyHSD
display_anova_result(anova_sec_amt, "Quy mô Giao dịch", "Ngành")
## 
##  So sánh Quy mô Giao dịch theo Ngành (ANOVA)
## 
## 
## Table: Bảng: Kết quả ANOVA cho Quy mô Giao dịch theo Ngành
## 
## |Nguồn Biến đổi |df     |SS           |MS        |F-statistic |P-value |
## |:--------------|:------|:------------|:---------|:-----------|:-------|
## |sector         |4      |3.617148e+08 |90428703  |0.554       |0.696   |
## |Residuals      |405253 |6.613193e+13 |163186766 |NA          |NA      |
## Kết luận ANOVA: Không thể xác định p-value (NA).
# Hoặc chạy thủ công để xem kết quả:
tukey_sec_amt <- TukeyHSD(anova_sec_amt)
print(tukey_sec_amt)
##   Tukey multiple comparisons of means
##     95% family-wise confidence level
## 
## Fit: aov(formula = formula, data = data)
## 
## $sector
##                    diff       lwr       upr     p adj
## BANK-AUTO    50.9457285 -120.9121 222.80360 0.9280834
## FMCG-AUTO     0.5415207 -195.8305 196.91350 1.0000000
## RETAIL-AUTO -33.4123900 -200.2117 133.38688 0.9824036
## TECH-AUTO   -19.5671184 -187.9417 148.80742 0.9978166
## FMCG-BANK   -50.4042078 -244.5148 143.70636 0.9546812
## RETAIL-BANK -84.3581185 -248.4890  79.77279 0.6263713
## TECH-BANK   -70.5128470 -236.2444  95.21870 0.7738686
## RETAIL-FMCG -33.9539107 -223.6004 155.69255 0.9884579
## TECH-FMCG   -20.1086391 -211.1421 170.92479 0.9985180
## TECH-RETAIL  13.8452716 -146.6347 174.32522 0.9993228

Nhận xét:

  • Kết quả ANOVA: Bảng ANOVA cho thấy p-value = 0.696 (lớn hơn 0.05) đối với yếu tố sector.

  • Kiểm định Post-hoc TukeyHSD: Bảng kết quả TukeyHSD cho thấy p adj cho tất cả các cặp so sánh giữa các ngành đều lớn hơn 0.05 (thực tế đều rất gần 1).

  • Kết luận: Cả kết quả ANOVA và TukeyHSD đều đi đến cùng một kết luận: Không có đủ bằng chứng thống kê để nói rằng có sự khác biệt ý nghĩa về Quy mô Giao dịch trung bình (amount) giữa các ngành (sector). Mặc dù có thể có sự khác biệt nhỏ về giá trị trung bình (như cột diff trong TukeyHSD cho thấy), những khác biệt này không đủ lớn để có ý nghĩa thống kê với mức tin cậy 95%. Điều này gợi ý rằng quy mô các khoản đầu tư (số tiền) trong bộ dữ liệu này không phụ thuộc một cách hệ thống vào ngành nghề của cổ phiếu được giao dịch.

1.3.5.9. So sánh ESG theo sector

# Tính toán ANOVA
anova_sec_esg <- run_anova_calc(nyse_clean_finite, ESG ~ sector)
# Hiển thị kết quả
display_anova_result(anova_sec_esg, "Xếp hạng ESG", "Ngành")
## 
##  So sánh Xếp hạng ESG theo Ngành (ANOVA)
## 
## 
## Table: Bảng: Kết quả ANOVA cho Xếp hạng ESG theo Ngành
## 
## |Nguồn Biến đổi |df     |SS       |MS         |F-statistic |P-value |
## |:--------------|:------|:--------|:----------|:-----------|:-------|
## |sector         |4      |5670182  |1417545.62 |49930.46    |0       |
## |Residuals      |405253 |11505293 |28.39      |NA          |NA      |
## Kết luận ANOVA: Không thể xác định p-value (NA).
tukey_esg_sector <- TukeyHSD(anova_sec_esg)
print(tukey_esg_sector)
##   Tukey multiple comparisons of means
##     95% family-wise confidence level
## 
## Fit: aov(formula = formula, data = data)
## 
## $sector
##                  diff        lwr       upr p adj
## BANK-AUTO   -1.252598  -1.324280 -1.180916     0
## FMCG-AUTO   -4.790929  -4.872836 -4.709021     0
## RETAIL-AUTO -9.957872 -10.027444 -9.888299     0
## TECH-AUTO   -6.303788  -6.374018 -6.233559     0
## FMCG-BANK   -3.538331  -3.619295 -3.457366     0
## RETAIL-BANK -8.705274  -8.773733 -8.636814     0
## TECH-BANK   -5.051190  -5.120317 -4.982063     0
## RETAIL-FMCG -5.166943  -5.246045 -5.087841     0
## TECH-FMCG   -1.512860  -1.592540 -1.433179     0
## TECH-RETAIL  3.654084   3.587147  3.721020     0

Nhận xét:

  • Kết quả ANOVA: Bảng ANOVA cho thấy p-value = 0 (nhỏ hơn 0.05) đối với yếu tố sector. Điều này khẳng định có sự khác biệt trung bình rất có ý nghĩa thống kê về Xếp hạng ESG (ESG) giữa các ngành.

  • Kiểm định Post-hoc TukeyHSD (Dựa trên kết quả bạn cung cấp): Bảng kết quả TukeyHSD cho thấy tất cả các cặp ngành đều có sự khác biệt ý nghĩa thống kê về ESG trung bình (tất cả p adj đều bằng 0).

  • Diễn giải sự khác biệt (Dựa trên cột diff - chênh lệch ESG trung bình):

    • Thứ tự Xếp hạng ESG (Từ cao xuống thấp): Dựa trên các giá trị diff (chênh lệch dương nghĩa là nhóm 1 cao hơn nhóm 2, chênh lệch âm nghĩa là nhóm 1 thấp hơn nhóm 2), chúng ta có thể suy ra thứ tự xếp hạng ESG trung bình của các ngành như sau:

      1. AUTO (Cao nhất)

      2. BANK (BANK-AUTO diff = -1.25 => BANK thấp hơn AUTO)

      3. TECH (TECH-BANK diff = -5.05 => TECH thấp hơn BANK; TECH-AUTO diff = -6.30)

      4. FMCG (FMCG-TECH diff = -1.51 => FMCG thấp hơn TECH; FMCG-AUTO diff = -4.79)

      5. RETAIL (Thấp nhất) (RETAIL-AUTO diff = -9.96; RETAIL-FMCG diff = -5.17)

    • Mức độ Khác biệt: Sự khác biệt là rất đáng kể giữa các ngành. Ví dụ, AUTO có ESG trung bình cao hơn RETAIL tới gần 10 điểm. Ngành TECHFMCG có vẻ gần nhau hơn.

  • Kết luận: Có sự phân hóa rất rõ ràng về mức độ xếp hạng ESG trung bình giữa các ngành trong bộ dữ liệu này. Ngành AUTOBANK có xu hướng được xếp hạng ESG cao hơn, trong khi TECH, FMCG, và đặc biệt là RETAIL có xếp hạng ESG trung bình thấp hơn đáng kể. Điều này có thể phản ánh các tiêu chuẩn ESG khác nhau áp dụng cho từng ngành hoặc mức độ ưu tiên khác nhau của các công ty trong việc thực hành ESG.

1.3.5.10. Kết luận và giải thích phương pháp kiểm định

Các phát hiện chính:

Phân tích kiểm định sự khác biệt trung bình giữa các nhóm (Mục 1.3.5.1 đến 1.3.5.9) đã cung cấp những bằng chứng thống kê quan trọng:

  • Yếu tố phân loại chính: Biến investment (GOOD/BAD) cho thấy sự khác biệt trung bình rất lớn và có ý nghĩa thống kê đối với Real_Return, khẳng định vai trò phân loại hiệu quả của nó. Sự khác biệt về Sharpe_Ratio giữa hai nhóm này tuy có ý nghĩa thống kê (do cỡ mẫu lớn) nhưng chênh lệch thực tế lại rất nhỏ.

  • Ảnh hưởng của Ngành (sector): Ngành nghề có ảnh hưởng đáng kể đến hầu hết các chỉ số được kiểm định, bao gồm Real_Return, Volatility_Buy (Rủi ro), Log_PE (Định giá), Leverage_Ratio (Đòn bẩy), và ESG. Kết quả TukeyHSD cho thấy sự phân hóa rõ rệt, ví dụ ngành TECH có Real_ReturnLog_PE cao nhất, BANK có Leverage_Ratio cao nhất, FMCG có Volatility_Buy thấp nhất, RETAIL có ESG thấp nhất. Tuy nhiên, không tìm thấy bằng chứng về sự khác biệt ý nghĩa về Quy mô Giao dịch (amount) trung bình giữa các ngành.

  • Ảnh hưởng của Chiến lược nắm giữ (Holding_Period): Thời gian nắm giữ cũng ảnh hưởng có ý nghĩa thống kê đến Real_Return trung bình. Kết quả TukeyHSD cho thấy chiến lược Long-term (>180 ngày) có lợi suất thực tế trung bình cao nhất, tiếp theo là Mid-term và cuối cùng là Short-term.

Giải thích lựa chọn phương pháp kiểm định:

  • t-test vs. ANOVA: Kiểm định t-test (cụ thể là Welch t-test, không yêu cầu phương sai bằng nhau) được sử dụng khi so sánh giá trị trung bình giữa hai nhóm độc lập (ví dụ: investment có 2 nhóm GOOD và BAD). Khi cần so sánh giá trị trung bình giữa ba nhóm trở lên (ví dụ: sector có 5 nhóm, Holding_Period có 3 nhóm), chúng ta sử dụng ANOVA (Phân tích Phương sai). ANOVA kiểm tra giả thuyết H0 rằng trung bình của tất cả các nhóm là bằng nhau. Nếu ANOVA có ý nghĩa (p < 0.05), chúng ta mới thực hiện kiểm định post-hoc (như TukeyHSD) để xác định cụ thể những cặp nhóm nào khác biệt với nhau.

  • Kiểm định tham số (t-test/ANOVA) vs. Phi tham số: Mặc dù Mục 1.3.3 cho thấy nhiều biến định lượng không tuân theo phân phối chuẩn (một giả định của t-test/ANOVA), nghiên cứu này vẫn ưu tiên sử dụng các kiểm định tham số vì:

    1. Định lý giới hạn trung tâm (CLT) và cỡ mẫu Lớn: Với cỡ mẫu cực lớn (N > 300,000), theo CLT, phân phối của trung bình mẫu có xu hướng xấp xỉ chuẩn. Điều này làm cho các kiểm định t-test và ANOVA trở nên khá “robust” (ít bị ảnh hưởng) bởi sự vi phạm giả định về tính chuẩn của dữ liệu gốc. Kết quả p-value vẫn được coi là đáng tin cậy để xác định sự tồn tại của khác biệt trung bình.

    2. Khả năng giải thích: Các kiểm định tham số trực tiếp so sánh giá trị trung bình (mean), một chỉ số dễ hiểu và thường được quan tâm trong phân tích tài chính hơn là trung vị (median) hoặc xếp hạng (rank) mà các kiểm định phi tham số (như Wilcoxon test, Kruskal-Wallis test) sử dụng. Do đó, việc sử dụng t-test và ANOVA trong bối cảnh này, kết hợp với việc báo cáo các hạn chế về giả định, được xem là phù hợp cho mục tiêu phân tích khám phá dữ liệu (EDA).

Kết luận chung: Kết quả kiểm định cung cấp bằng chứng định lượng mạnh mẽ cho thấy các yếu tố phân loại như ngành nghề, chiến lược nắm giữ, và kết quả đầu tư có mối liên hệ ý nghĩa thống kê với hiệu suất, rủi ro, và định giá trong bộ dữ liệu NYSE này. Các phát hiện chi tiết từ TukeyHSD giúp làm rõ hơn bản chất của những khác biệt đó.

1.3.6. Giá trị ngoại lai

Các phân tích trước (Skewness, Kurtosis, Mean vs Median) đã cho thấy sự tồn tại của các giá trị cực đoan (outliers) trong nhiều biến định lượng. Mục này sẽ định lượng cụ thể mức độ outliers bằng phương pháp IQR (Interquartile Range) và phân tích đặc điểm của chúng.

1.3.6.1. Xác định ngưỡng ngoại lai bằng phương pháp IQR

# 1. Chọn các biến để phân tích outlier
# (Chọn các biến có độ lệch/độ nhọn cao từ Mục 1.3.3)
vars_for_outlier <- c("Real_Return", "amount", "PE", "Leverage_Ratio", "Nominal_Return") 

# 2. Áp dụng hàm identify_outliers_iqr cho từng biến
outlier_results_list <- lapply(vars_for_outlier, function(var) {
  identify_outliers_iqr(nyse_clean_core, var)
})

# 3. Chuyển list kết quả thành data frame để trình bày
outlier_threshold_df <- do.call(rbind, lapply(outlier_results_list, function(res) {
  data.frame(
    Variable = res$var_name,
    Q1 = round(res$Q1, 3),
    Q3 = round(res$Q3, 3),
    IQR = round(res$IQR, 3),
    Lower_Bound = round(res$Lower_Bound, 3),
    Upper_Bound = round(res$Upper_Bound, 3)
  )
}))

# 4. Trình bày bảng ngưỡng Outlier
cat("\n 1.3.6.1: Xác định Ngưỡng Ngoại lai bằng Phương pháp IQR \n")
## 
##  1.3.6.1: Xác định Ngưỡng Ngoại lai bằng Phương pháp IQR
kable(outlier_threshold_df,
      caption = "Bảng 1.3.18: Ngưỡng xác định Giá trị Ngoại lai (Outlier) bằng Phương pháp IQR",
      col.names = c("Tên Biến", "Q1", "Q3", "IQR", "Ngưỡng Dưới (Q1-1.5*IQR)", "Ngưỡng Trên (Q3+1.5*IQR)"),
      format = "pipe", align = "l")
Bảng 1.3.18: Ngưỡng xác định Giá trị Ngoại lai (Outlier) bằng Phương pháp IQR
Tên Biến Q1 Q3 IQR Ngưỡng Dưới (Q1-1.5*IQR) Ngưỡng Trên (Q3+1.5*IQR)
25% Real_Return -0.621 0.486 1.107 -2.281 2.146
25%1 amount 400.000 10000.000 9600.000 -14000.000 24400.000
25%2 PE 9.820 23.490 13.670 -10.685 43.995
25%3 Leverage_Ratio 2.486 6.692 4.207 -3.824 13.002
25%4 Nominal_Return -0.028 0.111 0.140 -0.238 0.321

Nhận xét:

Bảng 1.3.18 trình bày các ngưỡng dưới (Lower Bound) và ngưỡng trên (Upper Bound) được tính toán bằng phương pháp IQR (Q1 - 1.5IQR và Q3 + 1.5IQR) để xác định các giá trị ngoại lai tiềm năng cho 5 biến có độ lệch cao:

  • Lợi suất Thực tế (Real_Return):

    • Khoảng tứ phân vị (IQR) là 1.107 (từ Q1=-0.621 đến Q3=0.486).

    • Ngưỡng outlier được xác định là các giá trị dưới -2.281 (-228.1%) hoặc trên 2.146 (+214.6%). Bất kỳ lợi suất nào nằm ngoài khoảng rộng này đều được coi là ngoại lai.

  • Quy mô Giao dịch (amount):

    • IQR là 9,600 USD (từ Q1=400 đến Q3=10,000).

    • Ngưỡng outlier là các giá trị dưới -14,000 USD (không thực tế vì amount luôn dương) hoặc trên 24,400 USD. Các giao dịch có quy mô lớn hơn 24,400 USD được coi là ngoại lai.

  • Định giá (PE - Gốc):

    • IQR là 13.67 (từ Q1=9.82 đến Q3=23.49).

    • Ngưỡng outlier là các giá trị dưới -10.685 (P/E âm đã bị loại bỏ khi tính Log_PE) hoặc trên 43.995. Các công ty có P/E dương cao hơn ~44 lần được coi là có định giá ngoại lai.

  • Đòn bẩy (Leverage_Ratio):

    • IQR là 4.207 (từ Q1=2.486 đến Q3=6.692).

    • Ngưỡng outlier là các giá trị dưới -3.824 (không thực tế vì Leverage_Ratio > 1) hoặc trên 13.002. Các công ty có tỷ lệ ROE/ROA cao hơn ~13 lần được coi là có mức đòn bẩy ngoại lai (hoặc ROA rất nhỏ).

  • Lợi suất Danh nghĩa (Nominal_Return):

    • IQR là 0.140 (từ Q1=-0.028 đến Q3=0.111).

    • Ngưỡng outlier là các giá trị dưới -0.238 (-23.8%) hoặc trên 0.321 (+32.1%). Khoảng ngưỡng này hẹp hơn đáng kể so với Real_Return, phản ánh tác động của biến inflation (có giá trị âm) đã khuếch đại biên độ của Real_Return.

Kết luận: Các ngưỡng IQR cung cấp một định nghĩa định lượng rõ ràng cho các giá trị ngoại lai. Bước tiếp theo (1.3.6.2) sẽ sử dụng các ngưỡng này để đếm số lượng và tỷ lệ outlier thực tế trong dữ liệu.

1.3.6.2. Định lượng tỷ lệ phần trăm ngoại lai

# 1. Chuyển list kết quả thành data frame chứa số lượng outlier
outlier_count_df <- do.call(rbind, lapply(outlier_results_list, function(res) {
  data.frame(
    Variable = res$var_name,
    Num_Outliers_Low = res$Num_Outliers_Low,
    Num_Outliers_High = res$Num_Outliers_High,
    Total_Outliers = res$Total_Outliers,
    Total_NonNA = res$Total_NonNA # Tổng số quan sát không NA của biến đó
  )
}))

# 2. Tính toán tỷ lệ phần trăm outlier
outlier_percentage_df <- outlier_count_df %>%
  mutate(
    # Tỷ lệ outlier = Tổng outlier / Tổng số quan sát không NA
    Percentage_Outliers = round((Total_Outliers / Total_NonNA) * 100, 2) 
  ) %>%
  # Sắp xếp theo tỷ lệ giảm dần
  arrange(desc(Percentage_Outliers))

# 3. Trình bày bảng Tỷ lệ Outlier
cat("\n 1.3.6.2: Định lượng Tỷ lệ Phần trăm Ngoại lai \n")
## 
##  1.3.6.2: Định lượng Tỷ lệ Phần trăm Ngoại lai
kable(outlier_percentage_df %>% select(Variable, Total_Outliers, Total_NonNA, Percentage_Outliers),
      caption = "Bảng 1.3.19: Số lượng và Tỷ lệ Phần trăm Giá trị Ngoại lai",
      col.names = c("Tên Biến", "Số lượng Outlier", "Tổng Quan sát (Không NA)", "Tỷ lệ Outlier (%)"),
      format = "pipe", align = "l")
Bảng 1.3.19: Số lượng và Tỷ lệ Phần trăm Giá trị Ngoại lai
Tên Biến Số lượng Outlier Tổng Quan sát (Không NA) Tỷ lệ Outlier (%)
Nominal_Return 54140 405258 13.36
amount 47556 405258 11.73
PE 37258 405258 9.19
Leverage_Ratio 22506 402790 5.59
Real_Return 3140 405258 0.77

Bảng 1.3.19 định lượng số lượng và tỷ lệ phần trăm các giá trị được xác định là ngoại lai (outlier) theo phương pháp IQR (nằm ngoài khoảng [Q1 - 1.5IQR, Q3 + 1.5IQR]) cho 5 biến được kiểm tra:

  • Mức độ Outlier Cao:

    • Nominal_Return: Có tỷ lệ outlier cao nhất với 13.36% (54,140 quan sát). Điều này phù hợp với độ nhọn cực cao đã thấy ở Mục 1.3.3.2, cho thấy lợi suất danh nghĩa có phần đuôi rất dày chứa nhiều giá trị cực đoan (cả lãi rất cao và lỗ rất sâu).

    • amount: Có tỷ lệ outlier cao thứ hai với 11.73% (47,556 quan sát). Điều này chỉ ra rằng có một tỷ lệ đáng kể các giao dịch được thực hiện với số tiền rất lớn (cao hơn ngưỡng 24,400 USD).

    • PE (Gốc): Có tỷ lệ outlier là 9.19% (37,258 quan sát). Tỷ lệ này phản ánh sự tồn tại của nhiều công ty có P/E rất cao (> 44 lần) trong mẫu dữ liệu.

  • Mức độ Outlier Trung bình:

    • Leverage_Ratio: Có tỷ lệ outlier là 5.59% (22,506 quan sát). Tỷ lệ này cho thấy có một số lượng đáng kể các công ty sử dụng mức đòn bẩy rất cao (> 13 lần ROE/ROA), nhưng ít phổ biến hơn so với outlier về lợi suất hay quy mô. Lưu ý rằng Total_NonNA (402,790) thấp hơn tổng số quan sát do đã loại bỏ các trường hợp ROA gần 0.
  • Mức độ Outlier Thấp:

    • Real_Return: Đáng ngạc nhiên là Real_Return chỉ có tỷ lệ outlier rất thấp 0.77% (3,140 quan sát). Mặc dù nó có độ nhọn cao thứ hai (Kurtosis = 31.9), phương pháp IQR lại xác định ít outlier hơn so với Nominal_Return. Điều này có thể do biến inflation (thường âm) đã “kéo dãn” khoảng IQR của Real_Return (IQR = 1.107) so với Nominal_Return (IQR = 0.140), khiến các ngưỡng outlier trở nên rộng hơn và ít giá trị bị coi là cực đoan hơn theo định nghĩa này.

Kết luận: Phân tích định lượng cho thấy outliers là một đặc điểm phổ biến trong dữ liệu lợi suất (Nominal_Return), quy mô giao dịch (amount), và định giá (PE). Leverage_Ratio cũng có một tỷ lệ outlier đáng kể. Real_Return, mặc dù có đuôi dày, lại có ít outlier hơn theo định nghĩa IQR do khoảng IQR rộng hơn. Sự hiện diện của outliers nhấn mạnh tầm quan trọng của việc sử dụng các thước đo thống kê robust (như Median thay vì Mean) và cần xem xét các kỹ thuật xử lý outlier hoặc mô hình hóa phù hợp ở các bước sau.

1.3.6.3. Phân tích đặc điểm của các giao dịch ngoại lai

# 1. Lấy ngưỡng outlier cho Real_Return từ kết quả trước
cat("\n 1.3.6.3: Phân tích Đặc điểm Ngoại lai của Lợi suất Thực tế \n")
## 
##  1.3.6.3: Phân tích Đặc điểm Ngoại lai của Lợi suất Thực tế
rr_outlier_info <- outlier_results_list[[which(sapply(outlier_results_list, `[[`, "var_name") == "Real_Return")]]
rr_lower_bound <- rr_outlier_info$Lower_Bound
rr_upper_bound <- rr_outlier_info$Upper_Bound

cat(paste("Ngưỡng Outlier cho Real_Return: Dưới", round(rr_lower_bound, 3), "và Trên", round(rr_upper_bound, 3), "\n"))
## Ngưỡng Outlier cho Real_Return: Dưới -2.281 và Trên 2.146
# 2. Tạo data frame chỉ chứa các outlier của Real_Return
real_return_outliers <- nyse_clean_core %>%
  filter(Real_Return < rr_lower_bound | Real_Return > rr_upper_bound)

# 3. Phân tích đặc điểm: Tần suất theo Ngành (sector)
cat("\nPhân bổ Outlier Lợi suất Thực tế theo Ngành:\n")
## 
## Phân bổ Outlier Lợi suất Thực tế theo Ngành:
outlier_by_sector <- real_return_outliers %>%
  count(sector, name = "SoLuongOutlier") %>%
  mutate(TyLeTrongOutlier = round((SoLuongOutlier / sum(SoLuongOutlier)) * 100, 2)) %>%
  arrange(desc(SoLuongOutlier))

kable(outlier_by_sector,
      caption = "Bảng 1.3.20: Phân bổ Outlier Lợi suất Thực tế theo Ngành",
      col.names = c("Ngành", "Số lượng Outlier", "Tỷ lệ trong Tổng Outlier (%)"),
      format = "pipe", align = "l")
Bảng 1.3.20: Phân bổ Outlier Lợi suất Thực tế theo Ngành
Ngành Số lượng Outlier Tỷ lệ trong Tổng Outlier (%)
TECH 2785 88.69
RETAIL 241 7.68
BANK 80 2.55
AUTO 34 1.08
# 4. Phân tích đặc điểm: Tần suất theo Năm mua (Buy_Year)
cat("\nPhân bổ Outlier Lợi suất Thực tế theo Năm Mua:\n")
## 
## Phân bổ Outlier Lợi suất Thực tế theo Năm Mua:
outlier_by_year <- real_return_outliers %>%
  count(Buy_Year, name = "SoLuongOutlier") %>%
  mutate(TyLeTrongOutlier = round((SoLuongOutlier / sum(SoLuongOutlier)) * 100, 2)) %>%
  arrange(Buy_Year) # Sắp xếp theo năm

kable(outlier_by_year,
      caption = "Bảng 1.3.21: Phân bổ Outlier Lợi suất Thực tế theo Năm Mua",
      col.names = c("Năm Mua", "Số lượng Outlier", "Tỷ lệ trong Tổng Outlier (%)"),
      format = "pipe", align = "l")
Bảng 1.3.21: Phân bổ Outlier Lợi suất Thực tế theo Năm Mua
Năm Mua Số lượng Outlier Tỷ lệ trong Tổng Outlier (%)
2014 82 2.61
2015 2176 69.30
2016 882 28.09

Nhận xét:

Phân tích đặc điểm của 3,140 giao dịch có Lợi suất Thực tế (Real_Return) được xác định là ngoại lai (dưới -228.1% hoặc trên +214.6%) theo phương pháp IQR:

  • Phân bổ theo Ngành (Bảng 1.3.20):

    • Tập trung cao độ: Các giá trị lợi suất cực đoan (cả âm và dương) tập trung chủ yếu vào ngành TECH (Công nghệ), chiếm tới 88.69% tổng số outlier. Ngành RETAIL (Bán lẻ) đứng thứ hai nhưng chỉ chiếm 7.68%. Các ngành BANK (2.55%) và AUTO (1.08%) có rất ít outlier về lợi suất. (Lưu ý: Ngành FMCG không xuất hiện, nghĩa là không có outlier nào thuộc ngành này).

    • Ý nghĩa: Điều này cho thấy ngành Công nghệ là ngành có biến động lợi suất mạnh nhất và tiềm ẩn nhiều rủi ro/cơ hội cực đoan nhất trong bộ dữ liệu này. Các ngành khác có vẻ ổn định hơn về mặt lợi suất.

  • Phân bổ theo Năm Mua (Bảng 1.3.21):

    • Tập trung vào Giai đoạn Khủng hoảng/Biến động: Phần lớn các outlier (lợi suất cực đoan) xảy ra trong các giao dịch được thực hiện vào năm 2015 (69.30%)2016 (28.09%). Hai năm này chiếm tới 97.39% tổng số outlier. Năm 2014 chỉ chiếm 2.61%. (Lưu ý: Các năm 2013, 2017, 2018 không xuất hiện, nghĩa là không có outlier nào được mua vào các năm đó).

    • Ý nghĩa: Kết quả này cho thấy giai đoạn 2015-2016 là giai đoạn thị trường có biến động mạnh nhất, tạo ra nhiều cơ hội siêu lợi nhuận hoặc thua lỗ cực lớn, đặc biệt là trong ngành Công nghệ. Các năm khác có vẻ ổn định hơn.

Kết luận: Phân tích đặc điểm outlier của Real_Return cho thấy chúng không phân bổ ngẫu nhiên mà tập trung mạnh vào ngành Công nghệ (TECH) và các giao dịch được thực hiện trong giai đoạn 2015-2016. Điều này gợi ý rằng các mô hình phân tích hoặc dự báo cần xem xét đến yếu tố ngành và yếu tố thời gian (chu kỳ thị trường) để giải thích hoặc kiểm soát các biến động lợi suất cực đoan này.

1.3.6.4. Đánh giá ảnh hưởng của ngoại lai lên thống kê mô tả

(So sánh Mean và SD của Real_Return trước và sau khi loại bỏ outlier)

# 1. Tính Mean và SD gốc (đã có từ Mục 1.3.1)
cat("\n 1.3.6.4: Đánh giá ảnh hưởng của ngoại lai lên thống kê Lợi suất \n")
## 
##  1.3.6.4: Đánh giá ảnh hưởng của ngoại lai lên thống kê Lợi suất
mean_rr_original <- mean(nyse_clean_core$Real_Return, na.rm = TRUE)
sd_rr_original <- sd(nyse_clean_core$Real_Return, na.rm = TRUE)

# 2. Tạo data frame không chứa outlier của Real_Return
nyse_no_rr_outliers <- nyse_clean_core %>%
  filter(Real_Return >= rr_lower_bound & Real_Return <= rr_upper_bound)

# 3. Tính Mean và SD sau khi loại bỏ outlier
mean_rr_no_outlier <- mean(nyse_no_rr_outliers$Real_Return, na.rm = TRUE)
sd_rr_no_outlier <- sd(nyse_no_rr_outliers$Real_Return, na.rm = TRUE)

# 4. Tạo bảng so sánh
impact_df <- data.frame(
  Metric = c("Mean (Trung bình)", "SD (Độ lệch chuẩn)"),
  Original = round(c(mean_rr_original, sd_rr_original), 3),
  Without_Outliers = round(c(mean_rr_no_outlier, sd_rr_no_outlier), 3)
)

# 5. Trình bày bảng so sánh
kable(impact_df,
      caption = "Bảng 1.3.22: So sánh Thống kê Lợi suất Thực tế Trước và Sau khi Loại bỏ Outlier",
      col.names = c("Chỉ số Thống kê", "Giá trị Gốc", "Giá trị Sau khi Loại bỏ Outlier"),
      format = "pipe", align = "l")
Bảng 1.3.22: So sánh Thống kê Lợi suất Thực tế Trước và Sau khi Loại bỏ Outlier
Chỉ số Thống kê Giá trị Gốc Giá trị Sau khi Loại bỏ Outlier
Mean (Trung bình) 0.087 0.057
SD (Độ lệch chuẩn) 0.774 0.666

Nhận xét:

Bảng 1.3.22 so sánh giá trị Trung bình (Mean) và Độ lệch chuẩn (SD) của Lợi suất Thực tế (Real_Return) trước và sau khi loại bỏ 0.77% các giá trị ngoại lai (outlier) được xác định bằng phương pháp IQR.

  • Ảnh hưởng lên Trung bình (Mean): Giá trị trung bình đã giảm từ 0.087 (8.7%) xuống còn 0.057 (5.7%) sau khi loại bỏ outliers. Sự sụt giảm này cho thấy các outliers bị loại bỏ có xu hướng nghiêng về phía giá trị dương rất lớn (ví dụ: Max = 16.353), làm “thổi phồng” giá trị trung bình gốc. Giá trị trung bình mới (5.7%) thấp hơn đáng kể so với trung vị (16.7%), tiếp tục khẳng định tính lệch trái của phần lớn dữ liệu còn lại (sau khi bỏ outliers).

  • Ảnh hưởng lên Độ lệch chuẩn (SD): Độ lệch chuẩn cũng giảm từ 0.774 xuống 0.666. Việc loại bỏ các giá trị cực đoan ở hai đầu đuôi phân phối đã làm giảm mức độ phân tán tổng thể của dữ liệu, làm cho SD nhỏ hơn. Tuy nhiên, SD sau khi loại bỏ outlier (0.666) vẫn còn rất lớn so với trung bình (0.057), cho thấy Real_Return vẫn là một biến có độ biến động rất cao ngay cả khi đã loại bỏ các giá trị cực đoan nhất theo định nghĩa IQR.

  • Kết luận: Outliers có tác động đáng kể lên các thước đo thống kê mô tả cơ bản như Mean và SD. Giá trị trung bình gốc (8.7%) bị ảnh hưởng mạnh bởi các khoản lãi cực lớn. Độ lệch chuẩn cũng bị ảnh hưởng bởi biên độ rộng do outliers tạo ra. Việc loại bỏ outliers giúp có cái nhìn ổn định hơn về xu hướng trung tâm và độ phân tán của phần lớn dữ liệu, nhưng cũng cần lưu ý rằng outliers là một phần bản chất của dữ liệu lợi suất tài chính và việc loại bỏ chúng có thể làm mất thông tin về rủi ro đuôi (tail risk).

1.4. TRỰC QUAN HÓA DỮ LIỆU PHÂN TÍCH

library(dplyr)
library(ggplot2)  # Thư viện trực quan hóa chính
library(scales)   # Để định dạng trục (vd: percent, comma)
library(knitr)    # Để hiển thị bảng (nếu cần)
library(tidyr)    # Để xử lý dữ liệu (pivot_longer)
library(plotly)   # Sẽ dùng ở các mục sau

# Tải dữ liệu đã xử lý
load("nyse_processed_final.RData") 

1.4.1. Trực quan hóa phân bố đơn biến

1.4.1.1. Histogram & Density Plot: Lợi suất Thực tế (Real_Return)

# 1. Chuẩn bị dữ liệu: Chuyển sang dạng dài và lọc bớt giá trị cực đoan để dễ nhìn
return_comparison_long_viz <- nyse_clean_core %>%
  select(Nominal_Return, Real_Return) %>%
  # Lọc bỏ NA và các giá trị quá lớn/nhỏ để tập trung vào phần chính của phân bố
  filter(!is.na(Nominal_Return), !is.na(Real_Return),
         Nominal_Return > -1 & Nominal_Return < 2, # Giới hạn trục X cho Nominal
         Real_Return > -1 & Real_Return < 2) %>%    # Giới hạn trục X cho Real
  pivot_longer(
    cols = everything(),
    names_to = "Return_Type",
    values_to = "Return_Value"
  )

# 2. Vẽ Biểu đồ Mật độ (Density Plot) bằng ggplot2
p_return_density <- ggplot(return_comparison_long_viz, aes(x = Return_Value, fill = Return_Type)) +
  # geom_density vẽ đường cong ước lượng mật độ
  # alpha = 0.6 giúp nhìn xuyên qua các lớp màu
  geom_density(alpha = 0.6) + 
  # Thêm đường dọc tại x=0 để phân biệt lãi/lỗ
  geom_vline(xintercept = 0, linetype = "dashed", color = "red") +
  # Định dạng trục X thành tỷ lệ phần trăm
  scale_x_continuous(labels = scales::percent_format(accuracy = 1)) +
  # Đặt tiêu đề và nhãn trục
  labs(title = "Biểu đồ 1.4.1: So sánh phân bố Lợi suất Thực tế và Danh nghĩa",
       subtitle = "Đã lọc giá trị ngoài khoảng [-100%, +200%] để dễ nhìn",
       x = "Lợi suất", 
       y = "Mật độ Ước lượng",
       fill = "Loại Lợi suất") + # Tiêu đề cho phần chú thích màu
  # Sử dụng theme tối giản
  theme_minimal() +
  # Điều chỉnh vị trí chú thích (legend)
  theme(legend.position = "bottom") 

# 3. Hiển thị biểu đồ
print(p_return_density)

1.4.1.2. Bar Chart: Tần suất Ngành (sector)

# 1. Tính toán số lượng theo ngành (trong mục 1.3.2.1)
sector_freq_viz <- nyse_clean_core %>%
 count(sector, name = "Count") %>%
 arrange(desc(Count))

# 2. Vẽ Biểu đồ Cột (Bar Chart) bằng ggplot2
p_sector_bar <- ggplot(sector_freq_viz, 
                       # aes() định nghĩa ánh xạ: trục X là ngành (sắp xếp lại), trục Y là số lượng
                       # reorder() sắp xếp các thanh theo Count giảm dần
                       aes(x = reorder(sector, Count), y = Count, fill = sector)) +
  # geom_col vẽ biểu đồ cột với chiều cao tương ứng giá trị Y
  geom_col(show.legend = FALSE) + # Ẩn chú thích màu vì trục X đã thể hiện
  # geom_text thêm nhãn số lượng trên đỉnh cột
  # stat="identity" dùng giá trị Y trực tiếp, nudge_y đẩy nhẹ nhãn lên trên
  geom_text(aes(label = scales::comma(Count)), stat = "identity", nudge_y = 5000, size = 3.5) +
  # coord_flip() lật trục X và Y để tên ngành dễ đọc hơn
  coord_flip() +
  # Định dạng trục Y với dấu phẩy ngăn cách hàng nghìn
  scale_y_continuous(labels = scales::comma) +
  # Đặt tiêu đề và nhãn trục
  labs(title = "Biểu đồ 1.4.2: Tần suất Giao dịch theo Ngành",
       x = "Ngành (Sector)",
       y = "Số lượng Giao dịch") +
  # Sử dụng theme tối giản
  theme_minimal()

# 3. Hiển thị biểu đồ
print(p_sector_bar)

1.4.1.3. Bar Chart: Tần suất Kết quả Đầu tư (investment)

# 1. Tính toán số lượng theo investment (trong mục 1.3.2.1)
investment_freq_viz <- nyse_clean_core %>%
 count(investment, name = "Count")

# 2. Vẽ Biểu đồ Cột
p_investment_bar <- ggplot(investment_freq_viz, aes(x = investment, y = Count, fill = investment)) +
  geom_col(show.legend = FALSE) +
  geom_text(aes(label = scales::comma(Count)), vjust = -0.5, size = 4) + # vjust điều chỉnh vị trí nhãn theo chiều dọc
  scale_y_continuous(labels = scales::comma) +
  labs(title = "Biểu đồ 1.4.3: Tần suất Giao dịch theo Kết quả Đầu tư (GOOD/BAD)",
       x = "Kết quả Đầu tư",
       y = "Số lượng Giao dịch") +
  theme_minimal()

# 3. Hiển thị biểu đồ
print(p_investment_bar)

1.4.1.4. Bar Chart: Tần suất Thời gian Nắm giữ (Holding_Period)

# 1. Tính toán số lượng theo Holding_Period (trong mục 1.3.2.1 / 1.1.3.6)
holding_freq_viz <- nyse_clean_core %>%
 count(Holding_Period, name = "Count")

# 2. Vẽ Biểu đồ Cột
p_holding_bar <- ggplot(holding_freq_viz, aes(x = Holding_Period, y = Count, fill = Holding_Period)) +
  geom_col(show.legend = FALSE) +
  geom_text(aes(label = scales::comma(Count)), vjust = -0.5, size = 4) +
  scale_y_continuous(labels = scales::comma) +
  labs(title = "Biểu đồ 1.4.4: Tần suất Giao dịch theo Thời gian Nắm giữ",
       x = "Thời gian Nắm giữ",
       y = "Số lượng Giao dịch") +
  theme_minimal()

# 3. Hiển thị biểu đồ
print(p_holding_bar)

1.4.1.5. Histogram & Density Plot: P/E đã chuẩn hóa (Log_PE)

# 1. Vẽ Biểu đồ Histogram kết hợp Density Plot cho Log_PE
p_logpe_hist <- ggplot(nyse_clean_core, aes(x = Log_PE)) +
  # geom_histogram vẽ biểu đồ tần suất dạng cột
  # bins = 50 chia thành 50 khoảng giá trị
  # fill задает цвет заливки, color - цвет контура
  geom_histogram(aes(y = after_stat(density)), # Trục Y là mật độ thay vì tần suất
                 bins = 50, fill = "#1F77B4", color = "white", alpha = 0.7) +
  # geom_density vẽ đường cong mật độ ước lượng
  geom_density(color = "red", linewidth = 1) + # linewidth thay cho size
  # Đặt tiêu đề và nhãn trục
  labs(title = "Biểu đồ 1.4.5: Phân bố Tỷ suất P/E sau Chuẩn hóa Logarit (Log_PE)",
       subtitle = "Histogram (Mật độ) và Đường cong Mật độ Ước lượng",
       x = "Giá trị Log(PE)",
       y = "Mật độ (Density)") +
  # Sử dụng theme tối giản
  theme_minimal()

# 2. Hiển thị biểu đồ
print(p_logpe_hist)

1.4.1.6. Box Plot: Lợi suất Thực tế (Real_Return)

# 1. Vẽ Box Plot cho Real_Return
p_realreturn_box <- ggplot(nyse_clean_core, aes(x = "", y = Real_Return)) + # x="" để vẽ 1 boxplot duy nhất
  # geom_boxplot vẽ biểu đồ hộp
  # outlier.shape=1 vẽ outlier dạng vòng tròn rỗng (dễ nhìn hơn điểm đặc)
  # outlier.alpha=0.3 làm mờ outlier
  geom_boxplot(fill = "lightblue", outlier.shape = 1, outlier.alpha = 0.3) +
  # Định dạng trục Y thành tỷ lệ phần trăm
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  # Đặt tiêu đề và nhãn trục (bỏ nhãn trục X)
  labs(title = "Biểu đồ 1.4.6: Phân bố Lợi suất Thực tế (Real_Return)",
       subtitle = "Boxplot thể hiện Median, IQR và Outliers",
       x = "",
       y = "Lợi suất Thực tế (%)") +
  # Sử dụng theme tối giản
  theme_minimal() +
  # Xóa các yếu tố không cần thiết của trục X
  theme(axis.ticks.x = element_blank(),
        axis.text.x = element_blank())

# 2. Hiển thị biểu đồ
print(p_realreturn_box)

1.4.1.7. Box Plot: Quy mô Giao dịch (amount)

# 1. Vẽ Box Plot cho amount
p_amount_box <- ggplot(nyse_clean_core, aes(x = "", y = amount)) +
  geom_boxplot(fill = "lightgreen", outlier.shape = 1, outlier.alpha = 0.1) + # alpha thấp hơn do nhiều outlier
  # Sử dụng thang log10 cho trục Y do độ lệch rất lớn của amount
  # Điều này giúp "nén" các giá trị lớn lại để thấy rõ hơn phần hộp và râu
  scale_y_log10(labels = scales::comma_format()) + # Định dạng số với dấu phẩy
  # Đặt tiêu đề và nhãn trục
  labs(title = "Biểu đồ 1.4.7: Phân bố Quy mô Giao dịch (amount)",
       subtitle = "Boxplot thể hiện Median, IQR và Outliers (Trục Y Logarit)",
       x = "",
       y = "Số tiền Đầu tư (USD, thang Log10)") +
  theme_minimal() +
  theme(axis.ticks.x = element_blank(),
        axis.text.x = element_blank())

# 2. Hiển thị biểu đồ
print(p_amount_box)

1.4.1.8. Histogram & Density Plot: Đòn bẩy Tài chính (Leverage_Ratio)

# 1. Vẽ Histogram kết hợp Density Plot cho Leverage_Ratio
# Lọc bỏ NA và có thể lọc giá trị quá lớn để dễ nhìn hơn
p_leverage_hist <- ggplot(nyse_clean_core %>% filter(!is.na(Leverage_Ratio) & Leverage_Ratio < 20), 
                          aes(x = Leverage_Ratio)) + # Giới hạn trục X < 20
  geom_histogram(aes(y = after_stat(density)), bins = 50, 
                 fill = "#FF7F0E", color = "white", alpha = 0.7) +
  geom_density(color = "blue", linewidth = 1) +
  labs(title = "Biểu đồ 1.4.8: Phân bố Tỷ số Đòn bẩy Tài chính (Leverage_Ratio)",
       subtitle = "Đã lọc NA và giá trị > 20 để dễ nhìn",
       x = "Đòn bẩy Tài chính (ROE/ROA)",
       y = "Mật độ (Density)") +
  theme_minimal()

# 2. Hiển thị biểu đồ
print(p_leverage_hist)

1.4.1.9. Histogram & Density Plot: Rủi ro (Volatility_Buy)

# 1. Vẽ Histogram kết hợp Density Plot cho Volatility_Buy
p_volatility_hist <- ggplot(nyse_clean_core, aes(x = Volatility_Buy)) +
  geom_histogram(aes(y = after_stat(density)), bins = 50, 
                 fill = "#9467BD", color = "white", alpha = 0.7) +
  geom_density(color = "black", linewidth = 1) +
  labs(title = "Biểu đồ 1.4.9: Phân bố Rủi ro Đầu tư (Volatility_Buy)",
       x = "Độ biến động tại thời điểm Mua",
       y = "Mật độ (Density)") +
  theme_minimal()

# 2. Hiển thị biểu đồ
print(p_volatility_hist)

1.4.1.10. Histogram & Density Plot: Tỷ suất Sharpe (Sharpe_Ratio)

# 1. Vẽ Histogram kết hợp Density Plot cho Sharpe_Ratio
p_sharpe_hist <- ggplot(nyse_clean_core, aes(x = Sharpe_Ratio)) +
  geom_histogram(aes(y = after_stat(density)), bins = 50, 
                 fill = "#8C564B", color = "white", alpha = 0.7) +
  geom_density(color = "darkred", linewidth = 1) +
  labs(title = "Biểu đồ 1.4.10: Phân bố Tỷ suất Sharpe",
       x = "Sharpe Ratio",
       y = "Mật độ (Density)") +
  theme_minimal()

# 2. Hiển thị biểu đồ
print(p_sharpe_hist)

PHẦN 2. PHÂN TÍCH DỮ LIỆU TÀI CHÍNH VÀ THỊ TRƯỜNG CỦA MÃ CHỨNG KHOÁN GAS (2014-2024)

2.1 GIỚI THIỆU BỘ DỮ LIỆU

  • Mục tiêu phân tích

Mục tiêu chính là phân tích sức khỏe tài chính và hiệu quả hoạt động của Tổng Công ty Khí Việt Nam (GAS) trong giai đoạn 11 năm (2014-2024). Phân tích cũng tìm cách khám phá mối quan hệ (nếu có) giữa các chỉ số tài chính nội tại và giá trị thị trường của cổ phiếu.

  • Nguồn dữ liệu

Bộ dữ liệu được xây dựng từ hai nguồn chính:

  • Dữ liệu tài chính: Trích xuất từ các Báo cáo tài chính hợp nhất đã được kiểm toán (Bảng Cân đối Kế toán, Bảng Kết quả Kinh doanh, Bảng Lưu Chuyển Tiền Tệ) hàng năm của GAS, từ 31/12/2014 đến 31/12/2024.

  • Dữ liệu thị trường: Thu thập từ các nguồn dữ liệu thị trường (ví dụ: CafeF, Vietstock) về giá cổ phiếu tại ngày chốt báo cáo (31/12 hàng năm).

  • Đơn vị quan sát và phạm vi

    • Đơn vị quan sát: Dữ liệu được tổng hợp theo năm.

    • Phạm vi thời gian: 11 năm, từ 2014 đến 2024.

  • Cấu trúc bộ dữ liệu (Các biến số):

    • Bộ dữ liệu GAS_data_final sau khi xử lý (ở mục 2.3) sẽ bao gồm 12 biến sau:

    • Biến định danh (Identifier):

      1. Nam: (Numeric) Năm quan sát, từ 2014 đến 2024.
    • Biến Tài chính Cơ bản (Trích xuất từ BCTC):

      1. DoanhThu: (Numeric) Doanh thu thuần hàng năm.

      2. LoiNhuanSauThue: (Numeric) Lợi nhuận sau thuế của cổ đông công ty mẹ.

      3. TongTaiSan: (Numeric) Tổng cộng tài sản cuối kỳ.

      4. NoPhaiTra: (Numeric) Tổng nợ phải trả cuối kỳ.

      5. VonChuSoHuu: (Numeric) Tổng vốn chủ sở hữu cuối kỳ.

    • Biến Thị trường:

      1. Gia_DongCua_CuoiNam: (Numeric) Giá đóng cửa của cổ phiếu GAS tại ngày 31/12.
    • Biến Phái sinh (Được tính toán - Feature Engineering):

      1. ROE_Nam: (Numeric) Tỷ suất lợi nhuận trên vốn chủ sở hữu (LNST / VCSH).

      2. ROA_Nam: (Numeric) Tỷ suất lợi nhuận trên tổng tài sản (LNST / Tổng Tài sản).

      3. TySoNo_Tren_VCSH: (Numeric) Tỷ số Nợ trên Vốn chủ sở hữu, đo lường đòn bẩy tài chính.

      4. DoanhThu_TangTruong_YoY: (Numeric) Tỷ lệ % tăng trưởng doanh thu so với năm trước.

      5. LoiNhuan_TangTruong_YoY: (Numeric) Tỷ lệ % tăng trưởng lợi nhuận so với năm trước.

2.2 ĐỌC DỮ LIỆU

# 1. Tải thư viện
library(readxl) # Dùng để đọc file Excel
library(dplyr) # Dùng để xử lý dữ liệu (rename, mutate, filter...)
library(stringr) # Dùng để xử lý chuỗi (str_remove_all)

# 2. Đọc dữ liệu từ excel
bctc_path <- "C:/Users/Admin/Documents/NGÔN NGỮ R/PV GAS.xlsx"

# 3. Đọc sheet cụ thể
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

# 4. Chuẩn hóa tên cột
# Đổi tên cột đầu tiên (chỉ tiêu) thành "ChiTieu" cho cả 2 bảng
if ("TÀI SẢN" %in% names(bckt_raw)) { # Dùng 'if' để kiểm tra xem cột 'TÀI SẢN' (%in%) có tồn tại trong danh sách tên cột (names()) của bckt_raw không
  bckt_raw <- bckt_raw %>% rename(ChiTieu = `TÀI SẢN`)} # Nếu có, dùng 'rename' đổi tên cột 'TÀI SẢN' thành 'ChiTieu'
if ("CHỈ TIÊU" %in% names(kqkd_raw)) {kqkd_raw <- kqkd_raw %>% rename(ChiTieu = `CHỈ TIÊU`)}
print("Đã chuẩn hóa tên cột thành 'ChiTieu'.")
## [1] "Đã chuẩn hóa tên cột thành 'ChiTieu'."

2.3 XỬ LÝ, MÃ HOÁ VÀ TẠO BIẾN MỚI

# PHẦN 1: HÀM HỖ TRỢ

# 1. Hàm trích xuất (với gỡ lỗi 'fixed = TRUE')
extract_row_data <- function(df, chi_tieu_name) {
  # Lọc hàng dựa trên chuỗi ký tự chính xác (fixed = TRUE)
  data_row <- df %>% 
    filter(grepl(chi_tieu_name, ChiTieu, ignore.case = TRUE, fixed = TRUE))
  
  # Báo lỗi nếu không tìm thấy (giúp gỡ lỗi)
  if(nrow(data_row) == 0) {
    stop(paste("\n--- LỖI TÌM KIẾM (fixed=TRUE) ---",
                 "\nKhông tìm thấy chỉ tiêu nào khớp CHÍNH XÁC với chuỗi:", 
                 "\n'", chi_tieu_name, "'",
                 "\n>>> Hãy kiểm tra chuỗi này từ file Excel"))
  }
  # Báo lỗi nếu tìm thấy nhiều hơn 1 hàng (đảm bảo tính duy nhất)
  if(nrow(data_row) > 1) {
    stop(paste("\n--- LỖI TÌM KIẾM (fixed=TRUE) ---",
                 "\nTìm thấy nhiều hơn 1 hàng khớp với chuỗi:", 
                 "\n'", chi_tieu_name, "'",
                 "\n>>> Hãy cung cấp chuỗi ký tự ở phần 3 sao cho nó là duy nhất."))
  }
  
  # Chọn 11 cột dữ liệu (ứng với 2014-2024) và chuyển thành vector
  data_vec <- data_row %>% 
    select(-ChiTieu) %>% # Bỏ cột 'ChiTieu'
    select(1:11) %>% # Lấy 11 cột (2014 -> 2024)
    unlist(use.names = FALSE) # Chuyển thành vector
  
  return(data_vec)
}

# 2. Hàm làm sạch số (loại bỏ dấu ".")
clean_numeric <- function(x) {
  x_char <- as.character(x) # Chuyển sang dạng text
  x_cleaned <- str_remove_all(x_char, "\\.") # Loại bỏ tất cả dấu chấm
  return(as.numeric(x_cleaned)) # Chuyển về dạng số
}

# PHẦN 2: TRÍCH XUẤT VÀ LÀM SẠCH

print("Bắt đầu trích xuất dữ liệu...")
## [1] "Bắt đầu trích xuất dữ liệu..."
nam_vec <- 2014:2024 # Tạo vector 11 năm

# 3. Trích xuất các chỉ tiêu cốt lõi
# Từ KQKD
dt_vec <- extract_row_data(kqkd_raw, "3. Doanh thu thuần về bán hàng và cung cấp dịch vụ")
lnst_vec <- extract_row_data(kqkd_raw, "18.1. Lợi nhuận sau thuế của cổ đông của Công ty mẹ")


# Từ BCKT
tts_vec <- extract_row_data(bckt_raw, "TỔNG CỘNG TÀI SẢN")
no_vec <- extract_row_data(bckt_raw, "C. NỢ PHẢI TRẢ") 
vcsh_vec <- extract_row_data(bckt_raw, "D. VỐN CHỦ SỞ HỮU")

print("Đã trích xuất thành công 5 chỉ tiêu.")
## [1] "Đã trích xuất thành công 5 chỉ tiêu."
# 4. Tạo bảng dữ liệu (Data Frame) và Mã hóa
# Tạo bảng từ các vector đã trích xuất
GAS_data_df <- data.frame(
  Nam = nam_vec,
  DoanhThu_Raw = dt_vec,
  LoiNhuanSauThue_Raw = lnst_vec,
  TongTaiSan_Raw = tts_vec,
  NoPhaiTra_Raw = no_vec,
  VonChuSoHuu_Raw = vcsh_vec
)

# Áp dụng hàm làm sạch số (Mã hóa)
GAS_data_final <- GAS_data_df %>%
  mutate(across(-Nam, clean_numeric)) %>% # Áp dụng hàm 'clean_numeric' cho TẤT CẢ các cột TRỪ cột 'Nam'
  # Đổi tên cột
  rename(
    DoanhThu = DoanhThu_Raw,
    LoiNhuanSauThue = LoiNhuanSauThue_Raw,
    TongTaiSan = TongTaiSan_Raw,
    NoPhaiTra = NoPhaiTra_Raw,
    VonChuSoHuu = VonChuSoHuu_Raw
  )


print("Đã làm sạch và mã hóa dữ liệu số.")
## [1] "Đã làm sạch và mã hóa dữ liệu số."
print(head(GAS_data_final)) # In 6 dòng đầu để kiểm tra
##    Nam     DoanhThu LoiNhuanSauThue   TongTaiSan    NoPhaiTra  VonChuSoHuu
## 1 2014 7.339340e+13    1.412268e+13 5.379141e+13 1.611206e+13 3.767935e+13
## 2 2015 6.430020e+13    2.984305e+11 5.671461e+13 1.382554e+13 4.288906e+13
## 3 2016 5.907619e+13    1.522566e+11 5.675385e+13 1.591001e+13 4.084385e+13
## 4 2017 6.452244e+13    2.529287e+11 6.188934e+13 1.861783e+13 4.327151e+13
## 5 2018 7.561155e+13    2.545966e+11 6.261442e+13 1.574730e+13 4.686713e+13
## 6 2019 7.500530e+13    1.834033e+11 6.217874e+11 1.256426e+13 4.961453e+13
# PHẦN 3: BỔ SUNG DỮ LIỆU & TẠO BIẾN MỚI (FEATURE ENGINEERING)

# 5. Bổ sung dữ liệu thị trường 
gia_dong_cua_vec <- c(
  34154.5, # 2014
  18128.8,  # 2015
  33089.0,  # 2016
  56311.2,  # 2017
  52231.7,  # 2018
  58209.9,  # 2019
  56436.3,  # 2020
  64672.3,  # 2021
  70096.3, # 2022
  64830.3,  # 2023
  64160.1   # 2024
)

# 6. Tính toán các chỉ số phái sinh
GAS_data_final <- GAS_data_final %>%
  mutate(
    Gia_DongCua_CuoiNam = gia_dong_cua_vec, # Thêm cột giá 
    # Các chỉ số hiệu quả
    ROE_Nam = (LoiNhuanSauThue / VonChuSoHuu) * 100, # Đơn vị %
    ROA_Nam = (LoiNhuanSauThue / TongTaiSan) * 100, # Đơn vị %
    
    # Chỉ số đòn bẩy
    TySoNo_Tren_VCSH = NoPhaiTra / VonChuSoHuu, # Tỷ lệ
    
    # Chỉ số tăng trưởng
    DoanhThu_TangTruong_YoY = (DoanhThu / lag(DoanhThu) - 1) * 100, # lag() là hàm lấy giá trị của hàng (năm) trước đó
    LoiNhuan_TangTruong_YoY = (LoiNhuanSauThue / lag(LoiNhuanSauThue) - 1) * 100
  )

# 7. Xử lý giá trị NA (cho năm 2014)
GAS_data_final <- GAS_data_final %>%
  mutate(
    # Hàm ifelse: NẾU (IF) giá trị là NA, THÌ (THEN) đổi thành 0, NẾU KHÔNG (ELSE) giữ nguyên giá trị cũ
    DoanhThu_TangTruong_YoY = ifelse(is.na(DoanhThu_TangTruong_YoY), 0, DoanhThu_TangTruong_YoY),
    LoiNhuan_TangTruong_YoY = ifelse(is.na(LoiNhuan_TangTruong_YoY), 0, LoiNhuan_TangTruong_YoY)
    # (ĐÃ LOẠI BỎ XỬ LÝ P/E)
  )

print("Bảng dữ liệu 'GAS_data_final' hoàn chỉnh (11 hàng, 12 cột):")
## [1] "Bảng dữ liệu 'GAS_data_final' hoàn chỉnh (11 hàng, 12 cột):"
# Sử dụng as.data.frame để buộc R in tất cả 11 hàng
print(as.data.frame(GAS_data_final))
##     Nam     DoanhThu LoiNhuanSauThue   TongTaiSan    NoPhaiTra  VonChuSoHuu
## 1  2014 7.339340e+13    1.412268e+13 5.379141e+13 1.611206e+13 3.767935e+13
## 2  2015 6.430020e+13    2.984305e+11 5.671461e+13 1.382554e+13 4.288906e+13
## 3  2016 5.907619e+13    1.522566e+11 5.675385e+13 1.591001e+13 4.084385e+13
## 4  2017 6.452244e+13    2.529287e+11 6.188934e+13 1.861783e+13 4.327151e+13
## 5  2018 7.561155e+13    2.545966e+11 6.261442e+13 1.574730e+13 4.686713e+13
## 6  2019 7.500530e+13    1.834033e+11 6.217874e+11 1.256426e+13 4.961453e+13
## 7  2020 6.413497e+13    7.854956e+12 6.320840e+13 1.370872e+13 4.949968e+13
## 8  2021 7.899216e+13    8.672965e+12 7.876870e+13 2.657534e+13 5.219273e+13
## 9  2022 1.007235e+14    1.479832e+13 8.266265e+13 2.148909e+13 6.117356e+13
## 10 2023 8.995391e+13    1.160603e+13 8.775446e+13 2.245584e+13 6.529862e+13
## 11 2024 1.035641e+14    1.039873e+13 8.185488e+13 2.028389e+13 6.157100e+13
##    Gia_DongCua_CuoiNam    ROE_Nam    ROA_Nam TySoNo_Tren_VCSH
## 1              34154.5 37.4812093 26.2545195        0.4276098
## 2              18128.8  0.6958196  0.5261969        0.3223559
## 3              33089.0  0.3727773  0.2682753        0.3895325
## 4              56311.2  0.5845154  0.4086788        0.4302562
## 5              52231.7  0.5432306  0.4066101        0.3359987
## 6              58209.9  0.3696564 29.4961404        0.2532374
## 7              56436.3 15.8687001 12.4270758        0.2769456
## 8              64672.3 16.6171897 11.0106737        0.5091771
## 9              70096.3 24.1907065 17.9020595        0.3512806
## 10             64830.3 17.7737762 13.2255742        0.3438945
## 11             64160.1 16.8890076 12.7038606        0.3294390
##    DoanhThu_TangTruong_YoY LoiNhuan_TangTruong_YoY
## 1                0.0000000               0.0000000
## 2              -12.3896680             -97.8868699
## 3               -8.1244079             -48.9808874
## 4                9.2190229              66.1199968
## 5               17.1864317               0.6594479
## 6               -0.8017943             -27.9631807
## 7              -14.4927520            4182.8873336
## 8               23.1655081              10.4139240
## 9               27.5108241              70.6258138
## 10             -10.6922788             -21.5719566
## 11              15.1302157             -10.4023558

2.4 THỐNG KÊ MÔ TẢ

2.4.1. Thống kê tổng quan

# Thao tác 1: Kiểm tra cấu trúc dữ liệu.
# Mục đích: Đảm bảo 12 biến đã được mã hóa đúng kiểu (numeric/int)
print("--- Thao tác 1: Cấu trúc dữ liệu (str) ---")
## [1] "--- Thao tác 1: Cấu trúc dữ liệu (str) ---"
str(GAS_data_final)
## 'data.frame':    11 obs. of  12 variables:
##  $ Nam                    : int  2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 ...
##  $ DoanhThu               : num  7.34e+13 6.43e+13 5.91e+13 6.45e+13 7.56e+13 ...
##  $ LoiNhuanSauThue        : num  1.41e+13 2.98e+11 1.52e+11 2.53e+11 2.55e+11 ...
##  $ TongTaiSan             : num  5.38e+13 5.67e+13 5.68e+13 6.19e+13 6.26e+13 ...
##  $ NoPhaiTra              : num  1.61e+13 1.38e+13 1.59e+13 1.86e+13 1.57e+13 ...
##  $ VonChuSoHuu            : num  3.77e+13 4.29e+13 4.08e+13 4.33e+13 4.69e+13 ...
##  $ Gia_DongCua_CuoiNam    : num  34155 18129 33089 56311 52232 ...
##  $ ROE_Nam                : num  37.481 0.696 0.373 0.585 0.543 ...
##  $ ROA_Nam                : num  26.255 0.526 0.268 0.409 0.407 ...
##  $ TySoNo_Tren_VCSH       : num  0.428 0.322 0.39 0.43 0.336 ...
##  $ DoanhThu_TangTruong_YoY: num  0 -12.39 -8.12 9.22 17.19 ...
##  $ LoiNhuan_TangTruong_YoY: num  0 -97.887 -48.981 66.12 0.659 ...
# Thao tác 2: Tóm tắt (Min, Q1, Median, Mean, Q3, Max)
# Mục đích: Xem nhanh phân phối, giá trị trung tâm và các điểm ngoại lai
print("--- Thao tác 2: Tóm tắt (summary) ---")
## [1] "--- Thao tác 2: Tóm tắt (summary) ---"
# Dùng options(scipen=999) để R hiển thị số đầy đủ, không dùng ký hiệu "e+" (scientific notation)
options(scipen = 999) 
print(summary(GAS_data_final))
##       Nam          DoanhThu               LoiNhuanSauThue         
##  Min.   :2014   Min.   : 59076193175700   Min.   :  152256595845  
##  1st Qu.:2016   1st Qu.: 64411322507300   1st Qu.:  253762618570  
##  Median :2019   Median : 75005297175400   Median : 7854955921940  
##  Mean   :2019   Mean   : 77207071686500   Mean   : 6235935457210  
##  3rd Qu.:2022   3rd Qu.: 84473031317800   3rd Qu.:11002380348300  
##  Max.   :2024   Max.   :103564126563000   Max.   :14798317219700  
##    TongTaiSan               NoPhaiTra               VonChuSoHuu            
##  Min.   :  621787389634   Min.   :12564256032000   Min.   :37679348560600  
##  1st Qu.:56734229902900   1st Qu.:14786419268900   1st Qu.:43080285823500  
##  Median :62614420245300   Median :16112058787500   Median :49499680985500  
##  Mean   :62421319359500   Mean   :17935442513000   Mean   :50081910482900  
##  3rd Qu.:80311793048400   3rd Qu.:20886487476900   3rd Qu.:56683147115100  
##  Max.   :87754455330400   Max.   :26575344013400   Max.   :65298620274400  
##  Gia_DongCua_CuoiNam    ROE_Nam           ROA_Nam        TySoNo_Tren_VCSH
##  Min.   :18129       Min.   : 0.3697   Min.   : 0.2683   Min.   :0.2532  
##  1st Qu.:43193       1st Qu.: 0.5639   1st Qu.: 0.4674   1st Qu.:0.3259  
##  Median :56436       Median :15.8687   Median :12.4271   Median :0.3439  
##  Mean   :52029       Mean   :11.9442   Mean   :11.3300   Mean   :0.3609  
##  3rd Qu.:64416       3rd Qu.:17.3314   3rd Qu.:15.5638   3rd Qu.:0.4086  
##  Max.   :70096       Max.   :37.4812   Max.   :29.4961   Max.   :0.5092  
##  DoanhThu_TangTruong_YoY LoiNhuan_TangTruong_YoY
##  Min.   :-14.493         Min.   : -97.89        
##  1st Qu.: -9.408         1st Qu.: -24.77        
##  Median :  0.000         Median :   0.00        
##  Mean   :  4.156         Mean   : 374.90        
##  3rd Qu.: 16.158         3rd Qu.:  38.27        
##  Max.   : 27.511         Max.   :4182.89
# Thao tác 3: Định dạng lại đơn vị (Tỷ VND) để dễ đọc
# Mục đích: Tạo bảng hiển thị đễ dễ đọc
print("--- Thao tác 3: Bảng dữ liệu đã định dạng (Tỷ VND) ---")
## [1] "--- Thao tác 3: Bảng dữ liệu đã định dạng (Tỷ VND) ---"
GAS_data_display <- GAS_data_final %>%
  mutate(
    # Tạo các cột mới chia cho 1 tỷ (1e9)
    DoanhThu_TyVND = DoanhThu / 1e9,
    LoiNhuanSauThue_TyVND = LoiNhuanSauThue / 1e9,
    TongTaiSan_TyVND = TongTaiSan / 1e9,
    NoPhaiTra_TyVND = NoPhaiTra / 1e9,
    VonChuSoHuu_TyVND = VonChuSoHuu / 1e9
  ) %>%
  # Chỉ chọn các cột đã định dạng và các cột %/tỷ lệ
  select(
    Nam, 
    DoanhThu_TyVND, 
    LoiNhuanSauThue_TyVND, 
    TongTaiSan_TyVND, 
    NoPhaiTra_TyVND, 
    VonChuSoHuu_TyVND, 
    Gia_DongCua_CuoiNam, 
    ROE_Nam, 
    ROA_Nam, 
    TySoNo_Tren_VCSH, 
    DoanhThu_TangTruong_YoY, 
    LoiNhuan_TangTruong_YoY
  )

# Dùng round() để làm tròn đến 2 chữ số thập phân cho dễ đọc
print(round(as.data.frame(GAS_data_display), 2))
##     Nam DoanhThu_TyVND LoiNhuanSauThue_TyVND TongTaiSan_TyVND NoPhaiTra_TyVND
## 1  2014       73393.40              14122.68         53791.41        16112.06
## 2  2015       64300.20                298.43         56714.61        13825.54
## 3  2016       59076.19                152.26         56753.85        15910.01
## 4  2017       64522.44                252.93         61889.34        18617.83
## 5  2018       75611.55                254.60         62614.42        15747.30
## 6  2019       75005.30                183.40           621.79        12564.26
## 7  2020       64134.97               7854.96         63208.40        13708.72
## 8  2021       78992.16               8672.97         78768.70        26575.34
## 9  2022      100723.55              14798.32         82662.65        21489.09
## 10 2023       89953.91              11606.03         87754.46        22455.84
## 11 2024      103564.13              10398.73         81854.88        20283.89
##    VonChuSoHuu_TyVND Gia_DongCua_CuoiNam ROE_Nam ROA_Nam TySoNo_Tren_VCSH
## 1           37679.35             34154.5   37.48   26.25             0.43
## 2           42889.06             18128.8    0.70    0.53             0.32
## 3           40843.85             33089.0    0.37    0.27             0.39
## 4           43271.51             56311.2    0.58    0.41             0.43
## 5           46867.13             52231.7    0.54    0.41             0.34
## 6           49614.53             58209.9    0.37   29.50             0.25
## 7           49499.68             56436.3   15.87   12.43             0.28
## 8           52192.73             64672.3   16.62   11.01             0.51
## 9           61173.56             70096.3   24.19   17.90             0.35
## 10          65298.62             64830.3   17.77   13.23             0.34
## 11          61571.00             64160.1   16.89   12.70             0.33
##    DoanhThu_TangTruong_YoY LoiNhuan_TangTruong_YoY
## 1                     0.00                    0.00
## 2                   -12.39                  -97.89
## 3                    -8.12                  -48.98
## 4                     9.22                   66.12
## 5                    17.19                    0.66
## 6                    -0.80                  -27.96
## 7                   -14.49                 4182.89
## 8                    23.17                   10.41
## 9                    27.51                   70.63
## 10                  -10.69                  -21.57
## 11                   15.13                  -10.40
# Thao tác 4: Trích xuất các giá trị thống kê chính
print("--- Thao tác 4: Trích xuất các giá trị chính ---")
## [1] "--- Thao tác 4: Trích xuất các giá trị chính ---"
# Tính toán và lưu các giá trị thống kê
mean_lnst_ty <- mean(GAS_data_final$LoiNhuanSauThue) / 1e9
median_lnst_ty <- median(GAS_data_final$LoiNhuanSauThue) / 1e9
mean_roe <- mean(GAS_data_final$ROE_Nam)
median_roe <- median(GAS_data_final$ROE_Nam)
mean_growth_ln <- mean(GAS_data_final$LoiNhuan_TangTruong_YoY)
median_growth_ln <- median(GAS_data_final$LoiNhuan_TangTruong_YoY)
mean_dt_ty <- mean(GAS_data_final$DoanhThu) / 1e9

# In ra
print(paste("Doanh thu trung bình (Mean):", round(mean_dt_ty, 2), "tỷ VND"))
## [1] "Doanh thu trung bình (Mean): 77207.07 tỷ VND"
print(paste("Lợi nhuận trung bình (Mean):", round(mean_lnst_ty, 2), "tỷ VND"))
## [1] "Lợi nhuận trung bình (Mean): 6235.94 tỷ VND"
print(paste("Lợi nhuận trung vị (Median):", round(median_lnst_ty, 2), "tỷ VND"))
## [1] "Lợi nhuận trung vị (Median): 7854.96 tỷ VND"
print(paste("ROE trung bình (Mean):", round(mean_roe, 2), "%"))
## [1] "ROE trung bình (Mean): 11.94 %"
print(paste("ROE trung vị (Median):", round(median_roe, 2), "%"))
## [1] "ROE trung vị (Median): 15.87 %"
print(paste("Tăng trưởng LN trung bình (Mean):", round(mean_growth_ln, 2), "%"))
## [1] "Tăng trưởng LN trung bình (Mean): 374.9 %"
print(paste("Tăng trưởng LN trung vị (Median):", round(median_growth_ln, 2), "%"))
## [1] "Tăng trưởng LN trung vị (Median): 0 %"
  • Kết quả từ str() xác nhận tất cả 12 biến đã được mã hóa chính xác, đảm bảo tính toàn vẹn dữ liệu cho các phân tích sau. Các biến tài chính gốc (ví dụ: DoanhThu) và các biến phái sinh (ví dụ: ROE_Nam) đều ở định dạng số (numeric) hoặc số nguyên (integer).

  • summary(), cung cấp cái nhìn tổng quan về phân phối của dữ liệu trong giai đoạn 11 năm (2014-2024). Từ kết quả Thao tác 4, Doanh thu trung bình đạt 77,207.07 tỷ VND, trong khi lợi nhuận sau thuế trung bình đạt 6,235.94 tỷ VND.

  • Một quan sát quan trọng là sự chênh lệch giữa giá trị trung bình (Mean) và trung vị (Median) ở nhiều chỉ số. Cụ thể:

    • Lợi nhuận sau thuế: Có Trung vị (7,854.96 tỷ VND) cao hơn đáng kể so với Trung bình (6,235.94 tỷ VND).

    • ROE (Tỷ suất sinh lời/VCSH): Có Trung vị (15.87%) cao hơn Trung bình (11.94%).

Cả hai hiện tượng này đều cho thấy phân phối của dữ liệu bị lệch trái. Về mặt tài chính, điều này ngụ ý rằng có một số năm hoạt động với lợi nhuận và hiệu quả sinh lời thấp bất thường (như kết quả Min. và 1st Qu. rất thấp trong bảng summary()) đã kéo giá trị trung bình chung (Mean) đi xuống. Do đó, giá trị Trung vị (Median) có thể đại diện tốt hơn cho hiệu quả hoạt động “điển hình” của GAS trong giai đoạn này.

Ngược lại, biến LoiNhuan_TangTruong_YoY (Tăng trưởng Lợi nhuận) thể hiện độ lệch cực lớn về bên phải. Kết quả cho thấy giá trị Trung bình (374.90%) cao hơn rất nhiều so với Trung vị (0%). Nguyên nhân là do sự xuất hiện của ít nhất một giá trị ngoại lai rất lớn (Max: 4182.89% từ summary()). Trong trường hợp này, Mean hoàn toàn không có ý nghĩa đại diện; Median (0%) là thước đo xu hướng trung tâm đáng tin cậy hơn, cho thấy một năm “điển hình” của GAS có mức tăng trưởng lợi nhuận không quá đột biến.

  • Tạo bảng GAS_data_display giúp chuẩn hóa các đơn vị tài chính lớn sang Tỷ VND, làm cho kết quả dễ đọc và dễ trình bày hơn, như được hiển thị trong bảng kết quả đã làm tròn.

2.4.2. Phân phối & Tần suất

# Thao tác 5: Phân tích phân vị (Quantiles) cho ROE
print("--- Thao tác 5: Phân vị của ROE (%) ---")
## [1] "--- Thao tác 5: Phân vị của ROE (%) ---"
q_roe <- quantile(GAS_data_final$ROE_Nam, probs = c(0, .25, .5, .75, 1))
print(round(q_roe, 2))
##    0%   25%   50%   75%  100% 
##  0.37  0.56 15.87 17.33 37.48
# Thao tác 6: Phân tích phân vị cho Tăng trưởng Lợi nhuận
print("--- Thao tác 6: Phân vị của Tăng trưởng Lợi nhuận (%) ---")
## [1] "--- Thao tác 6: Phân vị của Tăng trưởng Lợi nhuận (%) ---"
# Tạo một vector mới bỏ qua năm 2014 (giá trị 0) để phân tích
growth_ln_subset <- GAS_data_final$LoiNhuan_TangTruong_YoY[GAS_data_final$Nam > 2014]
q_growth <- quantile(growth_ln_subset, probs = c(0, .25, .5, .75, 1))
print(round(q_growth, 2))
##      0%     25%     50%     75%    100% 
##  -97.89  -26.37   -4.87   52.19 4182.89
# Thao tác 7: Thống kê Tần suất cho Tăng trưởng LN
print("--- Thao tác 7: Tần suất Tăng trưởng Lợi nhuận ---")
## [1] "--- Thao tác 7: Tần suất Tăng trưởng Lợi nhuận ---"
# table() dùng để đếm số lần xuất hiện của mỗi nhóm
freq_growth <- table(GAS_data_final$LoiNhuan_TangTruong_YoY > 0)
names(freq_growth) <- c("Tăng trưởng Âm hoặc Bằng 0", "Tăng trưởng Dương")
print(freq_growth)
## Tăng trưởng Âm hoặc Bằng 0          Tăng trưởng Dương 
##                          6                          5
# Thao tác 8: Thống kê Tần suất cho ROE
print("--- Thao tác 8: Tần suất ROE > 15% (Ngưỡng hiệu quả) ---")
## [1] "--- Thao tác 8: Tần suất ROE > 15% (Ngưỡng hiệu quả) ---"
# Sử dụng ngưỡng 15% (gần median) thay vì 20%
# sum() của một biểu thức logic sẽ đếm số lần TRUE
roe_tren_15 <- sum(GAS_data_final$ROE_Nam > 15)
print(paste("Số năm có ROE > 15%:", roe_tren_15, "năm"))
## [1] "Số năm có ROE > 15%: 6 năm"
# Thao tác 9: Biểu đồ thống kê đơn giản (Boxplot)
print("--- Thao tác 9: Biểu đồ Boxplot ---")
## [1] "--- Thao tác 9: Biểu đồ Boxplot ---"
par(mfrow = c(1, 2)) # Chia cửa sổ đồ thị thành 1 hàng 2 cột

boxplot(GAS_data_final$ROE_Nam, 
        main = "Boxplot Phân phối ROE (2014-2024)",
        ylab = "ROE (%)")

# Thao tác 10: Biểu đồ thống kê đơn giản (Histogram)
print("--- Thao tác 10: Biểu đồ Histogram ---")
## [1] "--- Thao tác 10: Biểu đồ Histogram ---"
hist(growth_ln_subset, 
     main = "Histogram Tăng trưởng LN (2015-2024)",
     xlab = "Tăng trưởng Lợi nhuận (%)",
     ylab = "Tần suất",
     breaks = 10) # 'breaks' gợi ý số lượng cột

par(mfrow = c(1, 1)) # Reset lại cửa sổ đồ thị
  • Phân tích phân vị (Thao tác 5 & 6):

    • Kết quả phân vị của ROE (q_roe, Thao tác 5) cho thấy một sự phân hóa rất rõ rệt: 25% số năm tệ nhất (từ 0% đến 25%) có ROE cực kỳ thấp, chỉ từ 0.37% đến 0.56%. Ngược lại, 50% số năm tốt nhất (từ 50%) có ROE từ 15.87% trở lên. Điều này xác nhận nhận định ở Mục 2.4.1: Dữ liệu bị lệch trái (left-skewed) do một số năm hoạt động kém hiệu quả (2015, 2016, 2017) kéo trung bình chung đi xuống.

    • Đối với tăng trưởng lợi nhuận (q_growth, Thao tác 6, đã loại bỏ năm 2014), phân phối cũng cho thấy sự bất ổn định lớn: Mức trung vị (Median) là -4.87%, cho thấy một năm “điển hình” (trong 10 năm qua) có sụt giảm lợi nhuận nhẹ. Khoảng biến động là rất lớn, 25% số năm tệ nhất sụt giảm từ -97.89% (Min) đến -26.37% (Q1). Ngược lại, 25% số năm tốt nhất tăng trưởng từ 52.19% (Q3) đến 4182.89% (Max).

  • Phân tích tần suất (Thao tác 7 & 8):

Thống kê tần suất tăng trưởng (freq_growth, Thao tác 7) chỉ ra sự thiếu ổn định: trong 11 năm, số năm “Tăng trưởng Âm hoặc Bằng 0” (6 năm) nhiều hơn số năm “Tăng trưởng Dương” (5 năm). Điều này củng cố cho nhận định rằng tăng trưởng lợi nhuận của GAS không bền vững qua các năm.

Tuy nhiên, thống kê về ROE (roe_tren_15, Thao tác 8) lại cho thấy một điểm sáng: có 6 trên 11 năm (chiếm đa số) đạt mức ROE trên 15%. Đây là một con số tương đối tích cực, cho thấy dù có những năm sụt giảm mạnh, GAS vẫn thường xuyên duy trì được mức sinh lời tốt trên vốn chủ sở hữu.

  • Phân tích biểu đồ (Thao tác 9 & 10):

    • Biểu đồ Boxplot (ROE): Hình ảnh trực quan hóa chính xác kết quả q_roe. Ta thấy phần “hộp” (IQR, từ Q1 đến Q3) bị dồn về phía dưới. Khoảng cách từ Q1 (0.56%) đến Median (15.87%) là rất lớn, trong khi khoảng cách từ Median (15.87%) đến Q3 (17.33%) lại rất hẹp. Điều này khẳng định sự phân phối lệch trái (lệch về phía giá trị thấp).

    • Biểu đồ Histogram (Tăng trưởng LN): Hình ảnh này cho thấy rõ sự lệch phải cực đoan. Hầu hết các giá trị (9/10 năm) tập trung thành hai cột ở gần 0 (trong khoảng -100% đến 1000%). Có duy nhất 1 giá trị (1 năm) nằm tách biệt hoàn toàn ở phía xa bên phải (cột > 3000%). Đây chính là giá trị ngoại lai 4182.89% (Max) đã làm sai lệch Mean (trung bình) của tăng trưởng lợi nhuận như đã phân tích ở mục 2.4.1.

2.4.3. Phân tích quy mô và hiệu quả cốt lõi

# Thao tác 11: Phân tích quy mô (Min/Max)
# (Các giá trị Mean đã được tính ở 2.4.1)
print("--- Thao tác 11: Phân tích quy mô (Min/Max) ---")
## [1] "--- Thao tác 11: Phân tích quy mô (Min/Max) ---"
# Tính toán Tổng tài sản trung bình
tts_mean_ty <- mean(GAS_data_final$TongTaiSan) / 1e9
print(paste("Tổng tài sản trung bình (11 năm):", round(tts_mean_ty, 2), "tỷ VND"))
## [1] "Tổng tài sản trung bình (11 năm): 62421.32 tỷ VND"
# Xác định năm Lợi nhuận cao nhất (Max)
ln_max <- GAS_data_final %>% filter(LoiNhuanSauThue == max(LoiNhuanSauThue))
print(paste("Năm lợi nhuận cao nhất:", ln_max$Nam, 
            "| LNST:", round(ln_max$LoiNhuanSauThue / 1e9, 2), "tỷ VND"))
## [1] "Năm lợi nhuận cao nhất: 2022 | LNST: 14798.32 tỷ VND"
# Xác định năm Lợi nhuận thấp nhất (Min)
ln_min <- GAS_data_final %>% filter(LoiNhuanSauThue == min(LoiNhuanSauThue))
print(paste("Năm lợi nhuận thấp nhất:", ln_min$Nam, 
            "| LNST:", round(ln_min$LoiNhuanSauThue / 1e9, 2), "tỷ VND"))
## [1] "Năm lợi nhuận thấp nhất: 2016 | LNST: 152.26 tỷ VND"
# Thao tác 12: Phân tích Cơ cấu tài chính (Đòn bẩy)
print("--- Thao tác 12: Phân tích Cơ cấu tài chính ---")
## [1] "--- Thao tác 12: Phân tích Cơ cấu tài chính ---"
# Tính tỷ lệ Nợ trên Tổng Tài sản
gas_co_cau_von <- GAS_data_final %>% 
  mutate(TyLeNo_TTS = NoPhaiTra / TongTaiSan)

# Tính trung bình của tỷ lệ này (đã có TySoNo_Tren_VCSH, đây là chỉ số khác)
co_cau_no_tb <- mean(gas_co_cau_von$TyLeNo_TTS)
print(paste("Tỷ lệ Nợ / Tổng Tài sản trung bình:", round(co_cau_no_tb * 100, 2), "%"))
## [1] "Tỷ lệ Nợ / Tổng Tài sản trung bình: 208.19 %"
print(paste("Tỷ số Nợ / VCSH trung bình (từ 1.4.1):", round(mean(GAS_data_final$TySoNo_Tren_VCSH), 2)))
## [1] "Tỷ số Nợ / VCSH trung bình (từ 1.4.1): 0.36"
# Thao tác 13: Phân tích Hiệu quả sinh lời (Biên Lợi nhuận)
print("--- Thao tác 13: Phân tích Biên Lợi nhuận ròng ---")
## [1] "--- Thao tác 13: Phân tích Biên Lợi nhuận ròng ---"
gas_bien_ln <- GAS_data_final %>% 
  mutate(Bien_LN_Rong = LoiNhuanSauThue / DoanhThu)

bien_ln_tb <- mean(gas_bien_ln$Bien_LN_Rong)
bien_ln_median <- median(gas_bien_ln$Bien_LN_Rong)
print(paste("Biên lợi nhuận ròng trung bình (Mean):", round(bien_ln_tb * 100, 2), "%"))
## [1] "Biên lợi nhuận ròng trung bình (Mean): 7.44 %"
print(paste("Biên lợi nhuận ròng trung vị (Median):", round(bien_ln_median * 100, 2), "%"))
## [1] "Biên lợi nhuận ròng trung vị (Median): 10.04 %"

Nhận xét

  • Quy mô và biến động (Thao tác 11): Quy mô của GAS rất lớn, với Tổng tài sản trung bình là 62,421.32 tỷ VND. Tuy nhiên, kết quả kinh doanh thể hiện sự biến động mạnh, phản ánh rủi ro ngành cụ thể:

    • Năm đỉnh cao lợi nhuận là 2022, đạt 14,798.32 tỷ VND.

    • Năm khó khăn nhất là 2016, khi lợi nhuận chỉ đạt 152.26 tỷ VND.

Sự chênh lệch cực lớn (chênh lệch hàng trăm lần) cho thấy lợi nhuận của GAS chịu ảnh hưởng rất mạnh mẽ từ các yếu tố bên ngoài (như giá dầu, giá khí thế giới).

  • Cơ cấu tài chính (Thao tác 12):

Phân tích cơ cấu vốn cho thấy một kết quả bất thường và đáng báo động từ dữ liệu. Tỷ lệ Nợ trên Tổng Tài sản trung bình (co_cau_no_tb) lên đến 208.19%. Về mặt lý thuyết, con số này là không thể có (vì Nợ là một phần của Tài sản). Kết quả này có thể cho rằng: Có ít nhất một điểm dữ liệu dị biệt (outlier) nghiêm trọng, nơi NoPhaiTra lớn hơn TongTaiSan rất nhiều. Điểm dị biệt này đã được phát hiện trong summary() ở Mục 2.4.1: TongTaiSan có giá trị Min là 621 tỷ, trong khi NoPhaiTra có Min là 12,564 tỷ.

Do đó, giá trị trung bình 208.19% bị chi phối hoàn toàn bởi điểm ngoại lai này và không có giá trị đại diện.

Ngược lại, chỉ số Tỷ số Nợ / VCSH trung bình (từ summary()) là 0.36, cho thấy trong các năm bình thường, cấu trúc vốn của GAS là an toàn (Nợ chỉ bằng 36% VCSH). Kết luận: Cần phải kiểm tra lại dữ liệu gốc của năm có TongTaiSan thấp bất thường trước khi đưa ra kết luận cuối cùng về đòn bẩy.

  • Hiệu quả sinh lời (Thao tác 13): Biên lợi nhuận ròng đo lường hiệu quả chuyển đổi doanh thu thành lợi nhuận. Kết quả cho thấy:

    • Biên lợi nhuận ròng trung bình (bien_ln_tb) là 7.44%.

    • Biên lợi nhuận ròng trung vị (bien_ln_median) là 10.04%.

Sự chênh lệch (Median > Mean) một lần nữa xác nhận hiện tượng lệch trái do một số năm có biên lợi nhuận rất thấp (như 2015, 2016). Tuy nhiên, con số trung vị 10.04% (bien_ln_median) cho thấy trong một năm “điển hình”, GAS vẫn duy trì được biên lợi nhuận ròng ở mức trên 10%, một con số tích cực.

2.4.4. Phân tích Tương quan & Rủi ro

# Thao tác 14: Phân tích Độ biến động (Rủi ro)
print("--- Thao tác 14: Độ biến động (Rủi ro) ---")
## [1] "--- Thao tác 14: Độ biến động (Rủi ro) ---"
# sd() là hàm tính Độ lệch chuẩn (Standard Deviation)
sd_lnst <- sd(GAS_data_final$LoiNhuanSauThue)
sd_roe <- sd(GAS_data_final$ROE_Nam)
print(paste("Độ lệch chuẩn LNST:", round(sd_lnst / 1e9, 2), "tỷ VND"))
## [1] "Độ lệch chuẩn LNST: 6088.62 tỷ VND"
print(paste("Độ lệch chuẩn ROE:", round(sd_roe, 2), "%"))
## [1] "Độ lệch chuẩn ROE: 12.45 %"
# Thao tác 15: Xử lý Outlier trước khi tính Tương quan
print("--- Thao tác 15: Xử lý Outlier trước khi tính Tương quan ---")
## [1] "--- Thao tác 15: Xử lý Outlier trước khi tính Tương quan ---"
# Dữ liệu từ 1.4.1 và 1.4.3 cho thấy 1 năm có TTS rất thấp (Min: 621 tỷ)
# Đây là outlier nghiêm trọng, gây ra Tỷ lệ Nợ/TTS > 200%
# lọc bỏ năm này để ma trận tương quan có ý nghĩa hơn.
# Ngưỡng 1,000 tỷ (1e12) được chọn để loại bỏ giá trị 621 tỷ
data_for_cor <- GAS_data_final %>% filter(TongTaiSan > 1e12) 
print(paste("Đã loại bỏ", nrow(GAS_data_final) - nrow(data_for_cor), "dòng dữ liệu outlier (TTS < 1,000 tỷ)"))
## [1] "Đã loại bỏ 1 dòng dữ liệu outlier (TTS < 1,000 tỷ)"
print(paste("Số quan sát mới để tính tương quan:", nrow(data_for_cor), "năm"))
## [1] "Số quan sát mới để tính tương quan: 10 năm"
# Thao tác 16: Ma trận Tương quan (trên dữ liệu đã lọc)
print("--- Thao tác 16: Ma trận Tương quan (đã lọc outlier) ---")
## [1] "--- Thao tác 16: Ma trận Tương quan (đã lọc outlier) ---"
# cor() là hàm tính Ma trận Tương quan (Correlation Matrix)
cor_matrix <- cor(data_for_cor %>% select(-Nam)) # Bỏ cột 'Nam'
print(round(cor_matrix, 2))
##                         DoanhThu LoiNhuanSauThue TongTaiSan NoPhaiTra
## DoanhThu                    1.00            0.70       0.85      0.61
## LoiNhuanSauThue             0.70            1.00       0.57      0.47
## TongTaiSan                  0.85            0.57       1.00      0.81
## NoPhaiTra                   0.61            0.47       0.81      1.00
## VonChuSoHuu                 0.85            0.55       0.97      0.63
## Gia_DongCua_CuoiNam         0.68            0.50       0.83      0.71
## ROE_Nam                     0.49            0.94       0.29      0.30
## ROA_Nam                     0.51            0.95       0.31      0.28
## TySoNo_Tren_VCSH           -0.11            0.05      -0.01      0.58
## DoanhThu_TangTruong_YoY     0.58            0.25       0.43      0.60
## LoiNhuan_TangTruong_YoY    -0.28            0.07      -0.14     -0.38
##                         VonChuSoHuu Gia_DongCua_CuoiNam ROE_Nam ROA_Nam
## DoanhThu                       0.85                0.68    0.49    0.51
## LoiNhuanSauThue                0.55                0.50    0.94    0.95
## TongTaiSan                     0.97                0.83    0.29    0.31
## NoPhaiTra                      0.63                0.71    0.30    0.28
## VonChuSoHuu                    1.00                0.78    0.25    0.29
## Gia_DongCua_CuoiNam            0.78                1.00    0.28    0.30
## ROE_Nam                        0.25                0.28    1.00    1.00
## ROA_Nam                        0.29                0.30    1.00    1.00
## TySoNo_Tren_VCSH              -0.27                0.06    0.15    0.10
## DoanhThu_TangTruong_YoY        0.31                0.58    0.16    0.14
## LoiNhuan_TangTruong_YoY       -0.01                0.13    0.09    0.13
##                         TySoNo_Tren_VCSH DoanhThu_TangTruong_YoY
## DoanhThu                           -0.11                    0.58
## LoiNhuanSauThue                     0.05                    0.25
## TongTaiSan                         -0.01                    0.43
## NoPhaiTra                           0.58                    0.60
## VonChuSoHuu                        -0.27                    0.31
## Gia_DongCua_CuoiNam                 0.06                    0.58
## ROE_Nam                             0.15                    0.16
## ROA_Nam                             0.10                    0.14
## TySoNo_Tren_VCSH                    1.00                    0.42
## DoanhThu_TangTruong_YoY             0.42                    1.00
## LoiNhuan_TangTruong_YoY            -0.48                   -0.40
##                         LoiNhuan_TangTruong_YoY
## DoanhThu                                  -0.28
## LoiNhuanSauThue                            0.07
## TongTaiSan                                -0.14
## NoPhaiTra                                 -0.38
## VonChuSoHuu                               -0.01
## Gia_DongCua_CuoiNam                        0.13
## ROE_Nam                                    0.09
## ROA_Nam                                    0.13
## TySoNo_Tren_VCSH                          -0.48
## DoanhThu_TangTruong_YoY                   -0.40
## LoiNhuan_TangTruong_YoY                    1.00
# Thao tác 17: Trực quan hóa Ma trận Tương quan
print("--- Thao tác 17: Trực quan hóa Ma trận Tương quan ---")
## [1] "--- Thao tác 17: Trực quan hóa Ma trận Tương quan ---"
library(corrplot)
# Vẽ biểu đồ, 'method = "number"' để hiển thị con số
corrplot(cor_matrix, method = "number", 
         title = "Ma trận Tương quan (đã lọc outlier, n=10)", 
         mar = c(0,0,1,0), # Căn chỉnh lề
         tl.cex = 0.8, # Giảm kích thước font chữ
         number.cex = 0.5) # Thu nhỏ font các con số trong matix

# Thao tác 18: Tương quan chính (LNST & Giá)
print("--- Thao tác 18: Tương quan chính (LNST & Giá) ---")
## [1] "--- Thao tác 18: Tương quan chính (LNST & Giá) ---"
# Trích xuất giá trị cụ thể từ ma trận
cor_ln_gia <- cor_matrix["LoiNhuanSauThue", "Gia_DongCua_CuoiNam"]
print(paste("Tương quan (LNST, Giá):", round(cor_ln_gia, 3)))
## [1] "Tương quan (LNST, Giá): 0.495"
# Thao tác 19: Tương quan chính (ROE & Giá)
print("--- Thao tác 19: Tương quan chính (ROE & Giá) ---")
## [1] "--- Thao tác 19: Tương quan chính (ROE & Giá) ---"
cor_roe_gia <- cor_matrix["ROE_Nam", "Gia_DongCua_CuoiNam"]
print(paste("Tương quan (ROE, Giá):", round(cor_roe_gia, 3)))
## [1] "Tương quan (ROE, Giá): 0.276"

Nhận xét: đánh giá mức độ rủi ro (biến động) và mối quan hệ tuyến tính (tương quan) giữa các biến số tài chính và thị trường.

  • Phân tích rủi ro (Thao tác 14):

Kết quả cho thấy mức độ rủi ro (biến động) rất cao. Độ lệch chuẩn của Lợi nhuận sau thuế (sd_lnst) là 6,088.62 tỷ VND. Con số này gần như bằng với Lợi nhuận trung bình (mean_lnst_ty = 6,235.94 tỷ VND ở Mục 2.4.1), cho thấy Lợi nhuận của GAS biến động cực kỳ mạnh qua các năm. Tương tự, Độ lệch chuẩn của ROE (sd_roe) là 12.45%, cũng gần bằng với ROE trung bình (mean_roe = 11.94%), khẳng định sự bất ổn định rất lớn trong hiệu quả sinh lời.

  • Phân tích Tương quan (Thao tác 15-19): Ở thao tác 15 đã được thực hiện loại bỏ 1 năm quan sát bị xác định là outlier (với TongTaiSan < 1,000 tỷ) để đảm bảo kết quả tương quan đáng tin cậy. Ma trận tương quan (cor_matrix, Thao tác 16) trên 10 năm còn lại cho thấy các mối quan hệ nội tại:

    • Quan hệ nội tại (Hiệu quả): LoiNhuanSauThue có tương quan dương rất mạnh với ROE_Nam (0.94) và ROA_Nam (0.95). Điều này là hợp lý vì chúng đều là thước đo lợi nhuận.

    • Quan hệ nội tại (Quy mô): DoanhThu, TongTaiSan, và VonChuSoHuu đều có tương quan dương rất mạnh với nhau (từ 0.85 đến 0.97), cho thấy công ty tăng trưởng quy mô một cách đồng đều.

    • Quan hệ Quy mô - Lợi nhuận: DoanhThu và LoiNhuanSauThue có tương quan dương mạnh (0.70), cho thấy khi quy mô doanh thu tăng, lợi nhuận có xu hướng tăng theo.

  • Tương quan với Thị trường (Thao tác 18, 19) (trả lời câu hỏi “giá cổ phiếu có phản ánh sức khỏe tài chính không?”):

    • Tương quan giữa LoiNhuanSauThue và Gia_DongCua_CuoiNam (cor_ln_gia) là 0.495 (dương, mức độ trung bình).

    • Tương quan giữa ROE_Nam và Gia_DongCua_CuoiNam (cor_roe_gia) là 0.276 (dương, mức độ yếu).

Thị trường (Giá cổ phiếu) dường như phản ứng ở mức độ trung bình với quy mô lợi nhuận tuyệt đối (0.495), nhưng phản ứng khá yếu với hiệu quả sinh lời (0.276). Đáng chú ý hơn, Gia_DongCua_CuoiNam lại tương quan rất mạnh với TongTaiSan (0.83) và VonChuSoHuu (0.78). Điều này có thể cho rằng, trong giai đoạn 10 năm này (sau khi lọc outlier), thị trường có xu hướng định giá cổ phiếu GAS dựa trên quy mô tài sản và vốn chủ sở hữu hơn là dựa trên hiệu quả sinh lời (ROE) hay lợi nhuận (LNST) trong năm đó.

2.4.5. Định giá P/E và Chất lượng dòng tiền

# Thao tác 20: Đọc và Chuẩn hóa Dữ liệu LCTT (Sheet 3)
print("--- Thao tác 20: Đọc và Chuẩn hóa Dữ liệu LCTT ---")
## [1] "--- Thao tác 20: Đọc và Chuẩn hóa Dữ liệu LCTT ---"
# Đọc sheet 3 từ file excel
lctt_raw <- read_excel(bctc_path, sheet = 3) # Bảng Lưu chuyển tiền tệ

# Chuẩn hóa cột chỉ tiêu
if ("CHỈ TIÊU" %in% names(lctt_raw)) {
  lctt_raw <- lctt_raw %>% rename(ChiTieu = `CHỈ TIÊU`)
}
print("Đã đọc và chuẩn hóa Sheet 3 (LCTT).")
## [1] "Đã đọc và chuẩn hóa Sheet 3 (LCTT)."
# Thao tác 21: Bổ sung EPS và Tính toán SL Cổ phiếu
print("--- Thao tác 21: Bổ sung EPS và Tính toán SL Cổ phiếu ---")
## [1] "--- Thao tác 21: Bổ sung EPS và Tính toán SL Cổ phiếu ---"
# Trích xuất 1 chỉ tiêu (EPS) từ kqkd_raw (đã đọc ở Mục 1.2)
eps_raw_vec <- extract_row_data(kqkd_raw, "19. Lãi cơ bản trên cổ phiếu")

# Lấy vector LNST (đã trích xuất ở Mục 1.3)
lnst_vec_for_calc <- GAS_data_final$LoiNhuanSauThue
# Làm sạch vector EPS vừa trích xuất (dùng hàm từ Mục 1.3)
eps_vec_cleaned <- clean_numeric(eps_raw_vec)

# TÍNH TOÁN SL Cổ phiếu Lưu hành = Lợi nhuận / EPS
# round() để làm tròn về số nguyên gần nhất
slcplh_calc_vec <- round(lnst_vec_for_calc / eps_vec_cleaned)

print("Đã trích xuất EPS và TÍNH TOÁN SL Cổ phiếu.")
## [1] "Đã trích xuất EPS và TÍNH TOÁN SL Cổ phiếu."
# Thêm 2 cột này vào bảng chính
GAS_data_final <- GAS_data_final %>%
  mutate(
    EPS = eps_vec_cleaned, # Dùng vector EPS đã làm sạch
    SL_CoPhieu_LuuHanh = slcplh_calc_vec # Dùng vector SL Cổ phiếu vừa tính toán
  )

# Thao tác 22: Tính toán P/E và Vốn hóa
print("--- Thao tác 22: Tính toán P/E và Vốn hóa ---")
## [1] "--- Thao tác 22: Tính toán P/E và Vốn hóa ---"
GAS_data_final <- GAS_data_final %>%
  mutate(
    # Tính toán Vốn hóa (đơn vị: Tỷ VND)
    VonHoa_TyVND = (Gia_DongCua_CuoiNam * SL_CoPhieu_LuuHanh) / 1e9,
    # Tính toán P/E
    P_E_CuoiNam = Gia_DongCua_CuoiNam / EPS
  )

# Xử lý P/E (Nếu EPS = 0, P/E sẽ là Inf - Vô cực)
GAS_data_final <- GAS_data_final %>%
  mutate(
    P_E_CuoiNam = ifelse(is.infinite(P_E_CuoiNam), NA, P_E_CuoiNam)
  )

# Thống kê P/E (loại bỏ NA nếu có)
pe_mean <- mean(GAS_data_final$P_E_CuoiNam, na.rm = TRUE)
pe_median <- median(GAS_data_final$P_E_CuoiNam, na.rm = TRUE)
print(paste("P/E trung bình (Mean, 11 năm):", round(pe_mean, 2)))
## [1] "P/E trung bình (Mean, 11 năm): 9.93"
print(paste("P/E trung vị (Median, 11 năm):", round(pe_median, 2)))
## [1] "P/E trung vị (Median, 11 năm): 9.48"
# Thao tác 23: Tính toán Biên Lợi nhuận ròng
print("--- Thao tác 23: Tính toán Biên Lợi nhuận ròng ---")
## [1] "--- Thao tác 23: Tính toán Biên Lợi nhuận ròng ---"
GAS_data_final <- GAS_data_final %>%
  mutate(
    BienLoiNhuanRong_Nam = (LoiNhuanSauThue / DoanhThu) * 100 # Đơn vị %
  )
# Thống kê Biên LN Ròng (đã có kết quả từ 1.4.3, nhưng tính lại để xác nhận)
bln_mean <- mean(GAS_data_final$BienLoiNhuanRong_Nam, na.rm = TRUE)
print(paste("Biên Lợi nhuận ròng trung bình (Mean):", round(bln_mean, 2), "%"))
## [1] "Biên Lợi nhuận ròng trung bình (Mean): 7.44 %"
# Thao tác 24: Phân tích Chất lượng Lợi nhuận (Dòng tiền)
print("--- Thao tác 24: Phân tích Chất lượng Lợi nhuận (Dòng tiền) ---")
## [1] "--- Thao tác 24: Phân tích Chất lượng Lợi nhuận (Dòng tiền) ---"
# Trích xuất Dòng tiền từ HĐKD (CFO) từ lctt_raw
cfo_raw_vec <- extract_row_data(lctt_raw, "Lưu chuyển tiền thuần từ hoạt động kinh doanh")
# Làm sạch dữ liệu CFO
cfo_vec_cleaned <- clean_numeric(cfo_raw_vec)

# Thêm CFO vào bảng chính
GAS_data_final <- GAS_data_final %>%
  mutate(CFO = cfo_vec_cleaned)

# Tính toán Tỷ lệ Chuyển đổi Tiền mặt
GAS_data_final <- GAS_data_final %>%
  mutate(
    TyLe_CFO_Tren_LNST = CFO / LoiNhuanSauThue
  )

# Thống kê Tỷ lệ Chuyển đổi
cash_conv_mean <- mean(GAS_data_final$TyLe_CFO_Tren_LNST, na.rm = TRUE)
cash_conv_median <- median(GAS_data_final$TyLe_CFO_Tren_LNST, na.rm = TRUE)
print(paste("Tỷ lệ CFO/LNST trung bình (Mean):", round(cash_conv_mean, 2)))
## [1] "Tỷ lệ CFO/LNST trung bình (Mean): 22.16"
print(paste("Tỷ lệ CFO/LNST trung vị (Median):", round(cash_conv_median, 2)))
## [1] "Tỷ lệ CFO/LNST trung vị (Median): 1.19"
print("Bảng dữ liệu GAS_data_final đã được cập nhật (19 biến).")
## [1] "Bảng dữ liệu GAS_data_final đã được cập nhật (19 biến)."
print(head(as.data.frame(GAS_data_final)))
##    Nam       DoanhThu LoiNhuanSauThue     TongTaiSan      NoPhaiTra
## 1 2014 73393403034088  14122675507937 53791407348105 16112058787504
## 2 2015 64300204038285    298430505873 56714606287288 13825543405185
## 3 2016 59076193175661    152256595845 56753853518438 15910005640211
## 4 2017 64522440976234    252928652205 61889343342437 18617834577626
## 5 2018 75611546239412    254596584934 62614420245293 15747295132679
## 6 2019 75005297175406    183403281712   621787389634 12564256032003
##      VonChuSoHuu Gia_DongCua_CuoiNam    ROE_Nam    ROA_Nam TySoNo_Tren_VCSH
## 1 37679348560601             34154.5 37.4812093 26.2545195        0.4276098
## 2 42889062882103             18128.8  0.6958196  0.5261969        0.3223559
## 3 40843847878227             33089.0  0.3727773  0.2682753        0.3895325
## 4 43271508764811             56311.2  0.5845154  0.4086788        0.4302562
## 5 46867125112614             52231.7  0.5432306  0.4066101        0.3359987
## 6 49614531357631             58209.9  0.3696564 29.4961404        0.2532374
##   DoanhThu_TangTruong_YoY LoiNhuan_TangTruong_YoY  EPS SL_CoPhieu_LuuHanh
## 1               0.0000000               0.0000000 7140         1977965757
## 2             -12.3896680             -97.8868699 4400           67825115
## 3              -8.1244079             -48.9808874 6748           22563218
## 4               9.2190229              66.1199968 4994           50646506
## 5              17.1864317               0.6594479 5911           43071660
## 6              -0.8017943             -27.9631807 6142           29860515
##   VonHoa_TyVND P_E_CuoiNam BienLoiNhuanRong_Nam            CFO
## 1   67556.4314    4.783543           19.2424318 16701449198611
## 2    1229.5879    4.120182            0.4641206  9126872112300
## 3     746.5943    4.903527            0.2577292  4942224182550
## 4    2851.9655   11.275771            0.3920011 14385549919558
## 5    2249.7060    8.836356            0.3367165 12421887654437
## 6    1738.1776    9.477353            0.2445204 12680818093290
##   TyLe_CFO_Tren_LNST
## 1           1.182598
## 2          30.582906
## 3          32.459836
## 4          56.875921
## 5          48.790472
## 6          69.141719

Nhận xét

Mục này hoàn thiện bộ dữ liệu bằng cách bổ sung các chỉ tiêu từ Bảng KQKD (phụ lục) và Bảng LCTT, cho phép phân tích về định giá thị trường và chất lượng lợi nhuận.

  • Phân tích Định giá P/E (Thao tác 21-22):

    • Bằng cách trích xuất EPS (eps_raw_vec) và sử dụng LoiNhuanSauThue (đã có), bộ dữ liệu đã tự động tính toán ra SL_CoPhieu_LuuHanh (slcplh_calc_vec).

    • Từ đó, chỉ số P/E (P_E_CuoiNam) và Vốn hóa (VonHoa_TyVND) được tính toán. Kết quả thống kê cho thấy P/E trung bình (pe_mean) là 9.93 và P/E trung vị (pe_median) là 9.48.

    • Hai chỉ số này rất gần nhau, cho thấy P/E của GAS trong 11 năm qua tương đối ổn định và không có các giá trị ngoại lai (outlier) quá lớn. Mức P/E trung bình ~9.5-10 là một mức định giá tương đối hợp lý, cho thấy thị trường định giá GAS ở mức ổn định, không quá đắt cũng không quá rẻ.

  • Phân tích Chất lượng dòng tiền (Thao tác 24): Thao tác này đã đọc Bảng LCTT (Sheet 3) và tính Tỷ lệ Chuyển đổi Tiền mặt (TyLe_CFO_Tren_LNST).

    • Kết quả cho thấy Tỷ lệ trung bình (cash_conv_mean) là 22.16, trong khi Tỷ lệ trung vị (cash_conv_median) chỉ là 1.19.

    • Sự chênh lệch cực kỳ lớn này cho thấy điều tương tự như đã thấy với LoiNhuan_TangTruong_YoY: Tồn tại ít nhất một năm ngoại lai (outlier) với Tỷ lệ CFO/LNST rất cao (ví dụ, LNST rất thấp nhưng CFO rất cao), làm cho giá trị Mean (22.16) trở nên vô nghĩa và không đại diện cho hoạt động kinh doanh thông thường.

    • Ngược lại, Tỷ lệ trung vị (cash_conv_median) là 1.19 là một con số đáng tin cậy và rất tích cực. Nó có nghĩa là: trong một năm kinh doanh điển hình, cứ mỗi 1 đồng Lợi nhuận sau thuế GAS ghi nhận trên sổ sách, họ thực sự tạo ra được 1.19 đồng tiền mặt. Tỷ lệ > 1 cho thấy chất lượng lợi nhuận của GAS là rất cao, lợi nhuận được chuyển đổi thành tiền thật một cách hiệu quả.

2.5 TRỰC QUAN HÓA DỮ LIỆU

# 1. Tải các thư viện trực quan hóa
library(ggplot2) # Nền tảng xây dựng biểu đồ
library(plotly)  # Giúp biểu đồ có tính tương tác (động)
library(tidyr)   # Dùng để biến đổi dữ liệu (cho biểu đồ xếp chồng)

2.5.1. Phân tích động lực Tăng trưởng và Quy mô (2014-2024)

Giới thiệu

Nhóm biểu đồ này trực quan hóa các chỉ số cơ bản nhất về quy mô (Doanh thu, Lợi nhuận, Tài sản) và tốc độ tăng trưởng của chúng.

  • Phân tích Doanh thu (DT) & Lợi nhuận (LN):

    • Từ Mục 2.4.1, ta biết mean_dt_ty là 77,207 tỷ và mean_lnst_ty là 6,236 tỷ. Hai biến này có quy mô quá chênh lệch, do đó Biểu đồ 1 bắt buộc phải sử dụng 2 trục Y (dual-axis) để so sánh xu hướng của chúng.

    • Ta cũng biết tương quan giữa chúng là 0.70 (Mục 2.4.4, đã lọc outlier), vì vậy chúng ta kỳ vọng hai đường này sẽ di chuyển tương đối cùng chiều.

  • Phân tích Tăng trưởng (Growth):

    • DoanhThu_TangTruong_YoY (Biên độ: -14.5% đến 27.5%) và LoiNhuan_TangTruong_YoY (Biên độ: -97.9% đến 4182.9%) cho thấy sự bất ổn (Mục 2.4.1).

    • Biểu đồ 2 & 3 sẽ dùng biểu đồ cột (bar chart) với 2 màu (Âm/Dương) để làm rõ sự biến động này. Đặc biệt, Biểu đồ 3 sẽ phải xử lý outlier 4182.9% (năm 2017) để các năm khác có thể được nhìn thấy.

  • Phân tích Cấu trúc Vốn:

    • Biểu đồ 4 & 5 sẽ trực quan hóa TongTaiSan, NoPhaiTra, và VonChuSoHuu.

    • Từ Mục 2.4.3, đã xác nhận 1 năm outlier (có TongTaiSan chỉ 621.79 tỷ, trong khi mean_tts_ty là 62,421 tỷ). Do đó, bắt buộc phải lọc bỏ outlier này (TongTaiSan < 1e12) khi vẽ, nếu không toàn bộ biểu đồ quy mô Bảng Cân Đối Kế Toán sẽ vô nghĩa.

Trực quan hóa và nhận xét:

1. Biểu đồ đường: Xu hướng Doanh thu vs. Lợi nhuận (2 Trục Y)

# 1. Chuẩn bị dữ liệu: Chuyển sang Tỷ VND
p1_data <- GAS_data_final %>%
  mutate(
    DT_Ty = DoanhThu / 1e9, # Doanh thu (Tỷ VND)
    LNST_Ty = LoiNhuanSauThue / 1e9 # Lợi nhuận (Tỷ VND)
  )

# 2. Định nghĩa trục Y thứ 2 (cho Lợi nhuận)
y2 <- list(
  overlaying = "y", # Đè trục y2 lên trục y1
  side = "right",   # Đặt ở bên phải
  title = "Lợi nhuận (Tỷ VND)", # Tiêu đề trục
  showgrid = FALSE  # Ẩn lưới
)

# 3. Vẽ biểu đồ plotly (p1)
p1 <- plot_ly(data = p1_data, x = ~Nam, 
              # Định nghĩa tooltip (hover)
              hovertemplate = paste(
                "Năm: %{x}<br>",
                "%{yaxis.title.text}: %{y:,.0f} Tỷ VND"
              )) %>%
  # Thêm đường Doanh thu (sử dụng trục y1 mặc định)
  add_lines(y = ~DT_Ty, name = "Doanh Thu (Trục trái)", yaxis = "y1") %>%
  # Thêm đường Lợi nhuận (sử dụng trục y2)
  add_lines(y = ~LNST_Ty, name = "Lợi Nhuận (Trục phải)", yaxis = "y2") %>%
  # Áp dụng layout (tiêu đề, 2 trục Y)
  layout(
    title = "Biểu đồ 1: Xu hướng Doanh thu và Lợi nhuận (2014-2024)",
    xaxis = list(title = "Năm"),
    yaxis = list(title = "Doanh thu (Tỷ VND)"),
    yaxis2 = y2, # Áp dụng trục y2
    legend = list(x = 0.1, y = -0.2, orientation = 'h') # Đặt chú thích bên dưới
  )

# 4. Hiển thị biểu đồ
p1

Nhận xét Biểu đồ 1: Xu hướng Doanh thu vs. Lợi nhuận

  • Tính bất ổn của Lợi nhuận: Đặc điểm nổi bật nhất là sự sụp đổ của Lợi nhuận (LN - đường màu cam) trong giai đoạn 2015-2017. Trong khi Doanh thu (DT - đường màu xanh) chỉ giảm nhẹ từ ~74k tỷ (2014) xuống đáy ~59k tỷ (2016), thì Lợi nhuận đã rơi tự do từ đỉnh ~14k tỷ (2014) xuống gần như bằng 0 trong suốt 3 năm 2015, 2016, 2017.

  • Giai đoạn phục hồi: Giai đoạn 2017-2019, DT phục hồi về mốc ~75k tỷ, nhưng LN vẫn giảm nhẹ.

  • Đỉnh 2022: Giai đoạn 2020-2022 chứng kiến sự tăng trưởng bùng nổ, cả DT và LN đều đạt đỉnh lịch sử. DT đạt ~100k tỷ và LN đạt ~14.8k tỷ.

  • Kết luận: Biểu đồ này khẳng định LN của GAS có tính chu kỳ và rủi ro cao, biến động mạnh hơn rất nhiều so với Doanh thu, cho thấy sự nhạy cảm lớn với các yếu tố bên ngoài (như giá dầu thế giới).

2. & 3. Biểu đồ Cột: Tăng trưởng Doanh thu và Lợi nhuận (% YoY)

# 1. Chuẩn bị dữ liệu: Thêm cột 'color' (màu sắc)
p2_p3_data <- GAS_data_final %>%
  mutate(
    # Tạo biến phân loại cho màu sắc
    color_dt = ifelse(DoanhThu_TangTruong_YoY > 0, "Tăng", "Giảm"),
    color_ln = ifelse(LoiNhuan_TangTruong_YoY > 0, "Tăng", "Giảm")
  )

# 2. Định nghĩa màu
colors_growth <- c("Tăng" = "#1f77b4", "Giảm" = "#d62728") # Xanh / Đỏ

# 3. Vẽ Biểu đồ 2: Tăng trưởng Doanh thu (p2)
p2 <- plot_ly(data = p2_p3_data, x = ~Nam, y = ~DoanhThu_TangTruong_YoY,
              color = ~color_dt, # Tô màu theo biến color_dt
              colors = colors_growth, # Áp dụng màu Xanh/Đỏ
              type = "bar",
              hovertemplate = paste(
                "Năm: %{x}<br>",
                "Tăng trưởng DT: %{y:.2f}%"
              )) %>%
  layout(
    title = "Biểu đồ 2: Tăng trưởng Doanh thu (% YoY) (2014-2024)",
    xaxis = list(title = "Năm"),
    yaxis = list(title = "% Tăng trưởng")
  )

# 4. Vẽ Biểu đồ 3: Tăng trưởng Lợi nhuận (p3)
# LỌC BỎ OUTLIER (4182.9%) để biểu đồ có ý nghĩa
p3_data_filtered <- p2_p3_data %>% 
  filter(LoiNhuan_TangTruong_YoY < 4000) # Lọc bỏ năm 2017

p3 <- plot_ly(data = p3_data_filtered, x = ~Nam, y = ~LoiNhuan_TangTruong_YoY,
              color = ~color_ln, # Tô màu theo biến color_ln
              colors = colors_growth, # Áp dụng màu Xanh/Đỏ
              type = "bar",
              hovertemplate = paste(
                "Năm: %{x}<br>",
                "Tăng trưởng LN: %{y:.2f}%"
              )) %>%
  layout(
    title = "Biểu đồ 3: Tăng trưởng Lợi nhuận (% YoY) (Đã lọc outlier 2017)",
    xaxis = list(title = "Năm"),
    yaxis = list(title = "% Tăng trưởng")
  )

# 5. Hiển thị biểu đồ
p2
p3

Nhận xét Biểu đồ 2: Tăng trưởng Doanh thu (% YoY)

Biểu đồ cột (tô màu ĐỎ/XANH) làm rõ hơn tính chu kỳ của Doanh thu:

  • Các chu kỳ giảm: Giai đoạn 2015-2016 (cột đỏ) cho thấy sụt giảm liên tiếp. Tuy nhiên, đợt sụt giảm mạnh và sâu nhất về doanh thu là năm 2020 (đáy ~ -14.5%), trùng khớp với thời điểm đại dịch COVID-19 làm ngưng trệ các hoạt động kinh tế.

  • Các chu kỳ tăng: Giai đoạn phục hồi mạnh nhất là 2021-2022, với đỉnh tăng trưởng vào năm 2022 (đạt ~ +27.5%).

  • Kết luận: Tăng trưởng doanh thu của GAS không ổn định mà đi theo chu kỳ rõ rệt, với 5 năm tăng trưởng âm (màu đỏ) và 6 năm tăng trưởng dương (màu xanh, tính cả năm 2014 là 0).

Nhận xét Biểu đồ 3: Tăng trưởng Lợi nhuận (% YoY)

(Lưu ý: Biểu đồ này đã lọc bỏ 1 năm outlier có tăng trưởng > 4000% để làm rõ các biến động còn lại).

  • Biến động khốc liệt: Biểu đồ này cho thấy sự biến động còn dữ dội hơn nhiều so với Doanh thu. Giai đoạn khủng hoảng 2015-2016 được thể hiện rõ: Lợi nhuận sụt giảm gần như toàn bộ vào năm 2015 (đáy ~ -98%) và tiếp tục giảm sâu vào năm 2016 (~ -49%).

  • Phục hồi mạnh: Các năm phục hồi lợi nhuận mạnh nhất (sau khi lọc outlier) là 2018 (tăng ~ +66%) và 2022 (tăng ~ +70%).

  • Kết luận: Biểu đồ này tái khẳng định kết luận từ Mục 2.4.1 và Biểu đồ 1: Lợi nhuận của GAS cực kỳ bất ổn định. Việc median_growth_ln (trung vị) bằng 0 (kết quả 2.4.1) là hoàn toàn có cơ sở, vì số năm tăng/giảm gần như bằng nhau và biên độ biến động rất lớn.

4. & 5. Biểu đồ Đường và Diện tích: Quy mô và Cơ cấu Bảng Cân Đối Kế Toán

# 1. Chuẩn bị dữ liệu: LỌC OUTLIER (TTS < 1e12) và tính Tỷ VND
p4_p5_data <- GAS_data_final %>%
  filter(TongTaiSan > 1e12) %>% # Lọc bỏ outlier 621 tỷ
  mutate(
    TTS_Ty = TongTaiSan / 1e9,
    NPT_Ty = NoPhaiTra / 1e9,
    VCSH_Ty = VonChuSoHuu / 1e9
  )

# 2. Vẽ Biểu đồ 4: Xu hướng Quy mô Bảng CĐKT (p4)
p4 <- plot_ly(data = p4_p5_data, x = ~Nam,
              hovertemplate = paste(
                "Năm: %{x}<br>",
                "%{yaxis.title.text}: %{y:,.0f} Tỷ VND"
              )) %>%
  # Thêm đường Tổng Tài Sản
  add_lines(y = ~TTS_Ty, name = "Tổng Tài Sản") %>%
  # Thêm đường Vốn Chủ Sg Hữu
  add_lines(y = ~VCSH_Ty, name = "Vốn Chủ Sở Hữu") %>%
  # Thêm đường Nợ Phải Trả
  add_lines(y = ~NPT_Ty, name = "Nợ Phải Trả") %>%
  layout(
    title = "Biểu đồ 4: Xu hướng Quy mô Bảng CĐKT (Đã lọc Outlier)",
    xaxis = list(title = "Năm"),
    yaxis = list(title = "Quy mô (Tỷ VND)"),
    legend = list(x = 0.1, y = -0.2, orientation = 'h')
  )
  
# 3. Chuẩn bị dữ liệu cho Biểu đồ 5 (Stacked Area): Dạng "long"
p5_data_long <- p4_p5_data %>%
  select(Nam, NPT_Ty, VCSH_Ty) %>% # Chỉ chọn 2 thành phần của nguồn vốn
  gather(key = "LoaiNguonVon", value = "GiaTri_Ty", -Nam) # Chuyển từ wide sang long

# 4. Vẽ Biểu đồ 5: Cơ cấu Nguồn vốn (p5)
p5 <- plot_ly(data = p5_data_long, x = ~Nam, y = ~GiaTri_Ty,
              color = ~LoaiNguonVon, # Tô màu theo Nợ / VCSH
              type = 'scatter', 
              mode = 'none', # Không vẽ điểm hay đường
              stackgroup = 'one', # Quan trọng: xếp chồng lên nhau
              hovertemplate = paste(
                "Năm: %{x}<br>",
                "Loại: %{fullData.name}<br>",
                "Giá trị: %{y:,.0f} Tỷ VND"
              )) %>%
  layout(
    title = "Biểu đồ 5: Cơ cấu Nguồn vốn (Nợ vs. Vốn CSH) (Đã lọc Outlier)",
    xaxis = list(title = "Năm"),
    yaxis = list(title = "Tổng Nguồn vốn (Tỷ VND)")
  )

# 5. Hiển thị biểu đồ
p4
p5

4. & 5. Nhận xét Biểu đồ 4 & 5: Quy mô và Cơ cấu Bảng CĐKT

(Lưu ý: Cả hai biểu đồ đều đã lọc bỏ 1 năm outlier (có TTS 621 tỷ) để trục Y có ý nghĩa).

  • Cấu trúc tài chính an toàn: Cả hai biểu đồ đều xác nhận một cấu trúc tài chính an toàn và bảo thủ. Biểu đồ 5 (diện tích xếp chồng) cho thấy phần Vốn Chủ Sở Hữu (VCSH - màu cam) luôn chiếm tỷ trọng lớn hơn đáng kể (gấp 2-3 lần) so với Nợ Phải Trả (NPT - màu xanh).

  • Tăng trưởng nhờ Vốn chủ: Biểu đồ 4 cho thấy đường Tổng Tài Sản (TTS - xanh dương) và đường Vốn Chủ Sở Hữu (VCSH - cam) tăng trưởng gần như song song. Điều này cho thấy GAS chủ yếu tài trợ cho sự mở rộng quy mô của mình bằng lợi nhuận giữ lại (tăng vốn chủ), thay vì dùng nợ vay.

  • Biến động Nợ: Đường Nợ Phải Trả (NPT - xanh lá) duy trì ở mức thấp và ổn định từ 2014-2020. Nó có một đợt tăng đột biến vào năm 2021 (đạt đỉnh ~26k tỷ) trước khi giảm trở lại. Điều này cho thấy trong giai đoạn phục hồi 2021-2022, GAS đã tạm thời tăng cường đòn bẩy để tài trợ cho hoạt động, nhưng nhanh chóng đưa về mức an toàn.

  • Kết luận: GAS duy trì một cấu trúc vốn rất mạnh, với tỷ lệ đòn bẩy thấp (khẳng định mean_tsn_vcsh = 0.36 ở Mục 2.4.1).

2.5.2. Phân tích Hiệu suất Sinh lời và Cấu trúc Tài chính

Giới thiệu:

Nhóm biểu đồ này tập trung vào việc đánh giá “chất lượng” hoạt động của GAS: khả năng sinh lời (ROE, ROA), hiệu quả chuyển đổi doanh thu (Biên LN ròng), và cấu trúc rủi ro (Đòn bẩy).

  • Phân tích Hiệu suất Sinh lời (ROE & ROA):

    • Từ Mục 2.4.1 & 2.4.2, ta biết hiệu suất sinh lời rất bất ổn. mean_roe (11.94%) và sd_roe (12.45%) gần bằng nhau, cho thấy sự biến động cực lớn.

    • Biểu đồ 6 sẽ trực quan hóa sự sụt giảm mạnh của ROE/ROA trong giai đoạn 2015-2017 (khi LNST sụt giảm) và sự phục hồi sau đó.

    • Biểu đồ 7 sẽ sử dụng ngưỡng 15% (gần với median_roe là 15.87%) để làm nổi bật 6 năm hoạt động hiệu quả (kết quả từ roe_tren_15 ở 2.4.2).

  • Phân tích Cấu trúc Tài chính (Đòn bẩy):

    • Biểu đồ 8 sẽ vẽ xu hướng của TySoNo_Tren_VCSH. Chúng ta biết mean_tsn_vcsh là 0.36 (thấp) và biểu đồ này bắt buộc phải lọc outlier (năm có TongTaiSan < 1e12) để cho thấy xu hướng đòn bẩy thực tế (dự kiến là ổn định và thấp).
  • Phân tích Hiệu quả (Biên Lợi nhuận):

    • Biểu đồ 9 sẽ vẽ BienLoiNhuanRong_Nam. Chỉ số này (với bln_mean = 7.44% và bln_median = 10.04%) đo lường 100 đồng doanh thu tạo ra bao nhiêu đồng lợi nhuận. Xu hướng của nó được kỳ vọng sẽ theo rất sát xu hướng của Lợi nhuận (Biểu đồ 1).
  • Phân tích Tác động Đòn bẩy:

    • Biểu đồ 10 sẽ kiểm tra giả thuyết: “Dùng nhiều nợ hơn có giúp tăng ROE không?”. Từ Mục 2.4.4, ma trận tương quan (đã lọc outlier) cho thấy mối tương quan giữa TySoNo_Tren_VCSHROE_Nam là rất yếu (chỉ 0.15). Biểu đồ phân tán này sẽ trực quan hóa mối quan hệ yếu ớt đó.

Trực quan hóa và Nhận xét:

6. Biểu đồ Đường: ROE và ROA (%)

# 1. Chuẩn vị dữ liệu
# (ROE_Nam và ROA_Nam đã có đơn vị % từ Mục 1.3)
p6_data <- GAS_data_final

# 2. Vẽ biểu đồ plotly (p6)
p6 <- plot_ly(data = p6_data, x = ~Nam,
              # Định nghĩa tooltip (hover)
              hovertemplate = paste(
                "Năm: %{x}<br>",
                "%{fullData.name}: %{y:.2f}%"
              )) %>%
  # Thêm đường ROE (%)
  add_lines(y = ~ROE_Nam, name = "ROE (Tỷ suất LN trên VCSH)") %>%
  # Thêm đường ROA (%)
  add_lines(y = ~ROA_Nam, name = "ROA (Tỷ suất LN trên Tài sản)") %>%
  # Áp dụng layout
  plotly::layout(
    title = "Biểu đồ 6: Diễn biến ROE và ROA (2014-2024)",
    xaxis = list(title = "Năm"),
    yaxis = list(title = "Tỷ suất Lợi nhuận (%)"),
    legend = list(x = 0.1, y = -0.2, orientation = 'h') # Đặt chú thích bên dưới
  )

# 3. Hiển thị biểu đồ
p6

Nhận xét Biểu đồ 6: ROE và ROA

Biểu đồ này trực quan hóa một cách rõ nét sự bất ổn trong hiệu suất sinh lời và cũng xác nhận năm 2019 chính là năm dữ liệu ngoại lai (outlier) mà đã phát hiện:

  • Sự sụp đổ 2015-2018: Tương tự như Biểu đồ 1, cả ROE (Tỷ suất LN trên VCSH - đường xanh) và ROA (Tỷ suất LN trên Tài sản - đường cam) đều sụp đổ từ đỉnh 2014 (ROE ~37%, ROA ~26%) xuống gần như 0% trong suốt 4 năm 2015-2018, tương ứng với giai đoạn Lợi nhuận sụt giảm.

  • Phát hiện Outlier 2019: Điểm dị biệt nhất là năm 2019. ROE (xanh) vẫn ở mức 0%, trong khi ROA (cam) đột ngột tăng vọt lên đỉnh cao nhất (~29.5%).

    • Phân tích: Điều này xảy ra vì ROA = LNST / TongTaiSanROE = LNST / VonChuSoHuu.

    • Dữ liệu từ 2.4.1 cho thấy năm 2019, LNSTVCSH vẫn bình thường, nhưng TongTaiSan bị ghi nhận lỗi (chỉ 621 tỷ).

    • Do đó, ROA (với mẫu số TongTaiSan 621 tỷ) đã bị tính toán sai và tăng vọt. ROE (với mẫu số VCSH 49k tỷ) vẫn ở mức 0%.

  • Phục hồi 2020-2024: Từ 2020, khi TongTaiSan trở lại bình thường, cả hai chỉ số ROE và ROA đều phục hồi về mức ổn (10-25%).

  • Kết luận: Biểu đồ này khẳng định sự biến động của hiệu suất sinh lời và xác nhận 2019 là năm outlier do lỗi dữ liệu TongTaiSan.

7. Biểu đồ Cột kết hợp Đường: ROE hàng năm với ngưỡng tham chiếu 15%

# 1. Chuẩn bị dữ liệu: Thêm cột Ngưỡng 15%
p7_data <- GAS_data_final %>%
  mutate(
    Nguong_15 = 15, # Tạo một cột có giá trị 15%
    # Tạo biến màu sắc (Tích cực/Tiêu cực)
    color_roe = ifelse(ROE_Nam >= Nguong_15, "Trên 15%", "Dưới 15%")
  )

# 2. Định nghĩa màu
colors_roe <- c("Trên 15%" = "#1f77b4", "Dưới 15%" = "#d62728") # Xanh / Đỏ

# 3. Vẽ biểu đồ plotly (p7)
p7 <- plot_ly(data = p7_data, x = ~Nam) %>%
  # Thêm Biểu đồ Cột cho ROE
  add_bars(y = ~ROE_Nam, 
           name = "ROE Hàng năm",
           color = ~color_roe, # Tô màu theo biến color_roe
           colors = colors_roe, # Áp dụng màu Xanh/Đỏ
           hovertemplate = paste(
             "Năm: %{x}<br>",
             "ROE: %{y:.2f}%"
           )) %>%
  # Thêm Đường tham chiếu 15%
  add_lines(y = ~Nguong_15,
            name = "Ngưỡng tham chiếu 15%",
            line = list(color = 'black', dash = 'dash'), # Nét đứt màu đen
            hovertemplate = "Ngưỡng tham chiếu: 15%") %>%
  # Áp dụng layout
  plotly::layout(
    title = "Biểu đồ 7: ROE hàng năm so với Ngưỡng 15%",
    xaxis = list(title = "Năm"),
    yaxis = list(title = "ROE (%)"),
    legend = list(x = 0.1, y = -0.2, orientation = 'h')
  )

# 4. Hiển thị biểu đồ
p7

Nhận xét Biểu đồ 7: ROE hàng năm vs. Ngưỡng 15%

Biểu đồ này phân loại rõ ràng các năm hoạt động hiệu quả và không hiệu quả của GAS:

  • Phân loại rõ rệt: Biểu đồ cho thấy 2 “trạng thái” rõ rệt của GAS.

    • Nhóm Hiệu quả (Cột xanh): Gồm 6 năm (2014, 2020, 2021, 2022, 2023, 2024) có ROE vượt trội so với ngưỡng tham chiếu 15%. Năm 2014 là năm hoàng kim (ROE ~37.5%), và giai đoạn 2020-2024 là giai đoạn phục hồi hiệu quả bền vững.

    • Nhóm Kém hiệu quả (Cột đỏ): Gồm 5 năm (2015, 2016, 2017, 2018, 2019) có ROE gần như bằng 0.

  • Kết luận: Trực quan hóa này xác nhận kết quả roe_tren_15 (Mục 2.4.2) là 6 năm. Nó cho thấy GAS có khả năng sinh lời rất cao, nhưng cũng tiềm ẩn rủi ro sụt giảm mạnh trong nhiều năm liên tiếp.

8. Biểu đồ Đường: Diễn biến Đòn bẩy Tài chính (Tỷ số Nợ / VCSH)

# 1. Chuẩn bị dữ liệu: LỌC OUTLIER
p8_data <- GAS_data_final %>%
  filter(TongTaiSan > 1e12) # Lọc bỏ outlier 621 tỷ

# 2. Vẽ biểu đồ plotly (p8)
p8 <- plot_ly(data = p8_data, x = ~Nam, y = ~TySoNo_Tren_VCSH,
              type = 'scatter', mode = 'lines+markers', # Cả đường và điểm
              name = "Tỷ số Nợ / VCSH",
              hovertemplate = paste(
                "Năm: %{x}<br>",
                "Tỷ số Nợ/VCSH: %{y:.2f}"
              )) %>%
  # Áp dụng layout
  plotly::layout(
    title = "Biểu đồ 8: Diễn biến Đòn bẩy Tài chính (Đã lọc Outlier)",
    xaxis = list(title = "Năm"),
    yaxis = list(title = "Tỷ lệ (Lần)")
  )

# 3. Hiển thị biểu đồ
p8

Nhận xét Biểu đồ 8: Đòn bẩy Tài chính

(Lưu ý: Biểu đồ này đã lọc bỏ năm outlier 2019, nên nó phản ánh đúng xu hướng đòn bẩy trong 10 năm kinh doanh bình thường).

  • Cấu trúc Nợ an toàn: Biểu đồ cho thấy Tỷ số Nợ / VCSH (Đòn bẩy) luôn duy trì ở mức rất thấp, toàn bộ đều dưới 0.52 (tức Nợ luôn ít hơn một nửa Vốn chủ). Điều này khẳng định cấu trúc tài chính an toàn mà ta đã thấy ở Biểu đồ 4 & 5.

  • Các điểm biến động:

    • Đáy 2020: Đòn bẩy chạm đáy vào năm 2020 (chỉ ~0.28). Đây là năm COVID-19, cho thấy GAS đã co về phòng thủ, giảm nợ vay.

    • Đỉnh 2021: Ngay sau đó, đòn bẩy tăng vọt lên đỉnh cao nhất (~0.51) vào năm 2021.

  • Kết luận (Kết hợp Biểu đồ 4): Kết hợp với Biểu đồ 4 (cho thấy Nợ Phải Trả cũng đạt đỉnh năm 2021), có thể kết luận: Năm 2021, GAS đã chủ động tăng cường sử dụng nợ vay (tăng đòn bẩy) để tài trợ cho sự phục hồi và tăng trưởng bùng nổ của giai đoạn 2021-2022.

9. Biểu đồ Cột: Diễn biến Biên Lợi nhuận ròng (%)

# 1. Chuẩn bị dữ liệu: Sử dụng biến 'BienLoiNhuanRong_Nam' (từ 2.4.5)
p9_data <- GAS_data_final

# 2. Vẽ biểu đồ plotly (p9)
p9 <- plot_ly(data = p9_data, x = ~Nam, y = ~BienLoiNhuanRong_Nam,
              type = "bar",
              name = "Biên Lợi nhuận ròng",
              hovertemplate = paste(
                "Năm: %{x}<br>",
                "Biên LN ròng: %{y:.2f}%"
              )) %>%
  # Áp dụng layout
  plotly::layout(
    title = "Biểu đồ 9: Diễn biến Biên Lợi nhuận ròng (2014-2024)",
    xaxis = list(title = "Năm"),
    yaxis = list(title = "Biên Lợi nhuận ròng (%)")
  )

# 3. Hiển thị biểu đồ
p9

Nhận xét Biểu đồ 9: Diễn biến Biên Lợi nhuận ròng (%)

  • Phản ánh Lợi nhuận: Vì Biên Lợi nhuận ròng (LNST / DoanhThu) có cùng tử số (LNST) với ROE/ROA, không ngạc nhiên khi hình dạng của biểu đồ này gần như giống hệt Biểu đồ 6 (trừ outlier 2019).

  • Hai trạng thái: Biểu đồ cho thấy 2 trạng thái rõ rệt:

    • Giai đoạn Biên lợi nhuận cao (2014, 2020-2024): Đạt đỉnh 2014 (Biên LN ~19%), nghĩa là 100 đồng doanh thu tạo ra 19 đồng lợi nhuận. Giai đoạn 2020-2024 phục hồi ở mức 10-15%.

    • Giai đoạn Biên lợi nhuận sụp đổ (2015-2019): Biên lợi nhuận gần như bằng 0, cho thấy trong 5 năm này, GAS kinh doanh gần như hòa vốn (doanh thu chỉ đủ bù chi phí, có thể do giá dầu sụt giảm).

  • Kết luận: Biên lợi nhuận của GAS rất nhạy cảm với các cú sốc bên ngoài.

10. Biểu đồ Phân tán: Phân tích Tác động Đòn bẩy (Nợ/VCSH vs. ROE)

# 1. Chuẩn bị dữ liệu: LỌC OUTLIER
p10_data <- GAS_data_final %>%
  filter(TongTaiSan > 1e12) # Lọc bỏ outlier 621 tỷ

# 2. Vẽ biểu đồ ggplot (p10)
# (Sử dụng ggplot vì đây là biểu đồ phân tích, không phải xu hướng)
p10 <- ggplot(data = p10_data, 
              aes(x = TySoNo_Tren_VCSH, y = ROE_Nam)) +
  # Thêm các điểm (size = 3)
  geom_point(aes(color = as.factor(Nam)), size = 3) + # 'color' theo 'Nam'
  # Thêm nhãn cho các điểm
  geom_text(aes(label = Nam), vjust = -0.8, size = 3) +
  # Thêm đường xu hướng tuyến tính (lm = linear model)
  geom_smooth(method = "lm", se = FALSE, color = "red", linetype = "dashed") +
  # Đặt tiêu đề và nhãn trục
  labs(
    title = "Biểu đồ 10: Tác động của Đòn bẩy lên ROE (Đã lọc Outlier)",
    x = "Đòn bẩy Tài chính (Tỷ số Nợ / VCSH)",
    y = "Hiệu quả Sinh lời (ROE %)",
    caption = "Phân tích 10 năm (2014-2024, đã lọc 1 outlier)",
    color = "Năm" # Tiêu đề cho phần chú thích màu
  ) +
  theme_minimal() # Sử dụng theme tối giản

# 3. Hiển thị biểu đồ
p10

Nhận xét Biểu đồ 10: Tác động của Đòn bẩy lên ROE

(Lưu ý: Biểu đồ này phân tích 10 năm, đã lọc bỏ outlier 2019).

  • Tương quan yếu: Đường xu hướng (nét đứt màu đỏ) dốc lên rất nhẹ. Điều này trực quan hóa chính xác kết quả cor_roe_gia = 0.276 (Mục 2.4.4) - một mối tương quan dương nhưng rất yếu.

  • Phân cụm dữ liệu: Điểm nổi bật nhất của biểu đồ là dữ liệu bị phân tách thành 2 cụm rõ rệt:

    1. Cụm Kém hiệu quả (ROE ~ 0%): Các năm 2015, 2016, 2017, 2018 đều nằm ở đáy, bất kể mức đòn bẩy là bao nhiêu.

    2. Cụm Hiệu quả (ROE > 15%): Gồm 2014, 2020, 2021, 2022, 2023, 2024.

  • Không có mối quan hệ rõ ràng: Trong “Cụm Hiệu quả”, không có mối liên hệ rõ ràng. Năm có ROE cao nhất (2014) lại dùng đòn bẩy cao (~0.43). Ngược lại, năm có đòn bẩy cao nhất (2021, ~0.51) lại có ROE thấp hơn (chỉ ~17%). Trong khi đó, các năm có ROE rất cao (2022, 2023, 2024) lại dùng đòn bẩy ở mức trung bình-thấp (~0.35).

  • Kết luận: Biểu đồ này bác bỏ giả thuyết “dùng nhiều nợ hơn sẽ tăng ROE”. Nó cho thấy hiệu quả sinh lời (ROE) của GAS không phụ thuộc vào đòn bẩy tài chính, mà phụ thuộc vào các yếu tố vĩ mô (như giá dầu, nhu cầu thị trường) đã quyết định năm đó “hiệu quả” hay “kém hiệu quả”.

1.5.3. Phân tích Tương quan và Định giá Thị trường

Giới thiệu:

Nhóm biểu đồ này khám phá mối quan hệ giữa các chỉ số tài chính nội tại và các chỉ số thị trường (định giá).

  • Phân tích Tương quan Lợi nhuận (LNST, ROE) vs. Giá:

    • Từ Mục 2.4.4, ma trận tương quan (đã lọc outlier) cho thấy mối tương quan giữa LoiNhuanSauThueGia_DongCua_CuoiNam là trung bình (cor_ln_gia = 0.495), và tương quan giữa ROE_NamGia_DongCua_CuoiNam là yếu (cor_roe_gia = 0.276).

    • Biểu đồ 11 & 12 sẽ trực quan hóa mối quan hệ này bằng biểu đồ phân tán (scatter plot) động. Chúng ta kỳ vọng đường xu hướng (regression line) trên Biểu đồ 11 sẽ dốc hơn Biểu đồ 12.

  • Phân tích Tương quan Quy mô (Tài sản) vs. Vốn hóa:

    • Ngược lại, ma trận 2.4.4 cho thấy tương quan rất mạnh giữa TongTaiSanGia_DongCua_CuoiNam (0.83). Biến VonHoa_TyVND (Vốn hóa) được tính từ Giá, do đó chúng ta cũng kỳ vọng một mối quan hệ tuyến tính rất mạnh giữa TongTaiSanVonHoa_TyVND.

    • Biểu đồ 13 sẽ vẽ mối quan hệ này. Lưu ý quan trọng: Biểu đồ này bắt buộc phải lọc outlier năm 2019 (có TongTaiSan 621 tỷ) để đường xu hướng có ý nghĩa.

  • Phân tích Xu hướng Định giá (Vốn hóa, P/E):

    • Biểu đồ 14 sẽ so sánh xu hướng của VonHoa_TyVNDLoiNhuanSauThue (sử dụng 2 trục Y) để xem vốn hóa thị trường có bám sát lợi nhuận thực tế hay không.

    • Biểu đồ 15 sẽ vẽ diễn biến của chỉ số P_E_CuoiNam (đã tính ở 2.4.5, với pe_mean = 9.93) để xem thị trường đã định giá GAS đắt hay rẻ qua các năm.

Trực quan hóa và Nhận xét:

11. Biểu đồ Phân tán: Lợi nhuận Sau thuế vs. Giá Cổ phiếu

# 1. Chuẩn bị dữ liệu: Chuyển LNST sang Tỷ VND
p11_data <- GAS_data_final %>%
  mutate(LNST_Ty = LoiNhuanSauThue / 1e9)

# 2. Vẽ biểu đồ plotly (p11)
p11 <- plot_ly(data = p11_data, 
               x = ~LNST_Ty, # Trục X: Lợi nhuận
               y = ~Gia_DongCua_CuoiNam, # Trục Y: Giá
               text = ~Nam, # Hiển thị 'Năm' khi hover
               type = 'scatter', mode = 'markers', # Dạng điểm
               hovertemplate = paste(
                 "Năm: %{text}<br>",
                 "Lợi nhuận: %{x:,.0f} Tỷ VND<br>",
                 "Giá Cổ phiếu: %{y:,.0f} VND"
               )) %>%
  # Thêm đường xu hướng tuyến tính
  add_trace(type = 'scatter', mode = 'lines',
            x = ~LNST_Ty, 
            # Dùng hàm fitted() để lấy giá trị dự đoán từ 1 mô hình tuyến tính (lm)
            y = fitted(lm(Gia_DongCua_CuoiNam ~ LNST_Ty, data = p11_data)),
            name = "Đường xu hướng",
            hoverinfo = 'none') %>% # Không cần hover cho đường này
  # Áp dụng layout
  plotly::layout(
    title = "Biểu đồ 11: Mối quan hệ LNST vs. Giá Cổ phiếu (2014-2024)",
    xaxis = list(title = "Lợi nhuận Sau thuế (Tỷ VND)"),
    yaxis = list(title = "Giá Đóng cửa Cuối năm (VND)"),
    showlegend = FALSE # Ẩn chú thích
  )

# 3. Hiển thị biểu đồ
p11

Nhận xét Biểu đồ 11: Mối quan hệ LNST vs. Giá Cổ phiếu

Biểu đồ phân tán này cho thấy một mối quan hệ phức tạp, khẳng định kết quả tương quan trung bình (cor_ln_gia = 0.495) từ Mục 2.4.4.

  • Tổng quan: Đường xu hướng (màu cam) có độ dốc dương, cho thấy về tổng thể, lợi nhuận cao hơn có liên quan đến giá cổ phiếu cao hơn.

  • Phân cụm dữ liệu: Tuy nhiên, các điểm dữ liệu phân tán rất rộng (“nhiễu”), đặc biệt là ở cụm bên trái (Lợi nhuận < 2,000 tỷ). Trong cụm này (tương ứng giai đoạn 2015-2019), giá cổ phiếu dao động rất mạnh, từ mức đáy (năm 2015, ~18k VND) đến mức cao (năm 2018, ~58k VND) dù lợi nhuận gần như bằng 0.

  • Kết luận: Biểu đồ này chỉ ra rằng Lợi nhuận sau thuế không phải là yếu tố duy nhất hay yếu tố mạnh nhất quyết định giá cổ phiếu. Trong các năm khủng hoảng (LNST thấp), thị trường dường như định giá cổ phiếu dựa trên các yếu tố khác (như tài sản hoặc kỳ vọng phục hồi) thay vì lợi nhuận thực tế.

12. Biểu đồ Phân tán: ROE (%) vs. Giá Cổ phiếu

# 1. Chuẩn bị dữ liệu
p12_data <- GAS_data_final

# 2. Vẽ biểu đồ plotly (p12)
p12 <- plot_ly(data = p12_data, 
               x = ~ROE_Nam, # Trục X: ROE
               y = ~Gia_DongCua_CuoiNam, # Trục Y: Giá
               text = ~Nam, # Hiển thị 'Năm' khi hover
               type = 'scatter', mode = 'markers',
               hovertemplate = paste(
                 "Năm: %{text}<br>",
                 "ROE: %{x:.2f}%<br>",
                 "Giá Cổ phiếu: %{y:,.0f} VND"
               )) %>%
  # Thêm đường xu hướng tuyến tính
  add_trace(type = 'scatter', mode = 'lines',
            x = ~ROE_Nam, 
            y = fitted(lm(Gia_DongCua_CuoiNam ~ ROE_Nam, data = p12_data)),
            name = "Đường xu hướng",
            hoverinfo = 'none') %>%
  # Áp dụng layout
  plotly::layout(
    title = "Biểu đồ 12: Mối quan hệ ROE vs. Giá Cổ phiếu (2014-2024)",
    xaxis = list(title = "ROE (%)"),
    yaxis = list(title = "Giá Đóng cửa Cuối năm (VND)"),
    showlegend = FALSE
  )

# 3. Hiển thị biểu đồ
p12

Nhận xét Biểu đồ 12: Mối quan hệ ROE vs. Giá Cổ phiếu

Biểu đồ này cho thấy một mối quan hệ còn yếu hơn so với Biểu đồ 11.

  • Tương quan yếu: Đường xu hướng (màu cam) gần như phẳng, trực quan hóa kết quả tương quan rất yếu (cor_roe_gia = 0.276) từ Mục 2.4.4.

  • Không có quan hệ rõ ràng: Các điểm dữ liệu nằm rải rác mà không có một quy luật rõ ràng.

    • Năm có ROE cao nhất (2014, ~37%) lại không có giá cao nhất (chỉ ~34k VND).

    • Ngược lại, năm có giá cao nhất (2022, ~70k VND) chỉ có ROE ở mức khá ( ~24%).

    • Cụm ROE gần 0% (2015-2019) có mức giá trải dài từ 18k đến 58k.

  • Kết luận: Biểu đồ này khẳng định mạnh mẽ rằng thị trường không định giá cổ phiếu GAS dựa trên hiệu quả sinh lời (ROE) trong năm đó. Việc ROE cao hay thấp không phải là yếu tố chính dẫn dắt giá cổ phiếu.

13. Biểu đồ Phân tán: Tổng Tài sản vs. Vốn hóa Thị trường

# 1. Chuẩn bị dữ liệu: LỌC OUTLIER 2019 và tính Tỷ VND
p13_data <- GAS_data_final %>%
  filter(TongTaiSan > 1e12) %>% # Lọc bỏ outlier 621 tỷ
  mutate(
    TTS_Ty = TongTaiSan / 1e9, # Đơn vị Tỷ VND
    # VonHoa_TyVND đã được tính ở 2.4.5
  )

# 2. Vẽ biểu đồ plotly (p13)
p13 <- plot_ly(data = p13_data, 
               x = ~TTS_Ty, # Trục X: Tổng Tài Sản
               y = ~VonHoa_TyVND, # Trục Y: Vốn hóa
               text = ~Nam, # Hiển thị 'Năm' khi hover
               type = 'scatter', mode = 'markers',
               hovertemplate = paste(
                 "Năm: %{text}<br>",
                 "Tổng Tài sản: %{x:,.0f} Tỷ VND<br>",
                 "Vốn hóa: %{y:,.0f} Tỷ VND"
               )) %>%
  # Thêm đường xu hướng tuyến tính
  add_trace(type = 'scatter', mode = 'lines',
            x = ~TTS_Ty, 
            y = fitted(lm(VonHoa_TyVND ~ TTS_Ty, data = p13_data)),
            name = "Đường xu hướng",
            hoverinfo = 'none') %>%
  # Áp dụng layout
  plotly::layout(
    title = "Biểu đồ 13: Tổng Tài sản vs. Vốn hóa (Đã lọc Outlier)",
    xaxis = list(title = "Tổng Tài sản (Tỷ VND)"),
    yaxis = list(title = "Vốn hóa Thị trường (Tỷ VND)"),
    showlegend = FALSE
  )

# 3. Hiển thị biểu đồ
p13

Nhận xét Biểu đồ 13: Tổng Tài sản vs. Vốn hóa

(Lưu ý: Biểu đồ này đã lọc bỏ outlier 2019, phân tích trên 10 năm).

  • Tương quan tuyến tính rất mạnh: Đây là phát hiện quan trọng nhất. Trái ngược với Biểu đồ 11 và 12, các điểm dữ liệu (các năm) trong biểu đồ này bám rất sát vào đường xu hướng tuyến tính.

  • Quy mô quyết định giá trị: Đường xu hướng dốc lên mạnh mẽ, cho thấy một mối quan hệ gần như 1:1. Khi Tổng Tài sản (trục X) tăng lên, Vốn hóa Thị trường (trục Y) tăng lên một cách tương ứng.

  • Kết luận (Kết hợp 11 & 12): Kết quả này giải đáp cho các biểu đồ trước. Thị trường dường như định giá GAS không phải dựa trên yếu tố nội tại (LNST hay ROE) mà dựa trên quy mô (Tổng Tài sản). Đây là đặc điểm định giá thường thấy ở các công ty Blue-chip (chỉ các công ty lớn, uy tín, đầu ngành, có tài chính vững mạnh), nơi quy mô tài sản được xem là yếu tố bảo chứng cho giá trị.

14. Biểu đồ Đường động: Xu hướng Vốn hóa Thị trường vs. Lợi nhuận

# 1. Chuẩn bị dữ liệu: Chuyển LNST sang Tỷ VND
p14_data <- GAS_data_final %>%
  mutate(
    LNST_Ty = LoiNhuanSauThue / 1e9
    # VonHoa_TyVND đã có
  )

# 2. Định nghĩa trục Y thứ 2 (cho Lợi nhuận)
y2_p14 <- list(
  overlaying = "y", 
  side = "right", 
  title = "Lợi nhuận (Tỷ VND)",
  showgrid = FALSE
)

# 3. Vẽ biểu đồ plotly (p14)
p14 <- plot_ly(data = p14_data, x = ~Nam,
               hovertemplate = paste(
                 "Năm: %{x}<br>",
                 "%{yaxis.title.text}: %{y:,.0f} Tỷ VND"
               )) %>%
  # Thêm đường Vốn hóa (sử dụng trục y1)
  add_lines(y = ~VonHoa_TyVND, name = "Vốn hóa (Trục trái)", yaxis = "y1") %>%
  # Thêm đường Lợi nhuận (sử dụng trục y2)
  add_lines(y = ~LNST_Ty, name = "Lợi Nhuận (Trục phải)", yaxis = "y2") %>%
  # Áp dụng layout
  plotly::layout(
    title = "Biểu đồ 14: Xu hướng Vốn hóa Thị trường và Lợi nhuận (2014-2024)",
    xaxis = list(title = "Năm"),
    yaxis = list(title = "Vốn hóa (Tỷ VND)"),
    yaxis2 = y2_p14, # Áp dụng trục y2
    legend = list(x = 0.1, y = -0.2, orientation = 'h')
  )

# 4. Hiển thị biểu đồ
p14

Nhận xét Biểu đồ 14: Xu hướng Vốn hóa vs. Lợi nhuận

Biểu đồ này làm rõ hơn sự “lệch pha” giữa thị trường và lợi nhuận:

  • Giai đoạn 1 (2014-2015): Cùng pha: Cả Vốn hóa (xanh) và Lợi nhuận (cam) đều sụt giảm mạnh.

  • Giai đoạn 2 (2015-2019): Phân kỳ Lớn: Đây là giai đoạn đáng chú ý nhất. Lợi nhuận (cam) gần như bằng 0 và đi ngang. Tuy nhiên, Vốn hóa (xanh) không sụp đổ về 0, mà chỉ giảm về đáy rồi bắt đầu phục hồi nhẹ từ 2017, trước khi lợi nhuận phục hồi.

  • Giai đoạn 3 (2020-2022): Cùng pha: Cả hai cùng phục hồi mạnh mẽ, đạt đỉnh 2022.

  • Giai đoạn 4 (2022-2024): Phân kỳ Lần 2: Lợi nhuận (cam) đạt đỉnh 2022 và sụt giảm. Nhưng Vốn hóa (xanh) vẫn tiếp tục tăng, đạt đỉnh mới vào 2023-2024.

  • Kết luận: Biểu đồ này khẳng định thị trường (Vốn hóa) có “tầm nhìn” riêng, không bám sát lợi nhuận ngắn hạn. Sự phân kỳ 2022-2024 cho thấy thị trường tin rằng mức lợi nhuận đỉnh 2022 chỉ là tạm thời (do giá dầu cao), và họ định giá công ty dựa trên tiềm năng dài hạn/quy mô tài sản (như Biểu đồ 13) nên vốn hóa vẫn tiếp tục tăng.

15. Biểu đồ Đường: Chỉ số P/E

# 1. Chuẩn bị dữ liệu: 
p15_data <- GAS_data_final
# (P_E_CuoiNam đã được tính và xử lý NA/Inf ở 1.4.5)

# 2. Vẽ biểu đồ plotly (p15)
p15 <- plot_ly(data = p15_data, x = ~Nam, y = ~P_E_CuoiNam,
              type = 'scatter', mode = 'lines+markers', # Cả đường và điểm
              name = "P/E Cuối năm",
              hovertemplate = paste(
                "Năm: %{x}<br>",
                "P/E: %{y:.2f} (lần)"
              )) %>%
  # Áp dụng layout
  plotly::layout(
    title = "Biểu đồ 15: Định giá P/E (2014-2024)",
    xaxis = list(title = "Năm"),
    yaxis = list(title = "Chỉ số P/E (Lần)")
  )

# 3. Hiển thị biểu đồ
p15

Nhận xét Biểu đồ 15: Định giá P/E

Biểu đồ này cho thấy sự thay đổi trong kỳ vọng của thị trường:

  • Giai đoạn 1 (2014-2016): Định giá rẻ: P/E ở mức rất thấp, chỉ ~4-5 lần. Điều này cho thấy thị trường bi quan, đánh giá lợi nhuận 2014 là không bền vững và đang chiết khấu (discount) mạnh (thực tế đã đúng khi LN sụp đổ 2015-2016).

  • Giai đoạn 2 (2017-2021): Tăng kỳ vọng: P/E tăng mạnh từ ~5 (2016) lên đỉnh ~15 (2021). Giai đoạn này, lợi nhuận vẫn còn thấp (trừ 2020-2021), nhưng thị trường đã trả giá cao hơn cho mỗi đồng lợi nhuận, cho thấy sự kỳ vọng vào sự phục hồi.

  • Giai đoạn 3 (2022): “Đỉnh Lợi nhuận”: P/E giảm mạnh xuống ~9. Đây là một tín hiệu kinh điển: Khi lợi nhuận đạt đỉnh (LNST 2022 cao nhất lịch sử), thị trường nhận định đây là đỉnh chu kỳ và không bền vững, do đó P/E bị co lại (giảm).

  • Kết luận: P/E của GAS rất biến động, phản ánh sự thay đổi trong kỳ vọng của nhà đầu tư. Mức trung bình pe_mean = 9.93 (Mục 2.4.5) là một con số hợp lý cho một doanh nghiệp chu kỳ như GAS.

1.5.4. Phân tích Chất lượng Lợi nhuận và Phân phối Dữ liệu

Giới thiệu:

Nhóm biểu đồ cuối cùng này đi sâu vào “chất lượng” của lợi nhuận và kiểm tra lại các giả định về phân phối dữ liệu.

  • Phân tích Chất lượng Lợi nhuận (CFO vs. LNST):

    • Từ Mục 2.4.5, chúng ta có một phát hiện quan trọng: cash_conv_mean (Tỷ lệ CFO/LNST trung bình) là 22.16, trong khi cash_conv_median (trung vị) chỉ là 1.19.

    • Điều này 100% khẳng định sự tồn tại của ít nhất một năm outlier nghiêm trọng (năm có LNST rất thấp nhưng CFO rất cao, khiến tỷ lệ này tăng vọt).

    • Biểu đồ 16 sẽ so sánh xu hướng của Dòng tiền HĐKD (CFO) và Lợi nhuận (LNST) trên hai trục Y.

    • Biểu đồ 17 (quan trọng nhất) sẽ vẽ Tỷ lệ CFO/LNST. Bắt buộc phải lọc bỏ (filter) các giá trị outlier (ví dụ: Tỷ lệ > 10) để biểu đồ có ý nghĩa, nếu không sẽ chỉ thấy một cột outlier khổng lồ và 10 cột còn lại bằng 0.

  • Phân tích Phân phối (Violin, Density):

    • Biểu đồ 18 (Violin plot) là phiên bản nâng cao của Boxplot (Biểu đồ 9, Mục 2.4.2). Nó không chỉ cho thấy các mức phân vị (Q1, Q2, Q3) mà còn cho thấy “hình dạng” phân phối (dày ở đâu, mỏng ở đâu). Ta kỳ vọng sẽ thấy nó “dày” ở hai cụm: một cụm gần 0% và một cụm quanh 15-20%.

    • Biểu đồ 19 (Density plot) là phiên bản nâng cao của Histogram (Biểu đồ 10, Mục 2.4.2). Ta bắt buộc phải lọc bỏ outlier 4182.9% (năm 2017) để xem hình dạng phân phối thực sự của 10 năm còn lại.

  • Trực quan hóa Tương quan (Heatmap):

    • Biểu đồ 20 là phiên bản đẹp hơn (dùng ggplot2) của corrplot (Biểu đồ 17, Mục 2.4.4). Nó sẽ trực quan hóa cor_matrix (đã lọc outlier 2019) bằng màu sắc.

Trực quan hóa và Nhận xét

16. Biểu đồ Đường: So sánh Dòng tiền HĐKD (CFO) vs. Lợi nhuận (LNST)

# 1. Chuẩn bị dữ liệu: Chuyển sang Tỷ VND
p16_data <- GAS_data_final %>%
  mutate(
    LNST_Ty = LoiNhuanSauThue / 1e9, # Lợi nhuận (Tỷ VND)
    CFO_Ty = CFO / 1e9              # Dòng tiền HĐKD (Tỷ VND)
  )

# 2. Định nghĩa trục Y thứ 2 (cho Lợi nhuận)
y2_p16 <- list(
  overlaying = "y", # Đè trục y2 lên trục y1
  side = "right",   # Đặt ở bên phải
  title = "Lợi nhuận (Tỷ VND)", # Tiêu đề trục
  showgrid = FALSE  # Ẩn lưới
)

# 3. Vẽ biểu đồ plotly (p16)
p16 <- plot_ly(data = p16_data, x = ~Nam,
               # Định nghĩa tooltip (hover)
               hovertemplate = paste(
                 "Năm: %{x}<br>",
                 "%{yaxis.title.text}: %{y:,.0f} Tỷ VND"
               )) %>%
  # Thêm đường CFO (sử dụng trục y1 mặc định)
  add_lines(y = ~CFO_Ty, name = "CFO - Dòng tiền HĐKD (Trái)", yaxis = "y1") %>%
  # Thêm đường Lợi nhuận (sử dụng trục y2)
  add_lines(y = ~LNST_Ty, name = "LNST - Lợi nhuận Sổ sách (Phải)", yaxis = "y2") %>%
  # Áp dụng layout
  plotly::layout(
    title = "Biểu đồ 16: Dòng tiền HĐKD (CFO) vs. Lợi nhuận (LNST) (2014-2024)",
    xaxis = list(title = "Năm"),
    yaxis = list(title = "Dòng tiền (Tỷ VND)"),
    yaxis2 = y2_p16, # Áp dụng trục y2
    legend = list(x = 0.1, y = -0.2, orientation = 'h') # Đặt chú thích bên dưới
  )

# 4. Hiển thị biểu đồ
p16

Nhận xét Biểu đồ 16: Dòng tiền HĐKD (CFO) vs. Lợi nhuận (LNST)

Biểu đồ này cho thấy mối quan hệ tương quan nhưng cũng đầy biến động giữa dòng tiền thực tế và lợi nhuận sổ sách:

  • Tương quan thuận: Nhìn chung, hai đường CFO (xanh) và LNST (cam) di chuyển cùng pha: cùng sụt giảm mạnh 2014-2016 và cùng đạt đỉnh 2022.

  • Chất lượng tiền tốt trong khủng hoảng: Điểm đáng chú ý là trong suốt giai đoạn khủng hoảng 2015-2019, LNST (cam) gần như bằng 0, nhưng CFO (xanh) vẫn duy trì ở mức dương (đỉnh điểm là 2017, CFO đạt ~14k tỷ trong khi LNST bằng 0). Điều này cho thấy khả năng thu tiền của GAS vẫn rất tốt ngay cả khi lợi nhuận kế toán không có, chủ yếu do thu được các khoản phải thu cũ.

  • Giai đoạn phục hồi (2020-2024): Trong giai đoạn này, hai đường bám sát nhau hơn, LNST (cam) tăng mạnh, nhưng CFO (xanh) có xu hướng thấp hơn một chút, cho thấy lợi nhuận có thể đang nằm một phần ở các khoản phải thu mới.

  • Kết luận: CFO biến động còn mạnh hơn cả LNST, nhưng việc CFO duy trì mức dương cao trong giai đoạn 2015-2019 là một dấu hiệu tích cực về khả năng quản trị dòng tiền.

17. Biểu đồ Cột: Tỷ lệ Chuyển đổi Tiền mặt (CFO/LNST)

# 1. Chuẩn bị dữ liệu: LỌC OUTLIER NGHIÊM TRỌNG
# Từ 1.4.5, ta biết Mean (22.16) và Median (1.19) lệch nhau rất lớn
# Điều này có nghĩa là có outlier. Ta sẽ lọc bỏ các giá trị quá cao (>10)
# và quá thấp (< -10) để biểu đồ có ý nghĩa
p17_data <- GAS_data_final %>%
  filter(TyLe_CFO_Tren_LNST < 10 & TyLe_CFO_Tren_LNST > -10) %>%
  mutate(
    # Tạo biến màu sắc (Chất lượng Tốt/Xấu)
    # Tốt: Tỷ lệ > 1 (Tiền > Lợi nhuận)
    color_cash = ifelse(TyLe_CFO_Tren_LNST >= 1, "Tốt (>= 1)", "Kém (< 1)")
  )

# 2. Định nghĩa màu
colors_cash <- c("Tốt (>= 1)" = "#1f77b4", "Kém (< 1)" = "#d62728") # Xanh / Đỏ

# 3. Vẽ biểu đồ plotly (p17)
p17 <- plot_ly(data = p17_data, x = ~Nam, y = ~TyLe_CFO_Tren_LNST,
               color = ~color_cash, # Tô màu theo biến color_cash
               colors = colors_cash, # Áp dụng màu Xanh/Đỏ
               type = "bar",
               hovertemplate = paste(
                 "Năm: %{x}<br>",
                 "Tỷ lệ CFO/LNST: %{y:.2f}"
               )) %>%
  # Thêm đường tham chiếu (Tỷ lệ = 1)
  add_lines(y = 1, name = "Ngưỡng 100% (CFO = LNST)",
            line = list(color = 'black', dash = 'dash'),
            hoverinfo = 'none') %>%
  # Áp dụng layout
  plotly::layout(
    title = "Biểu đồ 17: Tỷ lệ Chuyển đổi Tiền mặt (Đã lọc Outlier)",
    xaxis = list(title = "Năm"),
    yaxis = list(title = "Tỷ lệ (CFO / LNST)")
  )

# 4. Hiển thị biểu đồ
p17

Nhận xét Biểu đồ 17: Tỷ lệ Chuyển đổi Tiền mặt

Biểu đồ này trực quan hóa chất lượng lợi nhuận qua các năm (sau khi đã lọc bỏ các năm 2015-2019, nơi LNST quá thấp khiến tỷ lệ này vô nghĩa):

  • Kết quả lọc: Biểu đồ chỉ còn lại các năm có lợi nhuận đáng kể (2014, 2020-2024).

  • Chất lượng lợi nhuận “Tốt” (Cột xanh): Các năm 2014 (Tỷ lệ ~1.19) và 2023 (Tỷ lệ ~1.19) có chất lượng lợi nhuận tuyệt vời, vượt ngưỡng 100% (đường nét đứt). Điều này có nghĩa là 1 đồng LNST tạo ra 1.19 đồng tiền mặt. Đây chính là giá trị median (trung vị) 1.19 mà ta tìm thấy ở Mục 2.4.5.

  • Chất lượng “Khá” (Cột đỏ): Các năm 2020, 2021, 2022, 2024 có tỷ lệ < 1 (trong khoảng 0.85 - 0.95). Đây vẫn là mức chấp nhận được, cho thấy phần lớn lợi nhuận (85-95%) được hỗ trợ bằng tiền mặt, chỉ một phần nhỏ nằm ở các khoản phải thu.

  • Kết luận: Biểu đồ này khẳng định cash_conv_median = 1.19 là một chỉ số đáng tin cậy. Chất lượng lợi nhuận của GAS trong các năm kinh doanh bình thường là rất cao (thường > 0.85), và trong các năm điển hình (trung vị) là xuất sắc (> 1).

18. Biểu đồ Violin kết hợp Boxplot: Phân phối của ROE (%)

# 1. Chuẩn bị dữ liệu: Không cần
p18_data <- GAS_data_final

# 2. Vẽ biểu đồ ggplot (p18)
# (Sử dụng ggplot vì đây là biểu đồ thống kê tĩnh)
p18 <- ggplot(data = p18_data, aes(x = "ROE", y = ROE_Nam)) +
  # Thêm biểu đồ Violin (cho thấy hình dạng phân phối)
  geom_violin(aes(fill = "ROE"), trim = FALSE) +
  # Thêm biểu đồ Boxplot (cho thấy Q1, Q2, Q3)
  geom_boxplot(width = 0.1, fill = "white") +
  # Thêm các điểm dữ liệu (jitter để tránh chồng chéo)
  geom_jitter(width = 0.05, height = 0, alpha = 0.5) +
  # Đặt tiêu đề và nhãn trục
  labs(
    title = "Biểu đồ 18: Phân phối của ROE (2014-2024)",
    x = "Chỉ số",
    y = "ROE (%)",
    caption = "Phân tích 11 năm (Bao gồm cả outlier 2019)"
  ) +
  theme_minimal() + # Sử dụng theme tối giản
  theme(legend.position = "none") # Ẩn chú thích

# 3. Hiển thị biểu đồ
p18

Nhận xét Biểu đồ 18: Phân phối của ROE

Biểu đồ Violin này là một phiên bản nâng cao của boxplot (ở 2.4.2), cung cấp cái nhìn sâu sắc về hình dạng phân phối của ROE trong 11 năm:

  • Phân phối hai cực (Bimodal): Đặc điểm nổi bật nhất là hình dạng “con quay” (violin) bị “thắt” ở giữa và “phình” ra ở hai đầu.

    • Cực 1 (Đáy): Phần phình rộng ở đáy (ROE ~ 0%). Điều này cho thấy có một cụm dữ liệu lớn (5 năm khủng hoảng 2015-2019) tập trung dày đặc ở mức 0%.

    • Cực 2 (Đỉnh): Phần phình rộng thứ hai ở khu vực 15% - 25%. Đây là cụm 6 năm hoạt động hiệu quả (2014, 2020-2024).

  • Hộp Boxplot: Hộp boxplot (màu trắng) nằm lọt thỏm trong “cực 2”, xác nhận rằng median (trung vị) nằm ở ~15.8%, và 75% số năm (Q3) có ROE dưới 17.3%.

  • Các chấm đó chính là 11 điểm dữ liệu (11 năm) thực tế

    • Cụm đáy (Khủng hoảng): thấy rõ 5 chấm dữ liệu (tương ứng 5 năm 2015, 2016, 2017, 2018, 2019) bị nén chặt và xếp chồng lên nhau ở mức gần 0%. Cụm chấm này chính là nguyên nhân tạo ra phần “phình” rộng ở đáy của biểu đồ violin.

    • Cụm đỉnh (Phục hồi): 5 chấm dữ liệu khác (tương ứng 2020, 2021, 2022, 2023, 2024) tụ lại ở cụm trên, trong khoảng 15% đến 25%. Cụm chấm này tạo ra phần “phình” thứ hai của violin và cũng là nơi chứa toàn bộ “hộp” boxplot (từ Q1 đến Q3).

    • Điểm biệt lập (Max): Quan trọng nhất, có một chấm đơn lẻ (năm 2014) nằm tách biệt ở đỉnh cao nhất, khoảng 37.5%. Đây chính là giá trị Max (đỉnh của râu boxplot), cho thấy năm hoạt động hoàng kim 2014 thực sự là một trường hợp đặc biệt, nằm xa hẳn so với cụm hoạt động hiệu quả (2020-2024).

  • Kết luận: Biểu đồ này trực quan hóa một cách hoàn hảo sự “phân cực” trong hiệu suất của GAS, GAS không có phân phối chuẩn, mà hoạt động ở hai ‘trạng thái’ rất rõ rệt. Doanh nghiệp này dường như chỉ hoạt động ở 2 trạng thái: “kém hiệu quả” (ROE ~ 0%) hoặc “hiệu quả cao” (ROE > 15%), chứ ít khi ở mức “trung bình” (khu vực 5-10% rất mỏng).

19. Biểu đồ Mật độ (Density plot): Phân phối Tăng trưởng Lợi nhuận (%)

# 1. Chuẩn bị dữ liệu: LỌC OUTLIER (4182.9%)
p19_data <- GAS_data_final %>%
  filter(LoiNhuan_TangTruong_YoY < 4000) # Lọc bỏ năm 2017

# 2. Vẽ biểu đồ ggplot (p19)
p19 <- ggplot(data = p19_data, aes(x = LoiNhuan_TangTruong_YoY)) +
  # Thêm biểu đồ mật độ (density plot)
  geom_density(aes(fill = "Tăng trưởng LN"), alpha = 0.6) +
  # Thêm 1 đường gạch tại giá trị 0
  geom_vline(xintercept = 0, linetype = "dashed", color = "red") +
  # Đặt tiêu đề và nhãn trục
  labs(
    title = "Biểu đồ 19: Phân phối Tăng trưởng LN (Đã lọc Outlier 2017)",
    x = "% Tăng trưởng Lợi nhuận (YoY)",
    y = "Mật độ (Density)",
    caption = "Phân tích 10 năm (2015-2024, đã lọc 1 outlier)"
  ) +
  theme_minimal() +
  theme(legend.position = "none") # Ẩn chú thích

# 3. Hiển thị biểu đồ
p19

Nhận xét Biểu đồ 19: Phân phối Tăng trưởng Lợi nhuận

(Lưu ý: Đã lọc bỏ 1 năm outlier 2017 để xem 10 năm còn lại).

  • Lệch trái: Biểu đồ mật độ cho thấy phân phối bị lệch về bên trái.

  • Đỉnh phân phối: Đỉnh cao nhất của đường mật độ (nơi tập trung nhiều năm nhất) nằm ở khoảng -25% đến 0%. Điều này trực quan hóa kết quả median_growth_ln là 0% (hoặc -4.87% nếu lọc 2014) từ 1.4.2. Đường nét đứt màu đỏ (tại 0) cho thấy phần lớn diện tích (xác suất) nằm ở vùng tăng trưởng âm.

  • Đuôi dương: Có một “cụm” nhỏ hơn ở phía bên phải, quanh mức 50-70%, đại diện cho các năm phục hồi mạnh mẽ (như 2018, 2022).

  • Kết luận: Biểu đồ này khẳng định tăng trưởng lợi nhuận của GAS là không ổn định. Một năm điển hình có xu hướng sụt giảm nhẹ, nhưng cũng có một khả năng (nhỏ hơn) là tăng trưởng bùng nổ.

20. Biểu đồ Nhiệt (Heatmap): Ma trận Tương quan (Phiên bản ggplot)

# 1. Tải thư viện để "melt" (chuyển đổi) dữ liệu
library(reshape2) 

# 2. Chuẩn bị dữ liệu:
# 2.1. Lấy dữ liệu đã lọc outlier (từ Mục 2.4.4)
data_for_cor_p20 <- GAS_data_final %>% 
  filter(TongTaiSan > 1e12) %>%
  select(-Nam, -EPS, -SL_CoPhieu_LuuHanh, -CFO) # Bỏ các cột không cần thiết

# 2.2. Tính toán ma trận
cor_matrix_p20 <- cor(data_for_cor_p20)

# 2.3. "Melt" (chuyển từ ma trận sang dạng 3 cột: Var1, Var2, value)
melted_cor_matrix <- melt(cor_matrix_p20)

# 3. Vẽ biểu đồ ggplot (p20)
p20 <- ggplot(data = melted_cor_matrix, aes(x = Var1, y = Var2, fill = value)) +
  # Sử dụng geom_tile để vẽ các ô vuông
  geom_tile() +
  # Thêm text giá trị vào giữa ô (làm tròn 2 chữ số)
  geom_text(aes(label = round(value, 2)), color = "black", size = 3) +
  # Định nghĩa thang màu: Đỏ (Âm) - Trắng (0) - Xanh (Dương)
  scale_fill_gradient2(low = "#d62728", high = "#1f77b4", mid = "white", 
                       midpoint = 0, limit = c(-1,1), name = "Tương quan") +
  # Xoay nhãn trục X 45 độ cho dễ đọc
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) +
  # Đặt tiêu đề
  labs(
    title = "Biểu đồ 20: Ma trận Tương quan (Đã lọc Outlier)"
  )

# 4. Hiển thị biểu đồ
p20

Nhận xét Biểu đồ 20: Ma trận Tương quan (Heatmap)

Biểu đồ nhiệt này là phiên bản trực quan của ma trận ở Mục 2.4.4, nhưng đã bổ sung các biến mới:

  • Màu xanh đậm (Tương quan dương mạnh > 0.7):

    • Tái khẳng định các mối quan hệ về Quy mô: TongTaiSan tương quan mạnh với VonChuSoHuu (0.97), VonHoa_TyVND (0.83), và Gia_DongCua_CuoiNam (0.83). Đây là phát hiện “Blue-chip” ở Mục 2.5.3.

    • Tái khẳng định quan hệ Lợi nhuận: LoiNhuanSauThue tương quan mạnh với ROE_Nam (0.94), ROA_Nam (0.95), và BienLoiNhuanRong_Nam (0.97).

  • Màu đỏ đậm (Tương quan âm mạnh < -0.7):

    • Phát hiện mới: TyLe_CFO_Tren_LNST (Tỷ lệ chuyển đổi tiền) có tương quan âm rất mạnh với LoiNhuanSauThue (-0.89), ROE_Nam (-0.83), ROA_Nam (-0.88), và BienLoiNhuanRong_Nam (-0.89).

    • Giải thích: Điều này nghe có vẻ lạ nhưng hoàn toàn hợp lý. Nó có nghĩa là: trong những năm LNST thấp (như 2015-2019, là các outlier của tỷ lệ này), Tỷ lệ CFO/LNST rất cao (vô cực). Ngược lại, trong những năm LNST cao (như 2014, 2022), Tỷ lệ CFO/LNST thấp hơn (chỉ ~ 1.19 hoặc 0.85). Biểu đồ này khẳng định lại kết quả của Biểu đồ 17.

  • Màu nhạt (Tương quan yếu):

    • Tái khẳng định: ROE_Nam (hiệu quả) có tương quan yếu với Gia_DongCua_CuoiNam (0.28) và VonHoa_TyVND (0.29).

    • Tái khẳng định: TySoNo_Tren_VCSH (đòn bẩy) có tương quan yếu với hầu hết mọi thứ, xác nhận Biểu đồ 10.

2.6. LƯỢC KHẢO CÁC NGHIÊN CỨU TRƯỚC

Việc phân tích các yếu tố ảnh hưởng đến giá cổ phiếu, đặc biệt trong ngành năng lượng tại các thị trường mới nổi như Việt Nam, đã thu hút sự quan tâm của nhiều nhà nghiên cứu. Một số phát hiện chính từ các nghiên cứu trước bao gồm:

  1. Vai trò của các Yếu tố Vĩ mô: Nhiều nghiên cứu (ví dụ: Nhu Quynh & Huong Linh, 2019; IOSR Journal, 2024) khẳng định các yếu tố vĩ mô như giá dầu thô thế giới, tỷ giá hối đoái, lãi suất, và lạm phát (CPI) có tác động mạnh mẽ đến giá cổ phiếu ngành năng lượng Việt Nam. Cụ thể, giá dầu thường có tác động cùng chiều (nghiên cứu của Scholar DLU, 2023) hoặc ngược chiều (nghiên cứu của Nguyet & Thao, 2013, trích dẫn trong IOSR Journal) tùy thuộc vào vị thế nhập/xuất khẩu ròng của doanh nghiệp và cả nền kinh tế. Sự biến động của các yếu tố vĩ mô này giải thích phần lớn tính chu kỳ và rủi ro cao của ngành.

  2. Yếu tố Nội tại Doanh nghiệp: Bên cạnh các yếu tố vĩ mô, các yếu tố nội tại cũng đóng vai trò quan trọng:

  • Hiệu quả Sinh lời (EPS, ROA): Các nghiên cứu (ví dụ: Scholar DLU, 2023; IOSR Journal, 2024; AB Academies, 2021) đều nhất quán tìm thấy mối tương quan dương giữa Thu nhập trên mỗi cổ phiếu (EPS) và Tỷ suất sinh lời trên tài sản (ROA) với giá cổ phiếu. Điều này phù hợp với lý thuyết tài chính cơ bản: doanh nghiệp làm ăn hiệu quả hơn thì giá cổ phiếu cao hơn.

  • Quy mô Doanh nghiệp (SIZE): Yếu tố quy mô (thường đo bằng Logarit của Tổng Tài sản) cũng được xác định là có tác động dương đến giá cổ phiếu (Scholar DLU, 2023; IOSR Journal, 2024). Các công ty lớn hơn thường được thị trường định giá cao hơn.

  • Đòn bẩy Tài chính (DE - Debt/Equity): Kết quả về đòn bẩy không nhất quán. Nghiên cứu của Scholar DLU (2023) tìm thấy tác động ngược chiều (nợ cao, giá thấp hơn do rủi ro), trong khi nghiên cứu của IOSR Journal (2024) lại tìm thấy tác động cùng chiều (có thể do hiệu ứng lá chắn thuế hoặc tín hiệu về tiềm năng tăng trưởng).

  1. Mô hình Định giá (P/E vs. P/B): Mặc dù EPS (và do đó là P/E) có ảnh hưởng đến giá, một số phân tích (ví dụ: Yuanta Việt Nam, 2023; Investing.com VN, 2024 - dù cho ngành ngân hàng) cho rằng chỉ số Giá trên Giá trị Sổ sách (P/B - Price To Book Value) cũng là một yếu tố định giá quan trọng, đặc biệt đối với các doanh nghiệp có tài sản lớn hoặc trong giai đoạn thị trường bất định. P/B phản ánh giá thị trường đang trả cho mỗi đồng vốn chủ sở hữu ghi trên sổ sách.

2.7. THẢO LUẬN KẾT QUẢ

Kết quả phân tích dữ liệu khám phá (EDA) trong Mục 2.4 và 2.5 cung cấp những bằng chứng thực nghiệm thú vị khi so sánh với các nghiên cứu trước:

  1. Xác nhận Tính chu kỳ và Ảnh hưởng Vĩ mô:
  • Phân tích Biểu đồ 1, 3, 6, 9 đã cho thấy sự biến động cực kỳ mạnh mẽ của Lợi nhuận, ROE, và Biên Lợi nhuận, đặc biệt là sự sụp đổ trong giai đoạn 2015-2019. Điều này hoàn toàn phù hợp với các nghiên cứu trước về tác động của các yếu tố vĩ mô (đặc biệt là giá dầu) lên ngành năng lượng. Mặc dù không trực tiếp phân tích các biến vĩ mô, sự biến động dữ dội của kết quả kinh doanh GAS là bằng chứng gián tiếp cho thấy sự phụ thuộc lớn vào các yếu tố này.
  1. Phát hiện “Bất thường” về Mối quan hệ Hiệu quả - Giá:
  • Trái ngược với đa số nghiên cứu trước (khẳng định EPSROA/ROE ảnh hưởng dương đến giá), phân tích TRÊN lại tìm thấy mối tương quan khá yếu giữa LoiNhuanSauThue (cor=0.50, Biểu đồ 11) và đặc biệt là ROE_Nam (cor=0.28, Biểu đồ 12) với Gia_DongCua_CuoiNam.

  • Lý giải: Sự khác biệt này có thể đến từ: (1) Đặc thù của GAS là một doanh nghiệp Nhà nước lớn, Blue-chip, khiến cách định giá khác biệt; (2) Giai đoạn phân tích (2014-2024) bao gồm nhiều năm khủng hoảng (LNST~0), làm “nhiễu” mối quan hệ này; (3) Các yếu tố vĩ mô (giá dầu) có thể đã lấn át tác động của hiệu quả nội tại trong giai đoạn này.

  1. Xác nhận Mạnh mẽ về Vai trò của Quy mô (Định giá Blue-chip):
  • Phát hiện quan trọng nhất là mối tương quan cực kỳ mạnh (cor=0.83) giữa TongTaiSanGia_DongCua_CuoiNam/VonHoa_TyVND (Biểu đồ 13).

  • Điều này hoàn toàn ủng hộ các nghiên cứu trước về tác động dương của Quy mô (SIZE) lên giá cổ phiếu (Scholar DLU, 2023; IOSR Journal, 2024) và cũng gián tiếp ủng hộ các phân tích nhấn mạnh vai trò của P/B (Giá trị Sổ sách - Book Value, liên quan đến Tài sản và Vốn chủ) trong định giá các doanh nghiệp lớn, ổn định tại Việt Nam. Kết quả của chúng ta cho thấy thị trường định giá GAS như một cổ phiếu “Blue-chip” dựa trên quy mô tài sản.

  1. Về đòn bẩy tài chính:
  • Phân tích biểu đồ 10, Ma trận Tương quan 2.4.4 tìm thấy mối tương quan rất yếu giữa TySoNo_Tren_VCSHROE_Nam (cor=0.15). Điều này dường như không ủng hộ mạnh mẽ cả hai luồng ý kiến (âm hoặc dương) từ các nghiên cứu trước.

  • Lý giải: Có thể là do GAS luôn duy trì đòn bẩy ở mức rất thấp (mean=0.36), khiến cho sự thay đổi nhỏ trong tỷ lệ nợ không đủ để tạo ra tác động đáng kể lên ROE.

  1. Về chất lượng lợi nhuận:
  • Phát hiện về chất lượng lợi nhuận cao (median CFO/LNST = 1.19, Biểu đồ 17) là một điểm cộng quan trọng cho GAS, cho thấy lợi nhuận kế toán được chuyển đổi hiệu quả thành tiền mặt. Đây là một yếu tố thường được các nhà đầu tư giá trị quan tâm.

Kết luận thảo luận: Phân tích EDA cung cấp những góc nhìn thực tế và sâu sắc về GAS. Mặc dù có những điểm tương đồng với các nghiên cứu trước (tính chu kỳ, vai trò của quy mô), phát hiện về mối quan hệ yếu giữa hiệu quả sinh lời và giá cổ phiếu là một điểm khác biệt quan trọng, nhấn mạnh đặc thù định giá của một cổ phiếu Blue-chip như GAS trên thị trường Việt Nam.

2.8 KẾT LUẬN

2.8.1. Tóm tắt các Phát hiện Chính

  1. Đặc điểm Kinh doanh - Blue-chip Chu kỳ:
  • GAS thể hiện rõ đặc điểm của một cổ phiếu “Blue-chip”: quy mô tài sản lớn, cấu trúc tài chính cực kỳ an toàn (đòn bẩy thấp, mean_tsn_vcsh = 0.36), và tăng trưởng quy mô chủ yếu dựa vào vốn chủ sở hữu.

  • Tuy nhiên, hiệu quả hoạt động kinh doanh (Lợi nhuận, ROE, Biên LN ròng) lại mang tính chu kỳ rất cao, biến động mạnh mẽ và phụ thuộc lớn vào các yếu tố vĩ mô (như giá dầu). Phân tích phân phối cho thấy ROE hoạt động ở hai trạng thái rõ rệt: “kém hiệu quả” (ROE ~0%) trong giai đoạn 2015-2019 và “hiệu quả cao” (ROE > 15%) trong giai đoạn còn lại.

  • Mặc dù lợi nhuận biến động, chất lượng lợi nhuận của GAS (khi hoạt động hiệu quả) là rất cao, thể hiện qua Tỷ lệ Chuyển đổi Tiền mặt trung vị (cash_conv_median) đạt 1.19, cho thấy khả năng chuyển đổi lợi nhuận thành dòng tiền thực tế tốt.

  1. Đặc điểm Định giá Thị trường - Định giá theo Quy mô:
  • Phát hiện quan trọng nhất và có phần khác biệt so với một số nghiên cứu trước: Thị trường chứng khoán Việt Nam trong giai đoạn 2014-2024 dường như không định giá cổ phiếu GAS dựa trên hiệu quả sinh lời (ROE, cor=0.28) hay lợi nhuận ngắn hạn (LNST, cor=0.50).

  • Thay vào đó, định giá thị trường (Giá cổ phiếu, Vốn hóa) lại có mối tương quan tuyến tính rất mạnh với Quy mô Tổng Tài sản (cor=0.83). Điều này ủng hộ các nghiên cứu về vai trò của quy mô và phù hợp với hành vi định giá cổ phiếu Blue-chip, nơi quy mô tài sản được xem là yếu tố bảo chứng cho giá trị dài hạn, bất chấp biến động lợi nhuận ngắn hạn. Sự phân kỳ giữa Vốn hóa và Lợi nhuận (Biểu đồ 14) càng củng cố nhận định này.

2.8.2. Hạn chế của phân tích

  • Vấn đề chất lượng dữ liệu: Phân tích đã phát hiện và xử lý một điểm dữ liệu ngoại lai (outlier) nghiêm trọng trong báo cáo tài chính năm 2019, nơi TongTaiSan được ghi nhận ở mức phi lý (621 tỷ VND). Việc lọc bỏ điểm dữ liệu này là cần thiết để đảm bảo tính chính xác của các phân tích liên quan đến cấu trúc vốn và tương quan.

  • Phạm vi phân tích: Nghiên cứu này chỉ tập trung vào dữ liệu tài chính nội tại và giá cổ phiếu. Việc kết hợp phân tích các yếu tố vĩ mô (giá dầu, tỷ giá, lãi suất) hoặc các yếu tố định tính (chính sách, dự án) có thể cung cấp bức tranh đầy đủ hơn.

2.8.3 Kết luận chung

  • Kết luận: GAS là một cổ phiếu Blue-chip điển hình trên thị trường Việt Nam: an toàn về mặt tài chính nhờ quy mô và cấu trúc vốn vững chắc, nhưng hiệu quả kinh doanh lại biến động mạnh theo chu kỳ ngành. Thị trường nhận thức rõ điều này và thể hiện qua việc định giá cổ phiếu dựa trên quy mô tài sản và tiềm năng dài hạn, thay vì phản ứng thái quá với lợi nhuận ngắn hạn. Chất lượng lợi nhuận cao (khả năng tạo tiền tốt) là một điểm cộng quan trọng.

  • Đề xuất:

    • Đối với Nhà đầu tư: GAS phù hợp với các nhà đầu tư dài hạn, tìm kiếm sự ổn định tương đối về giá trị tài sản và tiềm năng nhận cổ tức đều đặn (nhờ dòng tiền tốt). Tuy nhiên, nhà đầu tư cần chấp nhận sự biến động mạnh của lợi nhuận và hiệu quả sinh lời theo chu kỳ kinh tế và giá năng lượng thế giới. Việc mua vào nên cân nhắc thực hiện khi định giá P/E hoặc P/B (nếu tính thêm) ở mức thấp hơn trung bình lịch sử hoặc khi có dấu hiệu bắt đầu một chu kỳ phục hồi mới của ngành.

    • Đối với Nghiên cứu Tương lai: Các nghiên cứu tiếp theo có thể mở rộng mô hình phân tích bằng cách đưa vào các biến số vĩ mô (giá dầu, GDP, lạm phát, lãi suất) để lượng hóa tác động của các yếu tố này lên hiệu quả kinh doanh và giá cổ phiếu của GAS, hoặc so sánh mô hình định giá của GAS với các doanh nghiệp cùng ngành trong khu vực.