Hiểu rõ về định giá doanh nghiệp, sức khỏe tài chính và mức độ trưởng thành của doanh nghiệp là nền tảng của phân tích tài chính và việc ra quyết định đầu tư. Ba thước đo được sử dụng rộng rãi (chẳng hạn Q của Tobin, điểm Z của Altman và tuổi công ty) phản ánh những khía cạnh khác nhau nhưng bổ sung cho nhau về vị thế kinh tế của doanh nghiệp. Q của Tobin phản ánh đánh giá của thị trường về giá trị doanh nghiệp so với cơ sở tài sản của nó, điểm Z của Altman dự báo khả năng xảy ra kiệt quệ tài chính, còn tuổi công ty là đại diện cho mức độ trưởng thành về tổ chức và sự ổn định hoạt động.
Mặc dù các thước đo này đã được nghiên cứu rộng rãi ở các thị trường phát triển, đặc biệt là Hoa Kỳ (xem Lindenberg và Ross 1981; Altman 1968; Gompers, Ishii, và Metrick 2003), việc áp dụng chúng ở các thị trường mới nổi như Việt Nam đặt ra những thách thức và cơ hội riêng. Thị trường chứng khoán Việt Nam tăng trưởng nhanh nhưng vẫn mang những đặc điểm cấu trúc, như mức độ tập trung sở hữu, sự chi phối của doanh nghiệp nhà nước, thị trường trái phiếu còn thiếu chiều sâu và chuẩn mực kế toán đang tiếp tục phát triển, đòi hỏi phải điều chỉnh cẩn trọng các thước đo định giá và kiệt quệ tài chính tiêu chuẩn.
29.1 Các gói cần thiết
Hiện mã
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport matplotlib.ticker as mtickerimport seaborn as snsfrom matplotlib.colors import LinearSegmentedColormapimport warningswarnings.filterwarnings("ignore")plt.rcParams.update({"figure.figsize": (10, 6),"font.size": 12,"axes.titlesize": 14,"axes.labelsize": 12,"xtick.labelsize": 10,"ytick.labelsize": 10,"legend.fontsize": 10,"figure.dpi": 150,"axes.spines.top": False,"axes.spines.right": False,})# Color palette consistent with Tidy Finance stylecolors = {"primary": "#1f77b4","secondary": "#ff7f0e","tertiary": "#2ca02c","quaternary": "#d62728","quinary": "#9467bd","safe": "#2ca02c","alert": "#ff7f0e","danger": "#d62728","distress": "#8b0000",}
30 Nền tảng lý thuyết
30.1 Q của Tobin: Giá trị thị trường của doanh nghiệp
30.1.1 Khái niệm gốc
Q của Tobin được Tobin (1969) giới thiệu như một mối liên kết lý thuyết giữa thị trường tài chính và các quyết định đầu tư thực. Ý tưởng cốt lõi rất đơn giản mà tinh tế: nếu thị trường định giá tài sản của doanh nghiệp cao hơn chi phí thay thế của chúng, doanh nghiệp có động cơ đầu tư thêm vốn mới; nếu thị trường định giá thấp hơn, doanh nghiệp không nên đầu tư, thậm chí có thể có lợi khi bán bớt tài sản.
Một cách hình thức, Q của Tobin được định nghĩa như sau:
\[
Q = \frac{\text{Market Value of the Firm}}{\text{Replacement Cost of Assets}}
\tag{30.1}\]
Khi \(Q > 1\), thị trường nhận thấy doanh nghiệp sở hữu các tài sản vô hình có giá trị, như giá trị thương hiệu, năng lực quản lý, công nghệ độc quyền hoặc cơ hội tăng trưởng, vượt quá chi phí của cơ sở tài sản hữu hình. Khi \(Q < 1\), thị trường thực chất định giá doanh nghiệp thấp hơn chi phí để xây dựng lại tài sản của nó, gợi ý khả năng bị định giá thấp hoặc sự hiện diện của chi phí đại diện và sự kém hiệu quả về tổ chức.
30.1.2 Phân rã giá trị thị trường
Tử số của Q của Tobin biểu diễn tổng giá trị thị trường của mọi quyền đòi đối với doanh nghiệp:
\[
MV = CS + PS + ST + LT
\tag{30.2}\]
trong đó:
\(CS\) = Giá trị thị trường của cổ phiếu phổ thông (số cổ phiếu đang lưu hành \(\times\) giá thị trường)
\(PS\) = Giá trị thị trường của cổ phiếu ưu đãi
\(ST\) = Giá trị thị trường của nợ ngắn hạn
\(LT\) = Giá trị thị trường của nợ dài hạn
30.1.3 Chi phí thay thế của tài sản
Mẫu số phản ánh chi phí thay thế của cơ sở tài sản của doanh nghiệp:
\(RNP\) = Chi phí thay thế của nhà xưởng và thiết bị ròng
\(HNP\) = Giá trị lịch sử (sổ sách) của nhà xưởng và thiết bị ròng
\(RINV\) = Chi phí thay thế của hàng tồn kho
\(HINV\) = Giá trị lịch sử (sổ sách) của hàng tồn kho
Việc điều chỉnh chi phí thay thế đối với nhà xưởng và thiết bị đòi hỏi các phép tính đệ quy có tính đến tỷ lệ khấu hao và, trong các ước lượng chi tiết hơn, tỷ lệ tiến bộ kỹ thuật (Lindenberg và Ross 1981). Đối với hàng tồn kho, việc điều chỉnh phụ thuộc vào phương pháp kế toán hàng tồn kho: LIFO (nhập sau, xuất trước), FIFO (nhập trước, xuất trước), giá bình quân hoặc giá bán lẻ.
30.1.4 Q của Tobin giản lược
Trong thực tế, việc tính đầy đủ chi phí thay thế đòi hỏi dữ liệu thường không có sẵn, đặc biệt ở các thị trường mới nổi. Gompers, Ishii, và Metrick (2003) phổ biến một phiên bản giản lược:
\[
Q_{\text{simple}} = \frac{TA + ME - BE}{TA}
\tag{30.4}\]
trong đó \(ME\) là giá trị thị trường của vốn chủ sở hữu và \(BE\) là giá trị sổ sách của vốn chủ sở hữu. Cách xây dựng này giả định rằng giá trị sổ sách của nợ và cổ phiếu ưu đãi xấp xỉ giá trị thị trường của chúng, và tổng tài sản xấp xỉ chi phí thay thế của cơ sở tài sản của doanh nghiệp. Dù đơn giản, thước đo này được chứng minh là tương quan tốt với các cách xây dựng phức tạp hơn và đã trở thành chuẩn mực trong nghiên cứu tài chính doanh nghiệp thực nghiệm.
30.1.5 Xấp xỉ của Chung và Pruitt
Chung và Pruitt (1994) đề xuất một phép xấp xỉ khác được sử dụng rộng rãi:
trong đó \(DEBT = \text{Current Liabilities} - \text{Current Assets} + \text{Book Value of Inventories} + \text{Long-term Debt}\). Cách xây dựng này nắm bắt vị thế nợ ròng chính xác hơn so với phiên bản của Gompers, Ishii, và Metrick (2003).
30.2 Điểm Z của Altman: Dự báo kiệt quệ tài chính
30.2.1 Mô hình gốc
Điểm Z của Altman, do Altman (1968) phát triển, là một mô hình phân tích phân biệt đa biến dự báo xác suất phá sản của doanh nghiệp trong khoảng thời gian hai năm. Mô hình ban đầu được ước lượng bằng một mẫu ghép cặp gồm các doanh nghiệp sản xuất của Hoa Kỳ đã phá sản và chưa phá sản, và có dạng:
Vùng kiệt quệ-rủi ro phá sản đáng kể trong vòng 2 năm
\(Z < 1.80\)
Kiệt quệ nghiêm trọng-xác suất thất bại tài chính rất cao
30.2.2 Mô hình điểm Z’ cho doanh nghiệp chưa niêm yết
Vì mô hình gốc dùng giá trị thị trường của vốn chủ sở hữu trong \(X_3\), Altman và Hotchkiss (2010) phát triển điểm Z’ cho các doanh nghiệp chưa niêm yết (không giao dịch công khai) bằng cách thay vốn hóa thị trường bằng giá trị sổ sách của vốn chủ sở hữu:
trong đó \(X_4' = \frac{\text{Book Value of Equity}}{\text{Total Liabilities}}\), và các biến còn lại được định nghĩa như trong mô hình gốc nhưng với các hệ số được ước lượng lại.
30.2.3 Mô hình điểm Z’’ cho thị trường mới nổi
Phù hợp nhất với Việt Nam, Altman và Hotchkiss (2010) cũng phát triển điểm Z’’ cho các doanh nghiệp phi sản xuất và doanh nghiệp ở thị trường mới nổi:
\(X_4'' = \frac{\text{Book Value of Equity}}{\text{Total Liabilities}}\)
Lưu ý rằng mô hình này loại bỏ tỷ số doanh thu/tổng tài sản (\(X_2\) trong mô hình gốc) để giảm thiểu hiệu ứng ngành và bổ sung một hệ số chặn. Các vùng phân loại được dịch chuyển tương ứng (Bảng 30.3).
Bảng 30.3: Các vùng diễn giải điểm Z’’ cho thị trường mới nổi
Khoảng điểm Z’’
Diễn giải
\(Z'' > 2.60\)
Vùng an toàn
\(1.10 \leq Z'' \leq 2.60\)
Vùng xám
\(Z'' < 1.10\)
Vùng kiệt quệ
30.3 Tuổi công ty: Đo lường mức độ trưởng thành của doanh nghiệp
Tuổi công ty phản ánh kinh nghiệm tích lũy, uy tín và vốn tổ chức của doanh nghiệp. Các doanh nghiệp lâu đời thường có hoạt động ổn định hơn, lợi thế cạnh tranh vững chắc và dòng tiền dễ dự báo (Coad và c.s. 2018). Tuổi thường được dùng làm biến kiểm soát trong nghiên cứu tài chính doanh nghiệp, và mối quan hệ của nó với hiệu quả hoạt động là mơ hồ về mặt lý thuyết: doanh nghiệp lâu đời được hưởng lợi từ hiệu ứng học hỏi và uy tín nhưng có thể chịu sự cứng nhắc về tổ chức và suy giảm đổi mới (Huergo và Jaumandreu 2004).
Thước đo lý tưởng là số năm kể từ khi thành lập. Khi không có ngày thành lập, các đại diện thông dụng gồm:
Tuổi niêm yết: Số năm kể từ lần IPO hoặc niêm yết đầu tiên trên một sở giao dịch chứng khoán.
Tuổi dữ liệu: Số năm kể từ lần xuất hiện đầu tiên trong các cơ sở dữ liệu tài chính.
Tuổi đăng ký thành lập: Số năm kể từ ngày đăng ký thành lập pháp lý.
Trong bối cảnh Việt Nam, chúng ta có thể sử dụng nhiều đại diện, bao gồm ngày niêm yết lần đầu trên HOSE hoặc HNX, ngày báo cáo tài chính đầu tiên có sẵn, và (khi có) ngày thành lập từ hồ sơ công ty.
31 Bối cảnh thị trường Việt Nam
31.1 Các đặc điểm thể chế ảnh hưởng đến thước đo định giá
Thị trường chứng khoán Việt Nam có một số đặc điểm thể chế quan trọng cần xem xét khi tính toán và diễn giải Q của Tobin, điểm Z của Altman và tuổi công ty.
31.1.1 Sở hữu nhà nước và cổ phần hóa
A significant proportion of Vietnamese listed firms are former state-owned enterprises (SOEs) that underwent equitization (cổ phần hóa). These firms often retain substantial state ownership, which can affect:
Q của Tobin: Sở hữu nhà nước có thể làm giảm Q nếu thị trường cho rằng sự can thiệp của chính phủ làm giảm hiệu quả, hoặc có thể làm tăng Q nếu các mối liên hệ với nhà nước mang lại khả năng tiếp cận ưu đãi đối với nguồn lực và hợp đồng.
Điểm Z: Các doanh nghiệp nhà nước (SOE) có thể có bảo lãnh ngầm của chính phủ làm giảm rủi ro phá sản thực tế xuống thấp hơn mức điểm Z dự báo.
Tuổi: Tuổi hoạt động thực của các SOE đã cổ phần hóa có thể vượt xa tuổi niêm yết của chúng, gây ra khó khăn trong đo lường.
31.1.2 Giới hạn sở hữu nước ngoài
Việt Nam áp đặt giới hạn sở hữu nước ngoài (FOL) đối với các công ty niêm yết, thường được giới hạn ở mức 49% đối với hầu hết các ngành (có một số ngoại lệ). Ràng buộc này có thể tạo ra phần bù giá đối với các cổ phiếu tiến gần trần FOL, có khả năng làm tăng Q của Tobin của các doanh nghiệp này (Vo 2015).
31.1.3 Chuẩn mực kế toán
Chuẩn mực Kế toán Việt Nam (VAS) khác với Chuẩn mực Báo cáo Tài chính Quốc tế (IFRS) ở một số điểm liên quan đến các thước đo của chúng ta:
Cơ sở giá gốc: VAS dựa nhiều hơn vào giá gốc, có thể khiến giá trị sổ sách lệch đáng kể so với chi phí thay thế, ảnh hưởng đến cả phép tính Q lẫn điểm Z.
Hạn chế đo lường theo giá trị hợp lý: Không như IFRS, VAS hạn chế việc đo lường theo giá trị hợp lý đối với nhiều loại tài sản, khiến các đại diện dựa trên giá trị sổ sách kém tin cậy hơn.
Phương pháp hàng tồn kho: Các doanh nghiệp Việt Nam dùng nhiều phương pháp định giá hàng tồn kho (FIFO, bình quân gia quyền), ảnh hưởng đến giá trị sổ sách của hàng tồn kho và do đó đến thành phần vốn lưu động của điểm Z.
31.1.4 Vi cấu trúc thị trường
Thị trường Việt Nam có biên độ giá hằng ngày (hiện là \(\pm\) 7% trên HOSE, \(\pm\) 10% trên HNX, \(\pm\) 15% trên UPCoM), có thể ngăn giá đạt tới giá trị cân bằng một cách nhanh chóng. Điều này có nghĩa là vốn hóa thị trường tại một thời điểm có thể không phản ánh đầy đủ thông tin sẵn có, đưa nhiễu vào các thước đo dựa trên giá trị thị trường như Q của Tobin.
32 Chuẩn bị dữ liệu
32.1 Tải và làm sạch dữ liệu báo cáo tài chính
Chúng ta bắt đầu bằng việc tải dữ liệu báo cáo tài chính hằng năm và xây dựng các biến cần thiết cho ba thước đo.
Simulate Vietnamese financial data (replace with DataCore.vn API calls)
# ============================================================================# In practice, replace this section with actual DataCore.vn API calls:## from datacore import DataCoreClient# client = DataCoreClient(api_key="your_api_key")# financials = client.get_financial_statements(# frequency="annual",# start_date="2005-01-01",# end_date="2024-12-31"# )# market = client.get_market_data(frequency="daily")# profiles = client.get_company_profiles()## For demonstration purposes, we simulate realistic Vietnamese market data.# ============================================================================np.random.seed(42)n_firms =300years =range(2008, 2025)exchanges = ["HOSE", "HNX", "UPCoM"]industries = ["Bất động sản", "Ngân hàng", "Thực phẩm & Đồ uống","Xây dựng & Vật liệu", "Công nghệ thông tin", "Bán lẻ","Dầu khí", "Thép", "Dệt may", "Dược phẩm","Điện lực", "Vận tải & Logistics", "Hóa chất","Chứng khoán", "Bảo hiểm"]# Generate firm profilesfirm_ids = [f"VN{str(i).zfill(4)}"for i inrange(1, n_firms +1)]firm_profiles = pd.DataFrame({"ticker": firm_ids,"exchange": np.random.choice(exchanges, n_firms, p=[0.5, 0.3, 0.2]),"industry": np.random.choice(industries, n_firms),"founding_year": np.random.randint(1975, 2015, n_firms),"listing_year": np.random.randint(2000, 2020, n_firms),"state_ownership_pct": np.clip( np.random.beta(2, 5, n_firms) *100, 0, 75 ).round(1),})firm_profiles["listing_year"] = np.maximum( firm_profiles["listing_year"], firm_profiles["founding_year"] +1)# Generate panel datarecords = []for _, firm in firm_profiles.iterrows(): start_year =max(firm["listing_year"], 2008)# Base financial characteristics (firm fixed effects) base_ta = np.exp(np.random.normal(14, 1.5)) # Total assets in VND millions base_profitability = np.random.normal(0.08, 0.05) base_leverage = np.random.beta(3, 3) base_turnover = np.random.gamma(2, 0.4)for year in years:if year < start_year:continueif np.random.random() <0.02: # 2% chance of delistingbreak# Time-varying components with persistence shock = np.random.normal(0, 0.15) growth = np.random.normal(0.08, 0.05) ta = base_ta * (1+ growth) ** (year - start_year) * np.exp(shock) profitability = np.clip(base_profitability + np.random.normal(0, 0.03), -0.3, 0.5) leverage = np.clip(base_leverage + np.random.normal(0, 0.05), 0.05, 0.95) lt = ta * leverage * np.random.uniform(0.4, 0.7) total_liabilities = ta * leverage ct_liabilities = total_liabilities - lt seq = ta * (1- leverage) sale = ta * np.clip(base_turnover + np.random.normal(0, 0.1), 0.1, 5) ebit = ta * profitability ni = ebit * np.random.uniform(0.6, 0.9) re = seq * np.random.uniform(-0.2, 0.8) act = ta * np.random.uniform(0.2, 0.7) lct = ct_liabilities# Market value with noise and sentiment market_premium = np.random.lognormal(0, 0.4) me = seq * market_premium prcc = me /max(np.random.uniform(50, 500), 1) csho = me /max(prcc, 0.01)# Preferred stock (rare in Vietnam, mostly zero) pstk =0if np.random.random() >0.05else seq * np.random.uniform(0, 0.1)# Net plant and equipment ppent = ta * np.random.uniform(0.1, 0.6) invt = ta * np.random.uniform(0.05, 0.3)# Deferred taxes and investment tax credit (typically small in VN) txdb = ta * np.random.uniform(0, 0.02) itcb =0 records.append({"ticker": firm["ticker"],"year": year,"datadate": pd.Timestamp(year, 12, 31),"at": ta, # Total Assets"seq": seq, # Stockholders' Equity"lt": lt, # Long-term Debt"lct": lct, # Current Liabilities"tlb": total_liabilities, # Total Liabilities"sale": sale, # Net Sales/Revenue"ebit": ebit, # EBIT"ni": ni, # Net Income"re_var": re, # Retained Earnings"act": act, # Current Assets"ppent": ppent, # Net Plant & Equipment"invt": invt, # Inventories"txdb": txdb, # Deferred Taxes"itcb": itcb, # Investment Tax Credit"pstk": pstk, # Preferred Stock"me": me, # Market Value of Equity"prcc": prcc, # Price at Calendar Year End"csho": csho, # Shares Outstanding })df = pd.DataFrame(records)df = df.merge(firm_profiles[["ticker", "exchange", "industry","founding_year", "listing_year","state_ownership_pct"]], on="ticker", how="left")print(f"Panel dimensions: {df.shape[0]:,} firm-year observations")print(f"Number of unique firms: {df['ticker'].nunique()}")print(f"Year range: {df['year'].min()}–{df['year'].max()}")print(f"Exchanges: {df['exchange'].value_counts().to_dict()}")
Panel dimensions: 3,484 firm-year observations
Number of unique firms: 297
Year range: 2008–2024
Exchanges: {'HOSE': 1701, 'HNX': 1118, 'UPCoM': 665}
32.2 Định nghĩa biến và ánh xạ
Bảng 32.1 trình bày ánh xạ giữa tên biến chuẩn và các trường tương ứng.
Theo Daniel và Titman (1997), chúng ta tính giá trị sổ sách của vốn chủ sở hữu như sau:
\[
BE = SEQ + TXDB + ITCB - PREF
\tag{33.1}\]
trong đó \(PREF\) là giá trị cổ phiếu ưu đãi, sử dụng giá trị hoàn lại nếu có, nếu không thì dùng giá trị thanh lý, và sau cùng là giá trị ghi sổ như phương án dự phòng cuối cùng. Trong bối cảnh Việt Nam, cổ phiếu ưu đãi tương đối hiếm trong các công ty niêm yết, nên \(PREF\) thường bằng không.
Book value of equity computation
def compute_book_equity(df):""" Compute book value of equity following Daniel and Titman (1997). In Vietnam, preferred stock is uncommon among listed firms. The investment tax credit (ITCB) is not applicable under VAS, so we set it to zero when missing. """ result = df.copy()# Preferred stock: use coalesce logic result["pref"] = result["pstk"].fillna(0)# Book equity = Shareholders' equity + Deferred taxes + ITC - Preferred result["be"] = ( result["seq"]+ result["txdb"].fillna(0)+ result["itcb"].fillna(0)- result["pref"] )return resultdf_clean = compute_book_equity(df_clean)print("Book Equity Summary Statistics (VND millions)")print(df_clean["be"].describe().apply(lambda x: f"{x:,.0f}"))
Book Equity Summary Statistics (VND millions)
count 3,484
mean 3,521,607
std 9,055,435
min 4,633
25% 386,441
50% 1,112,062
75% 3,210,269
max 247,845,397
Name: be, dtype: str
33.2 Giá trị thị trường của vốn chủ sở hữu
Giá trị thị trường của vốn chủ sở hữu được tính bằng giá cổ phiếu cuối năm dương lịch và số cổ phiếu đang lưu hành:
\[
ME = P_{\text{close}} \times \text{CSHO}
\tag{33.2}\]
Đối với các doanh nghiệp Việt Nam, giá trị này lấy từ giá đóng cửa vào ngày giao dịch cuối cùng của năm tài chính. Hầu hết doanh nghiệp Việt Nam kết thúc năm tài chính vào ngày 31 tháng 12, dù một số (đặc biệt trong nông nghiệp và ngân hàng) có thể khác.
Market value of equity computation
# ME is already computed in our simulated data as prcc * csho# In practice with DataCore.vn:# me = df["gia_dong_cua_cuoi_nam"] * df["so_luong_co_phieu_luu_hanh"]df_clean["me"] = df_clean["prcc"] * df_clean["csho"]print("Market Equity Summary Statistics (VND millions)")print(df_clean["me"].describe().apply(lambda x: f"{x:,.0f}"))
Market Equity Summary Statistics (VND millions)
count 3,484
mean 3,653,445
std 9,747,318
min 3,379
25% 370,119
50% 1,106,646
75% 3,029,093
max 286,258,816
Name: me, dtype: str
33.3 Q của Tobin giản lược
Chúng ta triển khai phiên bản giản lược của Gompers, Ishii, và Metrick (2003):
\[
Q_{\text{simple}} = \frac{AT + ME - BE}{AT}
\tag{33.3}\]
giúp cách diễn giải trở nên rõ ràng: Q của Tobin bằng một cộng với phần bù (hoặc chiết khấu) giữa giá trị thị trường và giá trị sổ sách, chia cho tổng tài sản.
33.4 Áp dụng winsorization cho các giá trị cực đoan
Giá trị Q của Tobin có thể bị ảnh hưởng nặng bởi các giá trị ngoại lai, đặc biệt ở các thị trường mới nổi nơi chất lượng dữ liệu có thể không đồng đều. Chúng ta thực hiện winsorization tại phân vị thứ 1 và thứ 99.
Winsorization of extreme values
def winsorize(series, lower=0.01, upper=0.99):"""Winsorize a pandas Series at specified percentiles.""" low = series.quantile(lower) high = series.quantile(upper)return series.clip(lower=low, upper=high)# Winsorize Q measuresfor var in ["tobin_q_simple", "tobin_q_cp", "mtb"]: df_clean[f"{var}_w"] = winsorize(df_clean[var])print("Effect of Winsorization on Simple Tobin's Q:")print(f" Before: mean={df_clean['tobin_q_simple'].mean():.3f}, "f"std={df_clean['tobin_q_simple'].std():.3f}")print(f" After: mean={df_clean['tobin_q_simple_w'].mean():.3f}, "f"std={df_clean['tobin_q_simple_w'].std():.3f}")
Effect of Winsorization on Simple Tobin's Q:
Before: mean=1.031, std=0.243
After: mean=1.030, std=0.233
33.5 Phân phối chéo của Q của Tobin
Hiện mã
fig, axes = plt.subplots(1, 2, figsize=(14, 5))# Latest year distributionlatest_year = df_clean["year"].max()latest_data = df_clean[df_clean["year"] == latest_year]# Histogramaxes[0].hist( latest_data["tobin_q_simple_w"].dropna(), bins=50, color=colors["primary"], alpha=0.7, edgecolor="white")axes[0].axvline(x=1, color=colors["quaternary"], linestyle="--", linewidth=2, label="Q = 1")axes[0].set_xlabel("Tobin's Q (Simple)")axes[0].set_ylabel("Number of Firms")axes[0].set_title(f"Cross-Sectional Distribution ({latest_year})")axes[0].legend()# Box plot by exchangeexchange_data = latest_data[["exchange", "tobin_q_simple_w"]].dropna()exchanges_sorted = exchange_data.groupby("exchange")["tobin_q_simple_w"].median().sort_values().indexbox_data = [exchange_data[exchange_data["exchange"] == ex]["tobin_q_simple_w"].valuesfor ex in exchanges_sorted]bp = axes[1].boxplot(box_data, labels=exchanges_sorted, patch_artist=True, medianprops=dict(color="black", linewidth=2))box_colors = [colors["primary"], colors["secondary"], colors["tertiary"]]for patch, color inzip(bp["boxes"], box_colors): patch.set_facecolor(color) patch.set_alpha(0.7)axes[1].axhline(y=1, color=colors["quaternary"], linestyle="--", linewidth=1.5, alpha=0.7)axes[1].set_ylabel("Tobin's Q (Simple)")axes[1].set_title(f"Tobin's Q by Exchange ({latest_year})")plt.tight_layout()plt.show()
Hình 33.1: Phân phối của Q của Tobin trên các doanh nghiệp niêm yết Việt Nam (2024). Đường nét đứt thẳng đứng tại Q=1 biểu thị ngưỡng lý thuyết mà tại đó giá trị thị trường bằng chi phí thay thế.
Hình 34.1: Phân phối các tỷ số thành phần của điểm Z của Altman đối với các doanh nghiệp niêm yết Việt Nam. Mỗi biểu đồ con thể hiện một thành phần được gia quyền theo hệ số của nó trong công thức điểm Z gốc.
34.3 Phân phối các vùng rủi ro
Hiện mã
fig, axes = plt.subplots(1, 2, figsize=(14, 6))# --- Original Z-Score Zones ---zone_counts = ( df_clean .groupby(["year", "z_zone"]) .size() .unstack(fill_value=0))zone_pcts = zone_counts.div(zone_counts.sum(axis=1), axis=0) *100zone_colors = {"Safe": colors["safe"],"Grey Zone": colors["alert"],"Distress": colors["quaternary"],"High Distress": colors["distress"],}axes[0].stackplot( zone_pcts.index,*[zone_pcts[col] for col in ["Safe", "Grey Zone", "Distress", "High Distress"]if col in zone_pcts.columns], labels=[col for col in ["Safe", "Grey Zone", "Distress", "High Distress"]if col in zone_pcts.columns], colors=[zone_colors[col] for col in ["Safe", "Grey Zone", "Distress", "High Distress"]if col in zone_pcts.columns], alpha=0.8)axes[0].set_xlabel("Year")axes[0].set_ylabel("Percentage of Firms")axes[0].set_title("Original Z-Score Risk Zones")axes[0].legend(loc="upper right", fontsize=9)axes[0].set_ylim(0, 100)# --- Emerging Market Z''-Score Zones ---em_zone_counts = ( df_clean .groupby(["year", "z_em_zone"]) .size() .unstack(fill_value=0))em_zone_pcts = em_zone_counts.div(em_zone_counts.sum(axis=1), axis=0) *100em_zone_colors = {"Safe": colors["safe"], "Grey Zone": colors["alert"],"Distress": colors["quaternary"]}axes[1].stackplot( em_zone_pcts.index,*[em_zone_pcts[col] for col in ["Safe", "Grey Zone", "Distress"]if col in em_zone_pcts.columns], labels=[col for col in ["Safe", "Grey Zone", "Distress"]if col in em_zone_pcts.columns], colors=[em_zone_colors[col] for col in ["Safe", "Grey Zone", "Distress"]if col in em_zone_pcts.columns], alpha=0.8)axes[1].set_xlabel("Year")axes[1].set_ylabel("Percentage of Firms")axes[1].set_title("Emerging Market Z''-Score Risk Zones")axes[1].legend(loc="upper right", fontsize=9)axes[1].set_ylim(0, 100)plt.tight_layout()plt.show()
Hình 34.2: Tỷ lệ các doanh nghiệp niêm yết Việt Nam trong từng vùng rủi ro của điểm Z của Altman theo thời gian. Hình thể hiện cả các vùng điểm Z gốc và các vùng điểm Z’’ cho thị trường mới nổi.
34.4 So sánh các biến thể của điểm Z
Một câu hỏi thực tiễn quan trọng là biến thể điểm Z nào phù hợp nhất với các doanh nghiệp Việt Nam. Mô hình gốc được hiệu chỉnh trên các doanh nghiệp sản xuất của Hoa Kỳ, trong khi điểm Z’’ được thiết kế riêng cho thị trường mới nổi và các ngành phi sản xuất.
Hình 34.3: So sánh điểm Z gốc và điểm Z’’ cho thị trường mới nổi đối với các doanh nghiệp niêm yết Việt Nam. Các điểm nằm trên (dưới) đường 45 độ có điểm Z’’ (điểm Z) cao hơn thước đo còn lại.
35 Tính tuổi công ty
35.1 Nhiều đại diện cho tuổi
Đối với các doanh nghiệp Việt Nam, chúng ta tính ba thước đo tuổi:
\[
\text{Age}_{\text{data}} = \text{Current Year} - \text{First Year with Data}
\tag{35.3}\]
Company age computation with multiple proxies
def compute_company_age(df):""" Compute multiple proxies for company age. For Vietnamese firms: - Founding age: based on founding/incorporation date - Listing age: based on first listing on HOSE/HNX/UPCoM - Data age: based on first year with available financial data """ result = df.copy()# Founding age result["age_founding"] = result["year"] - result["founding_year"]# Listing age result["age_listing"] = result["year"] - result["listing_year"] result["age_listing"] = result["age_listing"].clip(lower=0)# Data age (years since first available financial data) first_year = result.groupby("ticker")["year"].transform("min") result["age_data"] = result["year"] - first_year# Log of age (commonly used in regressions) result["ln_age_founding"] = np.log1p(result["age_founding"]) result["ln_age_listing"] = np.log1p(result["age_listing"])return resultdf_clean = compute_company_age(df_clean)print("Company Age Summary Statistics")age_summary = df_clean[df_clean["year"] == latest_year][ ["age_founding", "age_listing", "age_data"]].describe().round(1)age_summary.columns = ["Founding Age", "Listing Age", "Data Age"]print(age_summary.to_string())
Company Age Summary Statistics
Founding Age Listing Age Data Age
count 232.0 232.0 232.0
mean 30.1 13.9 12.3
std 11.6 5.8 3.9
min 10.0 5.0 5.0
25% 20.0 9.0 9.0
50% 30.0 13.0 13.0
75% 40.0 19.0 16.0
max 49.0 24.0 16.0
Hình 35.1: Phân phối các thước đo tuổi công ty đối với các doanh nghiệp niêm yết Việt Nam. Tuổi thành lập phản ánh mức độ trưởng thành thực sự của tổ chức, trong khi tuổi niêm yết phản ánh kinh nghiệm trên thị trường vốn.
35.3 Tuổi và hiệu ứng cổ phần hóa
Một đặc điểm riêng của thị trường Việt Nam là việc cổ phần hóa các SOE. Nhiều doanh nghiệp có ngày thành lập sớm hơn thị trường chứng khoán hàng chục năm, tạo ra khoảng cách lớn giữa tuổi thành lập và tuổi niêm yết.
Hình 35.2: Mối quan hệ giữa tuổi thành lập và tuổi niêm yết của các doanh nghiệp Việt Nam. Khoảng cách phản ánh số năm hoạt động trước khi niêm yết, đặc biệt lớn đối với các doanh nghiệp nhà nước đã cổ phần hóa.
36 Phân tích kết hợp: Định giá, kiệt quệ và mức độ trưởng thành
36.1 Mối quan hệ giữa Q, điểm Z và tuổi
Ba thước đo này phản ánh những khía cạnh khác nhau về vị thế tài chính của doanh nghiệp, nhưng chúng không độc lập với nhau. Về mặt lý thuyết, chúng ta kỳ vọng:
Q và Z: Các doanh nghiệp có nhiều cơ hội tăng trưởng (Q cao) thường khỏe mạnh hơn về tài chính (Z cao), nhưng mối quan hệ không đơn điệu, giá trị Q rất cao có thể cho thấy sự định giá quá cao mang tính đầu cơ.
Q và tuổi: Các doanh nghiệp trẻ có thể có Q cao hơn (kỳ vọng tăng trưởng) hoặc thấp hơn (mô hình kinh doanh chưa được kiểm chứng). Mối quan hệ phụ thuộc vào vòng đời của ngành.
Z và tuổi: Các doanh nghiệp lâu đời thường có lợi nhuận ổn định hơn và lợi nhuận giữ lại cao hơn, góp phần làm điểm Z cao hơn, dù các doanh nghiệp rất lâu đời có thể đối mặt với năng lực cạnh tranh suy giảm.
Hiện mã
fig, axes = plt.subplots(1, 3, figsize=(16, 5))sample = latest.dropna(subset=["tobin_q_simple_w", "altman_z_w", "age_founding"])sample = sample.sample(min(300, len(sample)), random_state=42)# Q vs Zaxes[0].scatter( sample["altman_z_w"], sample["tobin_q_simple_w"], c=sample["age_founding"], cmap="viridis", alpha=0.6, s=np.log1p(sample["at"]) *3, edgecolor="white", linewidth=0.3)axes[0].set_xlabel("Altman Z-Score")axes[0].set_ylabel("Tobin's Q")axes[0].set_title("Valuation vs. Distress Risk")axes[0].axhline(y=1, color="gray", linestyle="--", alpha=0.5)axes[0].axvline(x=1.80, color="red", linestyle=":", alpha=0.5)axes[0].axvline(x=2.99, color="green", linestyle=":", alpha=0.5)# Q vs Ageaxes[1].scatter( sample["age_founding"], sample["tobin_q_simple_w"], c=sample["altman_z_w"], cmap="RdYlGn", alpha=0.6, s=np.log1p(sample["at"]) *3, edgecolor="white", linewidth=0.3)axes[1].set_xlabel("Founding Age (years)")axes[1].set_ylabel("Tobin's Q")axes[1].set_title("Valuation vs. Maturity")axes[1].axhline(y=1, color="gray", linestyle="--", alpha=0.5)# Z vs Agescatter = axes[2].scatter( sample["age_founding"], sample["altman_z_w"], c=sample["tobin_q_simple_w"], cmap="coolwarm", alpha=0.6, s=np.log1p(sample["at"]) *3, edgecolor="white", linewidth=0.3)axes[2].set_xlabel("Founding Age (years)")axes[2].set_ylabel("Altman Z-Score")axes[2].set_title("Distress Risk vs. Maturity")axes[2].axhline(y=1.80, color="red", linestyle=":", alpha=0.5)axes[2].axhline(y=2.99, color="green", linestyle=":", alpha=0.5)plt.tight_layout()plt.show()
Hình 36.1: Mối quan hệ giữa Q của Tobin, điểm Z của Altman và tuổi công ty đối với các doanh nghiệp niêm yết Việt Nam. Kích thước bong bóng phản ánh tổng tài sản; màu sắc cho biết vùng rủi ro điểm Z’’ cho thị trường mới nổi.
Ở đây chúng tôi cung cấp một hàm gọn gàng duy nhất nhận dữ liệu tài chính thô từ DataCore.vn và tạo ra bộ dữ liệu hoàn chỉnh với cả ba thước đo đã được tính.
Complete pipeline for computing Tobin’s Q, Z-Score, and Company Age
def compute_valuation_distress_age(df, firm_profiles=None):""" Complete pipeline to compute Tobin's Q, Altman Z-Score variants, and Company Age for Vietnamese listed firms. Parameters ---------- df : pd.DataFrame Panel of firm-year financial data with columns: at, seq, lt, lct, tlb, sale, ebit, ni, re_var, act, ppent, invt, txdb, itcb, pstk, me, prcc, csho, year, ticker firm_profiles : pd.DataFrame, optional Company profiles with founding_year, listing_year Returns ------- pd.DataFrame Input data augmented with computed measures """ result = df.copy()# === Data Quality Filters === result = result[result["at"] >0] result = result[result["seq"] >0]# === Book Value of Equity (Daniel & Titman 1997) === result["pref"] = result["pstk"].fillna(0) result["be"] = ( result["seq"]+ result["txdb"].fillna(0)+ result["itcb"].fillna(0)- result["pref"] )# === Market Value of Equity ===if"me"notin result.columns or result["me"].isna().all(): result["me"] = result["prcc"] * result["csho"]# === Tobin's Q Variants ===# Simple Q (Gompers et al. 2003) result["tobin_q"] = (result["at"] + result["me"] - result["be"]) / result["at"]# Chung-Pruitt Q debt_cp = ( result["lct"].fillna(0) - result["act"].fillna(0)+ result["invt"].fillna(0) + result["lt"].fillna(0) ) result["tobin_q_cp"] = ( (result["me"] + result["pstk"].fillna(0) + debt_cp) / result["at"] )# Market-to-Book result["mtb"] = np.where(result["be"] >0, result["me"] / result["be"], np.nan)# === Altman Z-Score Variants === result["wc"] = result["act"].fillna(0) - result["lct"].fillna(0) x1 = result["ebit"] / result["at"] x2 = result["sale"] / result["at"] x3_market = np.where(result["tlb"] >0, result["me"] / result["tlb"], np.nan) x3_book = np.where(result["tlb"] >0, result["be"] / result["tlb"], np.nan) x4 = result["wc"] / result["at"] x5 = result["re_var"].fillna(0) / result["at"]# Original Z result["altman_z"] =3.3* x1 +0.999* x2 +0.6* x3_market +1.2* x4 +1.4* x5# Z' (private firms) result["altman_z_prime"] = (0.717* x4 +0.847* x5 +3.107* x1 +0.420* x3_book +0.998* x2 )# Z'' (emerging markets) result["altman_z_em"] = (3.25+6.56* x4 +3.26* x5 +6.72* x1 +1.05* x3_book )# Risk zones result["z_zone"] = pd.cut( result["altman_z"], bins=[-np.inf, 1.80, 2.70, 2.99, np.inf], labels=["High Distress", "Distress", "Grey Zone", "Safe"] ) result["z_em_zone"] = pd.cut( result["altman_z_em"], bins=[-np.inf, 1.10, 2.60, np.inf], labels=["Distress", "Grey Zone", "Safe"] )# === Company Age ===if firm_profiles isnotNone: result = result.merge( firm_profiles[["ticker", "founding_year", "listing_year"]], on="ticker", how="left", suffixes=("", "_profile") ) result["age_founding"] = result["year"] - result["founding_year"] result["age_listing"] = (result["year"] - result["listing_year"]).clip(lower=0) first_year = result.groupby("ticker")["year"].transform("min") result["age_data"] = result["year"] - first_year# === Winsorize ===for var in ["tobin_q", "tobin_q_cp", "mtb", "altman_z", "altman_z_prime", "altman_z_em"]:if var in result.columns: result[f"{var}_w"] = winsorize(result[var])return result# Demonstrate the pipelinefinal_df = compute_valuation_distress_age(df, firm_profiles)print(f"Final dataset: {final_df.shape[0]:,} observations, {final_df.shape[1]} variables")print(f"Firms: {final_df['ticker'].nunique()}")print(f"\nKey variables computed:")for var in ["tobin_q", "tobin_q_cp", "mtb", "altman_z", "altman_z_prime","altman_z_em", "age_founding", "age_listing", "age_data"]:if var in final_df.columns: non_null = final_df[var].notna().sum()print(f" {var}: {non_null:,} non-null values")
Sở hữu nhà nước là đặc điểm nổi bật của bức tranh doanh nghiệp Việt Nam. Chúng ta xem xét sở hữu nhà nước ảnh hưởng thế nào đến cả Q của Tobin lẫn rủi ro kiệt quệ tài chính.
Hiện mã
fig, axes = plt.subplots(1, 2, figsize=(14, 6))latest = final_df[final_df["year"] == latest_year].dropna( subset=["tobin_q_w", "altman_z_em_w", "state_ownership_pct"])# Q vs State Ownershipaxes[0].scatter( latest["state_ownership_pct"], latest["tobin_q_w"], alpha=0.4, s=20, color=colors["primary"], edgecolor="white")# Binned meansbins = pd.cut(latest["state_ownership_pct"], bins=10)binned = latest.groupby(bins)["tobin_q_w"].mean()bin_centers = [(b.left + b.right) /2for b in binned.index]axes[0].plot(bin_centers, binned.values, color=colors["quaternary"], linewidth=3, label="Binned Mean")axes[0].set_xlabel("State Ownership (%)")axes[0].set_ylabel("Tobin's Q")axes[0].set_title("State Ownership and Firm Valuation")axes[0].axhline(y=1, color="gray", linestyle="--", alpha=0.5)axes[0].legend()# Z''-Score by SOE quartilelatest["soe_quartile"] = pd.qcut( latest["state_ownership_pct"], q=4, labels=["Q1 (Low)", "Q2", "Q3", "Q4 (High)"], duplicates="drop")soe_groups = latest.groupby("soe_quartile")["altman_z_em_w"]box_data = [group.values for name, group in soe_groups]bp = axes[1].boxplot( box_data, labels=[name for name, _ in soe_groups], patch_artist=True, medianprops=dict(color="black", linewidth=2))gradient_colors = plt.cm.Blues(np.linspace(0.3, 0.8, len(bp["boxes"])))for patch, color inzip(bp["boxes"], gradient_colors): patch.set_facecolor(color)axes[1].axhline(y=2.60, color="green", linestyle=":", alpha=0.5, label="Safe threshold")axes[1].axhline(y=1.10, color="red", linestyle=":", alpha=0.5, label="Distress threshold")axes[1].set_xlabel("State Ownership Quartile")axes[1].set_ylabel("Z''-Score (Emerging Market)")axes[1].set_title("Financial Health by State Ownership")axes[1].legend(fontsize=9)plt.tight_layout()plt.show()
Hình 38.1: Mối quan hệ giữa tỷ lệ sở hữu nhà nước và các thước đo định giá/kiệt quệ của doanh nghiệp. Biểu đồ bên trái thể hiện Q của Tobin theo sở hữu nhà nước, với đường làm trơn LOWESS. Biểu đồ bên phải thể hiện điểm Z’’ theo tứ phân vị sở hữu nhà nước.
Bảng 38.1: Thống kê mô tả theo sàn giao dịch đối với các doanh nghiệp niêm yết Việt Nam (năm gần nhất)
N Firms
Median Q
Mean Q
Median Z
Mean Z'' (EM)
% Distress (Z)
% Distress (Z'')
Median Age
Median SOE %
exchange
HNX
77
0.99
1.02
2.07
7.25
32.5%
0.0%
33
22.1%
HOSE
113
1.00
1.04
2.06
7.24
40.7%
0.0%
29
26.8%
UPCoM
42
0.98
1.05
2.13
7.80
30.9%
0.0%
26
27.6%
38.3 Bản đồ nhiệt theo ngành: Định giá và kiệt quệ
Hiện mã
fig, axes = plt.subplots(1, 2, figsize=(16, 8))# Tobin's Q heatmapq_pivot = ( final_df .groupby(["industry", "year"])["tobin_q_w"] .median() .unstack(fill_value=np.nan))sns.heatmap( q_pivot, cmap="RdYlGn", center=1, ax=axes[0], cbar_kws={"label": "Median Q", "shrink": 0.8}, linewidths=0.5, linecolor="white", xticklabels=2)axes[0].set_title("Tobin's Q by Industry and Year")axes[0].set_xlabel("Year")axes[0].set_ylabel("")# Z''-Score heatmapz_pivot = ( final_df .groupby(["industry", "year"])["altman_z_em_w"] .median() .unstack(fill_value=np.nan))sns.heatmap( z_pivot, cmap="RdYlGn", center=2.6, ax=axes[1], cbar_kws={"label": "Median Z''", "shrink": 0.8}, linewidths=0.5, linecolor="white", xticklabels=2)axes[1].set_title("Z''-Score (EM) by Industry and Year")axes[1].set_xlabel("Year")axes[1].set_ylabel("")plt.tight_layout()plt.show()
Hình 38.2: Q của Tobin và điểm Z’’ trung vị theo ngành và năm đối với các doanh nghiệp niêm yết Việt Nam. Màu ấm hơn biểu thị giá trị cao hơn.
38.4 Xử lý các doanh nghiệp bị hủy niêm yết: Thiên kiến sống sót
Một vấn đề then chốt khi đo lường kiệt quệ tài chính là thiên kiến sống sót. Nếu chỉ phân tích các doanh nghiệp hiện đang niêm yết, chúng ta bỏ sót chính những doanh nghiệp mà điểm Z được thiết kế để nhận diện, tức những doanh nghiệp đã phá sản hoặc bị hủy niêm yết.
Hình 39.1: So sánh các biến thể của Q của Tobin: Q đơn giản (Gompers et al. 2003) so với xấp xỉ Chung-Pruitt. Tương quan cao ủng hộ việc sử dụng thước đo đơn giản hơn.
39.2 Các thước đo điều chỉnh theo ngành
Q của Tobin và điểm Z thô có thể phản ánh đặc điểm ngành hơn là thuộc tính riêng của doanh nghiệp. Chúng ta tính các phiên bản điều chỉnh theo ngành:
40 Giải quyết kiệt quệ: Chế độ pháp lý đằng sau điểm Z
40.1 Điểm Z thực sự dự báo điều gì
Hàm phân biệt của Altman (1968) được ước lượng trên một mẫu ghép cặp gồm các doanh nghiệp đã nộp và chưa nộp đơn phá sản. Do đó, sự kiện mà nó chấm điểm là việc bước vào một thủ tục pháp lý cụ thể, chứ không phải cái chết về mặt kinh tế, và càng không phải mức tổn thất khi xảy ra kiệt quệ. Sự phân biệt này dễ bị bỏ qua vì các vùng diễn giải trong Bảng 30.2 được diễn đạt bằng ngôn ngữ xác suất thất bại, nhưng đối với bất kỳ ai định giá một quyền đòi đối với doanh nghiệp, đối tượng liên quan là
\[
\mathbb{E}[\text{Loss}_i] \;=\; \underbrace{\Pr(\text{distress}_i)}_{\text{what } Z \text{ scores}} \times \underbrace{\mathbb{E}\!\left[\text{Loss}_i \mid \text{distress}_i\right]}_{\text{set by the insolvency regime}} .
\tag{40.1}\]
Nhân tố thứ hai không phải là thuộc tính của doanh nghiệp. Nó là thuộc tính của các quy tắc quy định ai kiểm soát một doanh nghiệp kiệt quệ, chi phí tái cơ cấu là bao nhiêu, chủ nợ có thể buộc thanh lý hay không, và chủ sở hữu hiện hữu có thể giữ lại vốn chủ sở hữu hay không. Việc chuyển một hàm phân biệt được ước lượng ở một khu vực pháp lý sang nơi khác đồng nghĩa với việc chuyển theo một nhân tố thứ hai ngầm định. Việc nhân tố thứ hai thực sự thay đổi đã được ghi nhận rõ: Davydenko và Franks (2008) cho thấy các vụ vỡ nợ đối với các khoản vay tương tự ở Pháp, Đức và Anh được giải quyết khác nhau đến mức các ngân hàng điều chỉnh yêu cầu tài sản đảm bảo theo bộ luật, và Schoenherr và Starmans (2022) chứng minh cả về lý thuyết lẫn thực nghiệm rằng mức độ thân thiện tối ưu đối với con nợ phụ thuộc vào môi trường xung quanh chứ không phải là một hằng số phổ quát.
Đối với nghiên cứu về Việt Nam, điều này quan trọng gấp đôi. Các hệ số của điểm Z’’ được sử dụng trong Chương 34 được hiệu chỉnh bên ngoài Việt Nam, và phân phối kết cục mà chúng ngầm định lấy làm điều kiện được tạo ra bởi một hệ thống phá sản mà Việt Nam không có.
40.2 Thí nghiệm Subchapter V
Hotchkiss, Iverson, và Zheng (2026) cung cấp bằng chứng gần đây rõ ràng nhất rằng nhân tố thứ hai trong Phương trình 40.1 là một lựa chọn chính sách chứ không phải một hằng số công nghệ, và họ làm điều đó ở phân khúc mà câu hỏi này gay gắt nhất: các doanh nghiệp nhỏ.
Thực tế cách điệu hóa (stylized fact) làm động lực cho bài nghiên cứu lại đảo ngược thực tế quen thuộc. Đối với các công ty đại chúng lớn của Hoa Kỳ, các vụ thanh lý theo Chapter 11 hiếm khi xảy ra và hầu hết các doanh nghiệp nộp đơn thoát ra với một phần hoặc toàn bộ hoạt động còn nguyên vẹn. Đối với doanh nghiệp nhỏ, bức tranh đảo ngược: 70% doanh nghiệp nhỏ bước vào thủ tục phá sản giai đoạn 2010-2019 nộp đơn thẳng vào thanh lý theo Chapter 7, và trong số những doanh nghiệp đã vào Chapter 11, chỉ khoảng một phần ba được xác nhận kế hoạch. Phần còn lại bị chuyển sang Chapter 7 hoặc bị tòa bác đơn. Việc bị bác đơn không phải là một cú hạ cánh mềm, vì doanh nghiệp quay lại với các chủ nợ mà không được xóa nợ và thường ngừng hoạt động (Morrison 2007; Iverson 2018).
Ba ma sát giải thích khoảng cách này. Thứ nhất, các chi phí trực tiếp của Chapter 11 phần lớn là cố định, nên chúng trở nên quá nặng nề so với một cơ sở tài sản nhỏ (Bris, Welch, và Zhu 2006; Dou và c.s. 2021). Thứ hai, nguyên tắc ưu tiên tuyệt đối xóa sạch vốn chủ sở hữu trước phá sản, nhưng trong một doanh nghiệp nhỏ, các mối quan hệ của chủ sở hữu kiêm nhà quản lý với nhà cung cấp và khách hàng thường chính là giá trị hoạt động liên tục; các chủ nợ kiêm chủ sở hữu mới không thể dễ dàng thay thế những gì họ vừa tước đoạt, và các chủ nợ thương mại cùng các ngân hàng địa phương hiếm khi muốn nắm giữ vốn chủ sở hữu ngay từ đầu. Thứ ba, các chủ nợ phân tán với thứ tự ưu tiên khác nhau tạo ra các vấn đề phối hợp, và một chủ nợ có bảo đảm ưu tiên với khoản nợ nhỏ thường thích phát mại nhanh hơn một kế hoạch được thương lượng, ngay cả khi việc tiếp tục hoạt động có giá trị hơn xét trên tổng thể.
Đạo luật Tái cơ cấu Doanh nghiệp Nhỏ năm 2019 (Small Business Reorganization Act of 2019) đã tạo ra Subchapter V của Chapter 11, có hiệu lực từ ngày 19 tháng 2 năm 2020, giải quyết đồng thời cả ba ma sát này đối với các con nợ có tổng nợ không phụ thuộc điều kiện và đã xác định không vượt quá $7.5 triệu. Mức trần để đủ điều kiện ban đầu là $2.725 triệu và được CARES Act nâng lên $7.5 triệu vào ngày 27 tháng 3 năm 2020, một tháng sau khi thủ tục này mở ra. Ba thay đổi then chốt là: một kế hoạch có thể được xác nhận bất chấp sự phản đối của chủ nợ mà không xóa bỏ vốn chủ sở hữu của chủ doanh nghiệp, với điều kiện doanh nghiệp cam kết dành thu nhập khả dụng dự kiến của mình để trả nợ trong ba đến năm năm; ủy ban chủ nợ và bản công bố thông tin không còn bắt buộc; và một người được ủy thác Subchapter V được chỉ định để hòa giải thay vì thay thế ban quản lý.
Chính mức trần đủ điều kiện khiến đây trở thành một thí nghiệm chứ không phải một giai thoại. Bảng 40.1 tổng hợp các ước lượng chính.
Bảng 40.1: Tác động ước lượng của điều kiện đủ hưởng Subchapter V đối với kết cục Chapter 11 của doanh nghiệp nhỏ, từ Hotchkiss, Iverson, và Zheng (2026). “pp” là điểm phần trăm. Giai đoạn một là mức nhảy \(41.9\) pp trong việc sử dụng Subchapter V tại ngưỡng (\(F = 71.2\)) ở băng thông rộng và \(37.1\) pp (\(F = 19.7\)) ở băng thông hẹp.
Kết cục
Thiết kế
Ước lượng
Mức tham chiếu
Kế hoạch được xác nhận
OLS, 6,431 vụ dưới $15m
\(+18.4\) pp
tỷ lệ cơ sở \(31.9\%\)
Kế hoạch được xác nhận
Fuzzy RDD, $4–11m (\(n=999\))
\(+32.0\) pp
\(17.3\%\) đối với không thuộc SubV
Kế hoạch được xác nhận
Fuzzy RDD, $6–9m
\(+49.5\) pp
\(17.3\%\) đối với không thuộc SubV
Kế hoạch được xác nhận
DiD, ý định điều trị
\(+12.5\) pp
—
Số ngày đến khi xác nhận
OLS / fuzzy RDD
\(-24\%\) / \(-35\%\)
trung bình 319 ngày
Tỷ lệ thu hồi của chủ nợ không bảo đảm
Fuzzy RDD
\(+11.9\) pp
—
Khả năng tồn tại sau phá sản
Fuzzy RDD, $4–11m
\(+21\) pp
không có ý nghĩa ở $6–9m
Hai đặc điểm của bảng này đáng được nhấn mạnh, ngoài các con số riêng lẻ.
Thứ nhất là tác động rất lớn so với tỷ lệ cơ sở. Một doanh nghiệp ngay dưới ngưỡng có xác suất tái cơ cấu cao gấp hơn hai lần so với một doanh nghiệp tương tự ngay trên ngưỡng. Trong khoảng này, việc một doanh nghiệp nhỏ kiệt quệ có tồn tại được hay không phụ thuộc vào thủ tục mà nó được phép sử dụng nhiều hơn là bất cứ điều gì trên bảng cân đối kế toán. Hệ quả đối với Phương trình 40.1 là nhân tố tổn thất có điều kiện là một tham số chính sách.
Thứ hai là phản bác hiển nhiên không đứng vững. Một chế độ cho phép chủ sở hữu giữ vốn chủ sở hữu bất chấp sự phản đối của chủ nợ, theo lập luận chuẩn, sẽ giữ cho các doanh nghiệp không khả thi tiếp tục tồn tại gây thiệt hại cho chủ nợ; hiệu quả hoạt động kém sau phá sản của các doanh nghiệp lớn đã thoát khỏi thủ tục phá sản từ lâu đã được xem là bằng chứng cho chính thiên lệch duy trì hoạt động đó (Hotchkiss 1995; Morrison 2007). Ở đây, tỷ lệ thu hồi kỳ vọng của chủ nợ không bảo đảm tăng 11.9 điểm phần trăm và khả năng tồn tại sau phá sản tăng lên chứ không giảm. Lợi ích từ việc tránh một cuộc thanh lý tốn kém dường như được chia sẻ chứ không bị tái phân phối, đúng như kỳ vọng nếu tỷ lệ thanh lý trước cải cách phản ánh chi phí giao dịch và thất bại phối hợp chứ không phải việc phân loại đúng giữa doanh nghiệp khả thi và không khả thi.
40.3 Đọc bằng chứng từ góc nhìn Việt Nam
Bốn hàm ý được áp dụng sang bối cảnh Việt Nam, nhưng không hàm ý nào áp dụng một cách máy móc.
Vùng kiệt quệ mang một ý nghĩa khác ở đây. Khung pháp lý chính thức về mất khả năng thanh toán của Việt Nam là Luật Phá sản số 51/2014/QH13, có hiệu lực từ ngày 1 tháng 1 năm 2015, quy định cả thủ tục phục hồi kinh doanh và thanh lý. Tuy nhiên, như đã trình bày trong Mục 13.5, các trường hợp rời khỏi nhóm doanh nghiệp niêm yết Việt Nam quan sát được chủ yếu là hủy niêm yết bắt buộc do lỗ vượt vốn điều lệ, không nộp báo cáo tài chính và xử lý vi phạm của cơ quan quản lý, chứ không phải các thủ tục tái cơ cấu dưới sự giám sát của tòa án tạo ra một tỷ lệ thu hồi quan sát được. Do đó, nội dung thực nghiệm của điểm Z’’ dưới 1.10 ở Việt Nam gần với “kỳ vọng bị hủy niêm yết và lợi nhuận cuối kỳ âm lớn” hơn là “kỳ vọng một quy trình có giám sát với tỷ lệ thu hồi của chủ nợ đo lường được”. Đây chính là lý do việc ước tính lợi nhuận hủy niêm yết trong Mục 13.5 không phải là một chi tiết kỹ thuật: đối với các doanh nghiệp Việt Nam, nó đang làm công việc mà hồ sơ vụ án của tòa án phá sản đảm nhiệm trong dữ liệu của Hoa Kỳ.
Việt Nam không có cơ sở dữ liệu tương đương FJC. Thiết kế của Hotchkiss–Iverson–Zheng dựa trên một cuộc điều tra toàn bộ công khai, ở cấp độ từng vụ việc, về các hồ sơ nộp đơn với nợ phải trả được ghi nhận tại thời điểm nộp đơn, bổ sung bằng các bảng kê thu thập thủ công từ hồ sơ tòa án. Việt Nam không có dữ liệu nào tương đương, và việc xây dựng nó sẽ là một đóng góp nghiên cứu độc lập. Cho đến khi nó tồn tại, nghiên cứu kiệt quệ tài chính ở Việt Nam phần lớn bị giới hạn trong nhóm doanh nghiệp niêm yết, vốn là lát cắt kém đại diện nhất của tổng thể doanh nghiệp nhỏ mà lý thuyết hướng đến.
Ma sát tái triển khai tài sản có thể lớn hơn.Bernstein, Colonnelli, và Iverson (2019) cho thấy tài sản của các doanh nghiệp nhỏ bị thanh lý ở Hoa Kỳ được tái triển khai kém và cuối cùng bị sử dụng dưới công suất, đó là cơ chế khiến việc thanh lý quá mức gây tốn kém cho xã hội. Thị trường thứ cấp mỏng đối với thiết bị vốn đã qua sử dụng và sự phức tạp về hành chính khi chuyển nhượng quyền sử dụng đất khiến ma sát này nhiều khả năng nghiêm trọng hơn ở Việt Nam, dù chúng tôi không biết có ước lượng trực tiếp nào.
Dư địa cải cách vẫn còn rộng mở.Hotchkiss, Iverson, và Zheng (2026) ghi nhận rằng ít nhất mười một quốc gia đã áp dụng các thủ tục mất khả năng thanh toán đơn giản hóa cho doanh nghiệp nhỏ trong thập kỷ qua, một số trong khu vực, và Gurrea-Martínez (2024) khảo sát cải cách mất khả năng thanh toán ở các nền kinh tế mới nổi một cách cụ thể. Việt Nam không nằm trong nhóm áp dụng. Đối với nhà nghiên cứu, điều này có hai mặt: không có thí nghiệm tự nhiên sẵn có kiểu này ở Việt Nam để khai thác, nhưng câu hỏi đánh giá ex-ante hoàn toàn bỏ ngỏ và khuôn mẫu nhận diện dưới đây có thể chuyển giao.
40.4 Quy tắc ngưỡng như thiết kế nghiên cứu
Nội dung phương pháp luận của Hotchkiss, Iverson, và Zheng (2026) đáng được tách khỏi nội dung thể chế, vì các ngưỡng đủ điều kiện có ở khắp nơi trong quy định của Việt Nam và thiết kế này có thể chuyển giao ngay cả khi nội dung cụ thể thì không.
Điều kiện đủ hưởng là một hàm tất định của biến chạy, nhưng việc tham gia thì không: 39% doanh nghiệp đủ điều kiện trong mẫu của bài nghiên cứu vẫn chọn Chapter 11 truyền thống, và một số ít doanh nghiệp có vẻ không đủ điều kiện đã được chấp nhận sau khi tòa án phân loại lại một phần nợ phải trả của họ thành nợ phụ thuộc điều kiện. Do đó, việc điều trị nhảy tại ngưỡng mà không đi từ không lên một, đó là trường hợp mờ. Đặt \(s_i = L_i - c\) cho biến chạy đã được dời gốc về ngưỡng và \(B_i = \mathbf{1}\{s_i \leq 0\}\) cho điều kiện đủ hưởng. Thiết kế là bình phương tối thiểu hai giai đoạn với \(B_i\) là biến công cụ bị loại trừ:
trong đó \(D_i\) chỉ thị việc sử dụng thực tế thủ tục đơn giản hóa, còn \(f\) và \(g\) là các đa thức bậc thấp được ước lượng riêng ở mỗi phía của ngưỡng (Imbens và Lemieux 2008; Lee và Lemieux 2010). Trong trường hợp vừa đủ nhận diện, \(\beta\) bằng tỷ số giữa mức nhảy dạng rút gọn của \(y\) và mức nhảy giai đoạn một \(\pi\), đó là dạng Wald của bộ ước lượng và là cách hữu ích nhất để đọc nó. Điều \(\beta\) nhận diện là một tác động điều trị trung bình cục bộ: tác động đối với các doanh nghiệp gần ngưỡng sử dụng thủ tục vì họ đủ điều kiện. Đó không phải là tác động đối với một doanh nghiệp có nợ phải trả $1 triệu, và cũng không phải là tác động của việc bắt buộc áp dụng thủ tục.
40.4.2 Điều gì làm thiết kế đáng tin cậy
Bốn kiểm tra đảm nhiệm vai trò này, và cả bốn đều được báo cáo trong bài nghiên cứu.
Tính liên tục của mật độ. Nếu các doanh nghiệp thao túng biến chạy để đủ điều kiện, mật độ của \(s_i\) nhảy tại ngưỡng và phép so sánh diễn ra giữa các nhóm tự chọn. Kiểm định McCrary (2008) không tìm thấy sự gián đoạn (\(p = 0.25\)). Lập luận thể chế củng cố lập luận thống kê: một doanh nghiệp kiệt quệ không thể dễ dàng thanh toán nợ để xuống dưới một mức trần, và bản thân mức trần được nâng lên bất ngờ một tháng sau khi thủ tục mở ra.
Tính trơn của các hiệp biến. Đòn bẩy, tỷ trọng nợ có bảo đảm, tổng tài sản, tình trạng nộp đơn chung và số lượng chủ nợ đều liên tục qua ngưỡng, cả riêng lẻ lẫn đồng thời.
Độ vững theo đặc tả donut-hole. Loại bỏ các vụ việc trong dải $7–7.5 triệu, nơi mọi sự thao túng sẽ tập trung, hầu như không làm thay đổi các hệ số.
Độ nhạy theo băng thông, được báo cáo trung thực. Tác động xác nhận là \(+32.0\) pp trong khoảng $4–11 triệu và \(+49.5\) pp trong khoảng $6–9 triệu. Thu hẹp cửa sổ củng cố nhận diện nhưng làm giảm sức mạnh thống kê, và bài nghiên cứu cho thấy cả hai mặt của sự đánh đổi đó: ước lượng điểm tăng, nhưng tác động lên khả năng tồn tại có ý nghĩa ở cửa sổ rộng lại không có ý nghĩa ở cửa sổ hẹp. Báo cáo đường đi của băng thông không phải là một nghi thức kiểm tra độ vững; nó là kết quả chính. Lựa chọn băng thông theo dữ liệu với suy luận hiệu chỉnh thiên lệch (Calonico, Cattaneo, và Titiunik 2014) là phần bổ sung tự nhiên, không phải là sự thay thế cho việc trình bày đường đi đó.
Có một mối đe dọa mà không kiểm tra nội bộ nào có thể giải quyết, đó là sự chọn lọc vào chính mẫu. Nếu điều kiện đủ hưởng khiến các doanh nghiệp lẽ ra sẽ tái cơ cấu ngoài tòa phải nộp đơn, thì phép so sánh bị nhiễm ngay cả khi có sự gián đoạn hoàn hảo. Phản hồi của bài nghiên cứu là một khuôn mẫu hữu ích: thay vì bác bỏ mối đe dọa bằng lập luận, nó định lượng mức độ chọn lọc cần thiết để lật ngược kết quả, và cho thấy việc loại bỏ ngẫu nhiên 29 vụ Subchapter V tái cơ cấu làm ước lượng chuyển từ 32.0 sang 29.1 điểm phần trăm, trong khi để đưa nó về không cần loại bỏ ít nhất 120 vụ.
40.4.3 Sai biệt trong sai biệt như ý định điều trị
Vì thủ tục này chưa tồn tại trước tháng 2 năm 2020, cùng một ngưỡng hỗ trợ một thiết kế thứ hai,
với các doanh nghiệp dưới mức trần là nhóm được điều trị và các doanh nghiệp ngay trên mức trần là nhóm đối chứng chưa bao giờ được điều trị. Ở đây \(\beta_3\) là tác động ý định điều trị, và nó nhỏ hơn ước lượng RDD vì hai lý do cộng dồn: không phải mọi doanh nghiệp đủ điều kiện đều sử dụng thủ tục, và mẫu trước năm 2020 chỉ có thể được chia theo tổng nợ phải trả chứ không phải nợ không phụ thuộc điều kiện, nên một số doanh nghiệp thực sự đủ điều kiện bị phân loại nhầm vào nhóm đối chứng. Sự đối chiếu này rất đáng học hỏi. Chia ITT là 12.5 điểm phần trăm cho giai đoạn một là 42 điểm phần trăm cho ra 29.8, gần với ước lượng RDD là 32.0. Một ITT và một LATE trông không nhất quán thường là cùng một tham số chia cho các mẫu số khác nhau.
40.4.4 Điều chỉnh thiết kế cho Việt Nam
Quy định của Việt Nam có rất nhiều quy tắc ranh giới rõ ràng: các điều kiện niêm yết và hủy niêm yết gắn với lỗ lũy kế so với vốn điều lệ, với số năm thua lỗ liên tiếp và với ý kiến kiểm toán; các định nghĩa dựa trên quy mô quyết định khả năng tiếp cận các chương trình hỗ trợ và ưu đãi thuế; trần sở hữu nước ngoài. Mỗi quy tắc đều là một ứng viên cho biến chạy (forcing variable).
Lời cảnh báo là kiểm định thao túng, vốn gần như một thủ tục hình thức trong Hotchkiss, Iverson, và Zheng (2026), trở thành yếu tố then chốt ở đây. Một doanh nghiệp Hoa Kỳ kiệt quệ không thể dễ dàng trả bớt nợ để lọt xuống dưới mức trần nợ phải trả. Một doanh nghiệp Việt Nam tiến gần ngưỡng được xác định theo lỗ lũy kế, doanh thu hoặc số lao động được báo cáo thường có thể làm được, và các động cơ quản trị dồn tích được ghi nhận trong chương quản trị lợi nhuận cung cấp cả động cơ lẫn phương tiện. Bất kỳ RDD nào của Việt Nam xây dựng trên một ngưỡng kế toán đều cần kiểm định mật độ, một đặc tả donut-hole (loại bỏ các quan sát sát ngưỡng) và một lập luận về lý do ngày báo cáo đi trước việc doanh nghiệp biết đến quy tắc — và cần sẵn sàng kết luận rằng thiết kế không hiệu quả. Các quy tắc ngưỡng cũng thay đổi; nội dung chính xác và ngày có hiệu lực của thông tư điều chỉnh phải được đối chiếu với giai đoạn mẫu chứ không được mặc định.
40.5 Triển khai: Fuzzy RDD từ đầu
Không tồn tại bảng dữ liệu phá sản cấp vụ việc nào của Việt Nam, vì vậy chúng ta mô phỏng một bảng mà quá trình sinh dữ liệu được hiệu chỉnh theo các ước lượng trong Bảng 40.1: tỷ lệ xác nhận cơ sở \(17\%\), tỷ lệ tham gia khoảng \(60\%\) trong số các doanh nghiệp đủ điều kiện, và tác động cục bộ thực là \(32\) điểm phần trăm. Vì biết trước giá trị thực, bộ ước lượng có thể được kiểm tra so với nó, và vấn đề chọn lọc thúc đẩy thiết kế này có thể được cố ý đưa vào. Độ phức tạp vụ việc không quan sát được làm tăng tỷ lệ tham gia và giảm xác suất xác nhận cơ sở, nên phép so sánh ngây thơ giữa doanh nghiệp sử dụng và không sử dụng thủ tục bị chệch xuống dưới — cùng chiều mà Hotchkiss, Iverson, và Zheng (2026) lập luận là áp dụng trong dữ liệu của họ, nơi các doanh nghiệp nộp đơn theo Subchapter V thậm chí còn kiệt quệ hơn các doanh nghiệp nộp đơn theo Chapter 11 truyền thống.
Simulate a threshold-eligibility insolvency regime
rng = np.random.default_rng(2026)CUTOFF =7.5# eligibility ceiling, in millions of currency unitsTAU =0.32# true local effect on the probability of confirmationn_draw =2000liab = CUTOFF + rng.normal(0.0, 2.5, n_draw)liab = liab[(liab >2.0) & (liab <13.0)]n = liab.size# Unobserved case complexity: raises take-up, lowers baseline success.complexity = rng.normal(0.0, 1.0, n)eligible = (liab <= CUTOFF).astype(float)# Take-up is imperfect on both sides: some eligible firms decline the# simplified track, and a few ineligible ones are admitted after the court# reclassifies part of their liabilities as contingent.p_take = np.where(eligible ==1.0, np.clip(0.60+0.12* complexity, 0.05, 0.95),0.03)simplified = (rng.random(n) < p_take).astype(float)p_conf = np.clip(0.17+0.010* (liab - CUTOFF) -0.05* complexity + TAU * simplified,0.01, 0.99,)confirmed = (rng.random(n) < p_conf).astype(float)# A covariate that is smooth through the threshold, for the placebo check.leverage =3.0+0.15* (liab - CUTOFF) + rng.normal(0.0, 1.2, n)print(f"Cases simulated: {n:,}")print(f"Eligible (below cutoff): {eligible.mean():6.1%}")print(f"Use simplified track | eligible: {simplified[eligible ==1].mean():6.1%}")print(f"Use simplified track | above: {simplified[eligible ==0].mean():6.1%}")print(f"Plan confirmed (overall): {confirmed.mean():6.1%}")
Cases simulated: 1,940
Eligible (below cutoff): 50.8%
Use simplified track | eligible: 58.9%
Use simplified track | above: 2.5%
Plan confirmed (overall): 27.5%
Bộ máy ước lượng đủ ngắn để viết ra đầy đủ. Bình phương tối thiểu có trọng số với sai số chuẩn vững với phương sai thay đổi là khối xây dựng cơ bản; bình phương tối thiểu hai giai đoạn là cùng phép đại số được áp dụng cho phép chiếu của biến hồi quy nội sinh lên tập biến công cụ.
Weighted least squares, weighted 2SLS, and the fuzzy RD wrapper
from math import erfc, sqrtdef tri_weights(s, h):"""Triangular kernel weights on the centred running variable."""return np.clip(1.0- np.abs(s) / h, 0.0, None)def robust_wls(X, y, w):"""WLS coefficients with HC1 standard errors.""" Xw = X * w[:, None] XtWX = X.T @ Xw beta = np.linalg.solve(XtWX, Xw.T @ y) e = y - X @ beta G = X * (w * e)[:, None] bread = np.linalg.inv(XtWX) n_obs, k = X.shape V = bread @ (G.T @ G) @ bread * (n_obs /max(n_obs - k, 1))return beta, np.sqrt(np.diag(V))def robust_2sls(X, Z, y, w):"""Weighted 2SLS with HC1 standard errors; Z must have as many columns as X.""" Zw = Z * w[:, None] Xhat = Z @ np.linalg.solve(Z.T @ Zw, Zw.T @ X) A = Xhat.T @ (X * w[:, None]) beta = np.linalg.solve(A, (Xhat * w[:, None]).T @ y) e = y - X @ beta G = Xhat * (w * e)[:, None] Ainv = np.linalg.inv(A) n_obs, k = X.shape V = Ainv @ (G.T @ G) @ Ainv.T * (n_obs /max(n_obs - k, 1))return beta, np.sqrt(np.diag(V))def fuzzy_rd(running, treat, outcome, cutoff=CUTOFF, h=3.5, donut=0.0):""" Local-linear fuzzy RD with separate slopes on each side of the cutoff. Returns the first stage, the reduced form (intent-to-treat), and the 2SLS local average treatment effect, all estimated on the same sample. """ s = running - cutoff m = (np.abs(s) <= h) & (np.abs(s) >= donut) s, d, y = s[m], treat[m], outcome[m] below = (s <=0).astype(float) w = tri_weights(s, h) one = np.ones_like(s) Z = np.column_stack([one, below, s, below * s]) # instrument set X = np.column_stack([one, d, s, below * s]) # structural regressors b_fs, se_fs = robust_wls(Z, d, w) b_rf, se_rf = robust_wls(Z, y, w) b_iv, se_iv = robust_2sls(X, Z, y, w)return {"h": h, "n": int(m.sum()),"first_stage": b_fs[1], "first_stage_se": se_fs[1],"F": (b_fs[1] / se_fs[1]) **2,"itt": b_rf[1], "itt_se": se_rf[1],"late": b_iv[1], "late_se": se_iv[1],"wald": b_rf[1] / b_fs[1], }
Giờ đây có thể đặt phép so sánh ngây thơ và ước lượng RD cạnh nhau.
Naive OLS versus the fuzzy RD estimate
b_naive, se_naive = robust_wls( np.column_stack([np.ones(n), simplified]), confirmed, np.ones(n))main = fuzzy_rd(liab, simplified, confirmed, h=3.5)print("="*66)print(" Effect on the probability of confirming a plan")print("="*66)print(f" True local effect (by construction) {TAU:>10.3f}")print(f" Naive OLS, users vs non-users {b_naive[1]:>10.3f}"f" (se {se_naive[1]:.3f})")print("-"*66)print(f" Fuzzy RD, bandwidth +/-{main['h']:.1f}, n = {main['n']:,}")print(f" First stage (eligibility -> use) {main['first_stage']:>10.3f}"f" (F = {main['F']:.1f})")print(f" Reduced form (intent-to-treat) {main['itt']:>10.3f}"f" (se {main['itt_se']:.3f})")print(f" 2SLS local average treatment effect {main['late']:>10.3f}"f" (se {main['late_se']:.3f})")print(f" Wald ratio, ITT / first stage {main['wald']:>10.3f}")print("="*66)
==================================================================
Effect on the probability of confirming a plan
==================================================================
True local effect (by construction) 0.320
Naive OLS, users vs non-users 0.298 (se 0.023)
------------------------------------------------------------------
Fuzzy RD, bandwidth +/-3.5, n = 1,690
First stage (eligibility -> use) 0.562 (F = 253.7)
Reduced form (intent-to-treat) 0.232 (se 0.043)
2SLS local average treatment effect 0.414 (se 0.075)
Wald ratio, ITT / first stage 0.414
==================================================================
Tỷ số Wald và hệ số 2SLS trùng khớp đến độ chính xác của máy tính, vì mô hình vừa đủ nhận diện. Phép so sánh ngây thơ đánh giá thấp tác động thực, đúng như câu chuyện chọn lọc dự báo.
Tiếp theo là độ nhạy theo băng thông và đặc tả donut-hole. Mục đích của bảng không phải là tìm đặc tả có hệ số lớn nhất mà là xem ước lượng và độ chính xác của nó biến đổi cùng nhau như thế nào.
Bandwidth path for the fuzzy RD estimate (true effect = 0.32)
Bandwidth N First stage F LATE SE t
+/-1.5 873 0.557 117.130 0.417 0.111 3.741
+/-2.0 1148 0.563 160.669 0.418 0.095 4.401
+/-2.5 1376 0.563 195.700 0.401 0.086 4.670
+/-3.0 1546 0.562 226.385 0.407 0.080 5.107
+/-3.5 1690 0.562 253.732 0.414 0.075 5.512
+/-3.5 donut 1369 0.559 104.089 0.363 0.111 3.284
Tiếp theo là hai kiểm tra tính hợp lệ. Kiểm định mật độ tìm sự dồn tụ (bunching) ngay dưới ngưỡng, vốn cho thấy các doanh nghiệp quản lý biến chạy để đủ điều kiện; kiểm tra hiệp biến ước lượng dạng rút gọn trên một biến mà việc điều trị không thể ảnh hưởng.
Density continuity test and covariate smoothness placebo
def density_jump(x, cutoff=CUTOFF, h=3.5, binw=0.25, n_boot=400, seed=7):""" McCrary-style test: a local-linear density fitted separately on each side of the cutoff, with a bootstrap standard error for the log difference. """ n_bins =int(round(2* h / binw)) edges = np.linspace(-h, h, n_bins +1) mid = (edges[:-1] + edges[1:]) /2.0def one_jump(sample): s = sample - cutoff s = s[np.abs(s) <= h] dens = np.histogram(s, bins=edges)[0] / (sample.size * binw) fitted = []for side in (-1.0, 1.0): m = (mid * side) >0 A = np.column_stack([np.ones(int(m.sum())), mid[m]]) b, _ = robust_wls(A, dens[m], tri_weights(mid[m], h)) fitted.append(max(b[0], 1e-12))return np.log(fitted[1]) - np.log(fitted[0]) theta = one_jump(x) boot_rng = np.random.default_rng(seed) draws = np.array([ one_jump(x[boot_rng.integers(0, x.size, x.size)]) for _ inrange(n_boot) ]) se = draws.std(ddof=1) z = theta / se if se >0else0.0return theta, se, erfc(abs(z) / sqrt(2.0))theta, se_theta, p_density = density_jump(liab)cov_check = fuzzy_rd(liab, simplified, leverage, h=3.5)print("Validity checks")print("-"*66)print(f" Density log-jump at the cutoff {theta:>8.3f}"f" (se {se_theta:.3f}, p = {p_density:.3f})")print(f" Leverage jump at the cutoff {cov_check['itt']:>8.3f}"f" (se {cov_check['itt_se']:.3f}, "f"t = {cov_check['itt'] / cov_check['itt_se']:.2f})")print("-"*66)print(" Neither should be distinguishable from zero.")
Validity checks
------------------------------------------------------------------
Density log-jump at the cutoff 0.034 (se 0.091, p = 0.706)
Leverage jump at the cutoff -0.088 (se 0.122, t = -0.72)
------------------------------------------------------------------
Neither should be distinguishable from zero.
Hiện mã
bins = np.linspace(CUTOFF -3.5, CUTOFF +3.5, 29)idx = np.digitize(liab, bins) -1mids = (bins[:-1] + bins[1:]) /2.0fig, axes = plt.subplots(1, 2, figsize=(14, 5))panels = [ (axes[0], simplified, "First stage: take-up of the simplified track","Share using the procedure"), (axes[1], confirmed, "Reduced form: plan confirmation","Share confirming a plan"),]for ax, series, title, ylab in panels: means = np.array([ series[idx == b].mean() if (idx == b).sum() >0else np.nanfor b inrange(len(bins) -1) ]) ax.scatter(mids, means, s=34, color=colors["primary"], alpha=0.85, zorder=3, label="Binned mean")for side, col in [(-1.0, colors["tertiary"]), (1.0, colors["quaternary"])]: m = ((mids - CUTOFF) * side >0) &~np.isnan(means) A = np.column_stack([np.ones(int(m.sum())), mids[m] - CUTOFF]) b, _ = robust_wls(A, means[m], tri_weights(mids[m] - CUTOFF, 3.5)) grid = np.linspace(mids[m].min(), mids[m].max(), 50) ax.plot(grid, b[0] + b[1] * (grid - CUTOFF), color=col, linewidth=2) ax.axvline(CUTOFF, color=colors["distress"], linestyle="--", linewidth=2, label="Eligibility ceiling") ax.set_xlabel("Non-contingent liabilities at filing (millions)") ax.set_ylabel(ylab) ax.set_title(title) ax.legend(loc="best")plt.tight_layout()plt.show()
Hình 40.1: Gián đoạn hồi quy mờ tại một ngưỡng đủ điều kiện. Biểu đồ bên trái thể hiện giai đoạn một: mức tham gia thủ tục đơn giản hóa nhảy gián đoạn tại mức trần nhưng không đi từ không lên một, đó là điều làm cho thiết kế là mờ chứ không phải sắc nét. Biểu đồ bên phải thể hiện dạng rút gọn: xác suất xác nhận kế hoạch giảm mạnh đối với các doanh nghiệp ngay trên mức trần. Các điểm là trung bình theo nhóm; các đường là hồi quy tuyến tính cục bộ được ước lượng riêng ở mỗi phía.
Cuối cùng là phần tương ứng của sai biệt trong sai biệt. Nhóm giai đoạn trước nộp đơn trước khi thủ tục tồn tại, và biến chỉ thị điều trị của nó phải được xây dựng từ tổng nợ phải trả, vì sự phân chia nợ không phụ thuộc điều kiện không quan sát được trước khi quy tắc tạo ra lý do để ghi nhận nó. Sai số đo lường đó làm suy giảm ước lượng ý định điều trị, và việc điều chỉnh tỷ lệ theo giai đoạn một khôi phục tham số cấu trúc.
Difference-in-differences intent-to-treat, and rescaling to a LATE
did_rng = np.random.default_rng(20200219)def make_cohort(size, post):"""One filing cohort; the simplified track exists only when post is True.""" nc_liab = CUTOFF + did_rng.normal(0.0, 2.5, size) total_liab = nc_liab + did_rng.gamma(1.5, 0.6, size) # contingent claims cplx = did_rng.normal(0.0, 1.0, size) can_use = (nc_liab <= CUTOFF) &bool(post) p_use = np.where(can_use, np.clip(0.60+0.12* cplx, 0.05, 0.95), 0.0) used = (did_rng.random(size) < p_use).astype(float) p_c = np.clip(0.17+0.010* (nc_liab - CUTOFF) -0.05* cplx + TAU * used,0.01, 0.99)return pd.DataFrame({"total_liab": total_liab,"used": used,"confirmed": (did_rng.random(size) < p_c).astype(float),"post": float(post), })panel = pd.concat([make_cohort(4000, False), make_cohort(4000, True)], ignore_index=True)panel = panel[(panel["total_liab"] >=4.0) & (panel["total_liab"] <=11.0)].copy()panel["treated"] = (panel["total_liab"] <= CUTOFF).astype(float)D = np.column_stack([ np.ones(len(panel)), panel["treated"].to_numpy(), panel["post"].to_numpy(), (panel["treated"] * panel["post"]).to_numpy(),])unit_w = np.ones(len(panel))b_itt, se_itt = robust_wls(D, panel["confirmed"].to_numpy(), unit_w)b_first, se_first = robust_wls(D, panel["used"].to_numpy(), unit_w)print("="*66)print(f" Difference-in-differences, n = {len(panel):,}"f" (true effect = {TAU:.2f})")print("="*66)print(f" Treated x Post on confirmation (ITT) {b_itt[3]:>8.3f}"f" (se {se_itt[3]:.3f})")print(f" Treated x Post on take-up (1st stage) {b_first[3]:>8.3f}"f" (se {se_first[3]:.3f})")print(f" Rescaled: ITT / first stage {b_itt[3] / b_first[3]:>8.3f}")print("="*66)
==================================================================
Difference-in-differences, n = 6,398 (true effect = 0.32)
==================================================================
Treated x Post on confirmation (ITT) 0.111 (se 0.021)
Treated x Post on take-up (1st stage) 0.457 (se 0.016)
Rescaled: ITT / first stage 0.243
==================================================================
ITT rơi xa dưới tác động thực vì hầu hết các doanh nghiệp được điều trị trên danh nghĩa không bao giờ sử dụng thủ tục và một số bị phân loại nhầm theo tổng nợ phải trả thay vì nợ không phụ thuộc điều kiện. Chia cho giai đoạn một khôi phục tham số, đó là cùng phép đối chiếu mà Hotchkiss, Iverson, và Zheng (2026) báo cáo là \(12.5 / 0.42 = 29.8\) điểm phần trăm so với ước lượng RDD là \(32.0\).
Khuôn mẫu là điều có thể chuyển giao. Với một quy tắc ngưỡng của Việt Nam, một bảng dữ liệu cấp vụ việc hoặc cấp doanh nghiệp ghi nhận biến chạy theo cách quy tắc đo lường, và một lập luận đáng tin cậy rằng các doanh nghiệp không thể tự định vị quanh ngưỡng, các đoạn mã tương tự cho ra giai đoạn một, một LATE, một đường đi băng thông và hai kiểm tra tính hợp lệ quyết định liệu toàn bộ điều này có ý nghĩa hay không.
41 Các cân nhắc thực tiễn và hạn chế
41.1 Các hạn chế đã biết của Q của Tobin ở Việt Nam
Một số vấn đề ảnh hưởng đến độ tin cậy của các ước lượng Q của Tobin đối với doanh nghiệp Việt Nam:
Giá trị sổ sách làm đại diện cho chi phí thay thế: Thước đo Q giản lược giả định rằng giá trị sổ sách của tài sản xấp xỉ chi phí thay thế. Với việc VAS dựa nhiều vào giá gốc, giả định này có thể gây vấn đề hơn so với các nước áp dụng IFRS, đặc biệt đối với các doanh nghiệp có quyền sử dụng đất đáng kể hoặc tài sản hữu hình tuổi thọ dài.
Hiệu ứng vi cấu trúc thị trường: Biên độ giá hằng ngày của Việt Nam có thể ngăn giá thị trường đạt tới cân bằng, có khả năng làm méo mó thành phần giá trị thị trường. Giới hạn sở hữu nước ngoài có thể tạo ra phần bù giá nhân tạo đối với một số cổ phiếu.
Sự hiếm gặp của cổ phiếu ưu đãi: Dù điều này đơn giản hóa phép tính (hầu hết doanh nghiệp Việt Nam không có cổ phiếu ưu đãi), nó có nghĩa là phép tính BE bị chi phối bởi vốn cổ phần phổ thông, có thể không nắm bắt hết mọi quyền đòi của chủ sở hữu.
Hiệu ứng niêm yết chéo: Một số doanh nghiệp Việt Nam niêm yết trên nhiều nơi (HOSE, HNX, UPCoM, hoặc thậm chí các sàn nước ngoài). Cần thận trọng để sử dụng dữ liệu giá và số cổ phiếu nhất quán.
41.2 Các hạn chế đã biết của điểm Z của Altman ở Việt Nam
Mẫu hiệu chỉnh: Điểm Z gốc được ước lượng trên các doanh nghiệp sản xuất của Hoa Kỳ giữa thế kỷ 20. Điểm Z’’ cho thị trường mới nổi phù hợp hơn nhưng vẫn được ước lượng trên một mẫu không phải của Việt Nam.
Khác biệt kế toán: Các chuẩn mực kế toán VAS tạo ra các tỷ số tài chính có tính chất phân phối khác với dữ liệu US GAAP hoặc IFRS, có khả năng ảnh hưởng đến độ chính xác phân loại của hàm phân biệt.
Ngân hàng và doanh nghiệp tài chính: Điểm Z không được thiết kế cho các định chế tài chính, vốn có cấu trúc bảng cân đối kế toán khác biệt căn bản. Ngân hàng, công ty bảo hiểm và công ty chứng khoán nên được loại trừ hoặc phân tích riêng.
Bảo lãnh ngầm: Các SOE và doanh nghiệp liên kết với các tập đoàn kinh tế lớn có thể có sự hỗ trợ ngầm làm giảm rủi ro vỡ nợ thực tế xuống dưới dự báo của điểm Z.
41.3 Khuyến nghị cho các nhà nghiên cứu
Dựa trên phân tích của chúng tôi, chúng tôi đưa ra các khuyến nghị sau cho các nhà nghiên cứu làm việc với dữ liệu Việt Nam:
Sử dụng biến thể điểm Z’’ (thị trường mới nổi) làm thước đo kiệt quệ chính cho các doanh nghiệp phi tài chính của Việt Nam.
Báo cáo nhiều biến thể Q (đơn giản và Chung-Pruitt) để chứng minh độ vững.
Winsorization tại 1%/99% để giảm thiểu tác động của lỗi dữ liệu và các giá trị ngoại lai cực đoan.
Tính các thước đo điều chỉnh theo ngành khi thực hiện so sánh chéo.
Sử dụng tuổi thành lập thay vì tuổi niêm yết khi có sẵn, nhưng báo cáo cả hai để phân biệt mức độ trưởng thành của tổ chức với kinh nghiệm trên thị trường vốn.
Loại trừ các doanh nghiệp tài chính khỏi phân tích điểm Z.
Tính đến sở hữu nhà nước như một biến điều tiết trong các nghiên cứu về định giá và kiệt quệ.
Đừng đọc điểm Z như một dự báo thu hồi. Nó chấm điểm xác suất kiệt quệ, không phải điều mà hệ thống pháp luật làm với một doanh nghiệp kiệt quệ; xem Chương 40.
42 Tóm tắt
Chương này trình bày cách tiếp cận đối với ba thước đo cơ bản của tài chính doanh nghiệp (tức Q của Tobin, điểm Z của Altman và tuổi công ty). Chúng tôi đã trình bày nền tảng lý thuyết của từng thước đo và cung cấp nhiều hình minh họa về các mô thức cắt ngang và chuỗi thời gian.
Các phát hiện chính từ phân tích các doanh nghiệp niêm yết Việt Nam gồm:
Q của Tobin biến thiên đáng kể giữa các ngành và các sàn giao dịch, với các ngành công nghệ và hướng đến người tiêu dùng thường có mức định giá cao hơn. Các doanh nghiệp niêm yết trên HOSE có xu hướng có giá trị Q cao hơn các doanh nghiệp trên HNX hoặc UPCoM, phản ánh cả sự khác biệt về chất lượng doanh nghiệp lẫn hiệu ứng thanh khoản.
Điểm Z của Altman cho thấy một tỷ lệ đáng kể các doanh nghiệp Việt Nam hoạt động trong hoặc gần vùng kiệt quệ, dù biến thể phù hợp rất quan trọng; điểm Z’’ cho thị trường mới nổi cho phép phân loại tinh tế hơn mô hình gốc. Sức khỏe tài chính có biến thiên chuỗi thời gian đáng kể, với sự suy giảm rõ rệt trong các giai đoạn kinh tế suy thoái.
Tuổi công ty ở Việt Nam đòi hỏi xử lý cẩn thận do việc cổ phần hóa các SOE, tạo ra khoảng cách lớn giữa tuổi thành lập và tuổi niêm yết. Sự phân biệt này có ý nghĩa quan trọng về bản chất để hiểu mối quan hệ giữa mức độ trưởng thành, định giá và sự ổn định tài chính.
Giải quyết kiệt quệ là một câu hỏi tách biệt với dự báo kiệt quệ, và điểm Z chỉ nói về vế sau. Hotchkiss, Iverson, và Zheng (2026) cho thấy chỉ riêng một thay đổi trong thủ tục mất khả năng thanh toán đã làm xác suất một doanh nghiệp nhỏ của Hoa Kỳ tái cơ cấu thay vì thanh lý tăng hơn gấp đôi, mà không gây hại đến tỷ lệ thu hồi của chủ nợ. Vì các trường hợp rời khỏi thị trường ở Việt Nam chủ yếu là hủy niêm yết bắt buộc chứ không phải tái cơ cấu dưới sự giám sát của tòa án, một điểm Z’’ của Việt Nam trong vùng kiệt quệ ứng với một phân phối kết cục khác biệt đáng kể so với cùng điểm số đó trong mẫu mà các hệ số được ước lượng. Chương 40 phát triển luận điểm này và triển khai các thiết kế gián đoạn hồi quy mờ và sai biệt trong sai biệt mà các ngưỡng đủ điều kiện cho phép.
Altman, Edward I. 1968. “Financial ratios, discriminant analysis and the prediction of corporate bankruptcy”. The journal of finance 23 (4): 589–609.
Altman, Edward I, và Edith Hotchkiss. 2010. Corporate financial distress and bankruptcy: Predict and avoid bankruptcy, analyze and invest in distressed debt. Vol 289. John Wiley & Sons.
Bernstein, Shai, Emanuele Colonnelli, và Benjamin Iverson. 2019. “Asset allocation in bankruptcy”. The Journal of Finance 74 (1): 5–53. https://doi.org/10.1111/jofi.12740.
Bris, Arturo, Ivo Welch, và Ning Zhu. 2006. “The costs of bankruptcy: Chapter 7 liquidation versus Chapter 11 reorganization”. The Journal of Finance 61 (3): 1253–303. https://doi.org/10.1111/j.1540-6261.2006.00872.x.
Calonico, Sebastian, Matias D. Cattaneo, và Rocío Titiunik. 2014. “Robust nonparametric confidence intervals for regression-discontinuity designs”. Econometrica 82 (6): 2295–2326. https://doi.org/10.3982/ECTA11757.
Chung, Kee H, và Stephen W Pruitt. 1994. “A simple approximation of Tobin’s q”. Financial management, 70–74.
Coad, Alex, Jacob Rubæk Holm, Jackie Krafft, và Francesco Quatraro. 2018. “Firm age and performance”. Journal of Evolutionary Economics 28 (1): 1–11.
Daniel, Kent, và Sheridan Titman. 1997. “Evidence on the characteristics of cross sectional variation in stock returns”. the Journal of Finance 52 (1): 1–33.
Davydenko, Sergei A., và Julian R. Franks. 2008. “Do bankruptcy codes matter? A study of defaults in France, Germany, and the UK”. The Journal of Finance 63 (2): 565–608. https://doi.org/10.1111/j.1540-6261.2008.01325.x.
Dou, Winston Wei, Lucian A. Taylor, Wei Wang, và Wenyu Wang. 2021. “Dissecting bankruptcy frictions”. Journal of Financial Economics 142 (3): 975–1000. https://doi.org/10.1016/j.jfineco.2021.05.040.
Gompers, Paul, Joy Ishii, và Andrew Metrick. 2003. “Corporate governance and equity prices”. The quarterly journal of economics 118 (1): 107–56. https://doi.org/10.1162/00335530360535162.
Gurrea-Martínez, Aurelio. 2024. Reinventing Insolvency Law in Emerging Economies. Cambridge: Cambridge University Press.
Hotchkiss, Edith S., Benjamin Iverson, và Xiang Zheng. 2026. “Can small businesses survive Chapter 11?”The Journal of Finance.
Huergo, Elena, và Jordi Jaumandreu. 2004. “Firms’ age, process innovation and productivity growth”. International Journal of Industrial Organization 22 (4): 541–59.
Imbens, Guido W., và Thomas Lemieux. 2008. “Regression discontinuity designs: A guide to practice”. Journal of Econometrics 142 (2): 615–35. https://doi.org/10.1016/j.jeconom.2007.05.001.
Iverson, Benjamin. 2018. “Get in line: Chapter 11 restructuring in crowded bankruptcy courts”. Management Science 64 (11): 5370–94. https://doi.org/10.1287/mnsc.2017.2808.
Lee, David S., và Thomas Lemieux. 2010. “Regression discontinuity designs in economics”. Journal of Economic Literature 48 (2): 281–355. https://doi.org/10.1257/jel.48.2.281.
Lindenberg, Eric B, và Stephen A Ross. 1981. “Tobin’s q ratio and industrial organization”. Journal of business, 1–32.
McCrary, Justin. 2008. “Manipulation of the running variable in the regression discontinuity design: A density test”. Journal of Econometrics 142 (2): 698–714. https://doi.org/10.1016/j.jeconom.2007.05.005.
Morrison, Edward R. 2007. “Bankruptcy decision making: An empirical study of continuation bias in small-business bankruptcies”. The Journal of Law and Economics 50 (2): 381–419. https://doi.org/10.1086/511318.
Schoenherr, David, và Jan Starmans. 2022. “When should bankruptcy law be creditor- or debtor-friendly? Theory and evidence”. The Journal of Finance 77 (5): 2669–2717. https://doi.org/10.1111/jofi.13171.
Tobin, James. 1969. “A general equilibrium approach to monetary theory”. Journal of money, credit and banking 1 (1): 15–29.
Vo, Xuan Vinh. 2015. “Foreign ownership and stock return volatility–Evidence from Vietnam”. Journal of Multinational Financial Management 30: 101–9.
# Định giá doanh nghiệp, kiệt quệ tài chính và mức độ trưởng thành của công tyHiểu rõ về định giá doanh nghiệp, sức khỏe tài chính và mức độ trưởng thành của doanh nghiệp là nền tảng của phân tích tài chính và việc ra quyết định đầu tư. Ba thước đo được sử dụng rộng rãi (chẳng hạn Q của Tobin, điểm Z của Altman và tuổi công ty) phản ánh những khía cạnh khác nhau nhưng bổ sung cho nhau về vị thế kinh tế của doanh nghiệp. Q của Tobin phản ánh đánh giá của thị trường về giá trị doanh nghiệp so với cơ sở tài sản của nó, điểm Z của Altman dự báo khả năng xảy ra kiệt quệ tài chính, còn tuổi công ty là đại diện cho mức độ trưởng thành về tổ chức và sự ổn định hoạt động.Mặc dù các thước đo này đã được nghiên cứu rộng rãi ở các thị trường phát triển, đặc biệt là Hoa Kỳ [xem @lindenberg1981tobin; @altman1968financial; @gompers2003corporate], việc áp dụng chúng ở các thị trường mới nổi như Việt Nam đặt ra những thách thức và cơ hội riêng. Thị trường chứng khoán Việt Nam tăng trưởng nhanh nhưng vẫn mang những đặc điểm cấu trúc, như mức độ tập trung sở hữu, sự chi phối của doanh nghiệp nhà nước, thị trường trái phiếu còn thiếu chiều sâu và chuẩn mực kế toán đang tiếp tục phát triển, đòi hỏi phải điều chỉnh cẩn trọng các thước đo định giá và kiệt quệ tài chính tiêu chuẩn.## Các gói cần thiết```{python}#| label: setup#| message: false#| warning: falseimport pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport matplotlib.ticker as mtickerimport seaborn as snsfrom matplotlib.colors import LinearSegmentedColormapimport warningswarnings.filterwarnings("ignore")plt.rcParams.update({"figure.figsize": (10, 6),"font.size": 12,"axes.titlesize": 14,"axes.labelsize": 12,"xtick.labelsize": 10,"ytick.labelsize": 10,"legend.fontsize": 10,"figure.dpi": 150,"axes.spines.top": False,"axes.spines.right": False,})# Color palette consistent with Tidy Finance stylecolors = {"primary": "#1f77b4","secondary": "#ff7f0e","tertiary": "#2ca02c","quaternary": "#d62728","quinary": "#9467bd","safe": "#2ca02c","alert": "#ff7f0e","danger": "#d62728","distress": "#8b0000",}```# Nền tảng lý thuyết {#sec-valuation-theory}## Q của Tobin: Giá trị thị trường của doanh nghiệp {#sec-valuation-tobinq-theory}### Khái niệm gốcQ của Tobin được @tobin1969general giới thiệu như một mối liên kết lý thuyết giữa thị trường tài chính và các quyết định đầu tư thực. Ý tưởng cốt lõi rất đơn giản mà tinh tế: nếu thị trường định giá tài sản của doanh nghiệp cao hơn chi phí thay thế của chúng, doanh nghiệp có động cơ đầu tư thêm vốn mới; nếu thị trường định giá thấp hơn, doanh nghiệp không nên đầu tư, thậm chí có thể có lợi khi bán bớt tài sản.Một cách hình thức, Q của Tobin được định nghĩa như sau:$$Q = \frac{\text{Market Value of the Firm}}{\text{Replacement Cost of Assets}}$$ {#eq-tobinq-basic}Khi $Q > 1$, thị trường nhận thấy doanh nghiệp sở hữu các tài sản vô hình có giá trị, như giá trị thương hiệu, năng lực quản lý, công nghệ độc quyền hoặc cơ hội tăng trưởng, vượt quá chi phí của cơ sở tài sản hữu hình. Khi $Q < 1$, thị trường thực chất định giá doanh nghiệp thấp hơn chi phí để xây dựng lại tài sản của nó, gợi ý khả năng bị định giá thấp hoặc sự hiện diện của chi phí đại diện và sự kém hiệu quả về tổ chức.### Phân rã giá trị thị trườngTử số của Q của Tobin biểu diễn tổng giá trị thị trường của mọi quyền đòi đối với doanh nghiệp:$$MV = CS + PS + ST + LT$$ {#eq-mv-decomposition}trong đó:- $CS$ = Giá trị thị trường của cổ phiếu phổ thông (số cổ phiếu đang lưu hành $\times$ giá thị trường)- $PS$ = Giá trị thị trường của cổ phiếu ưu đãi- $ST$ = Giá trị thị trường của nợ ngắn hạn- $LT$ = Giá trị thị trường của nợ dài hạn### Chi phí thay thế của tài sảnMẫu số phản ánh chi phí thay thế của cơ sở tài sản của doanh nghiệp:$$RC = TA + (RNP - HNP) + (RINV - HINV)$$ {#eq-replacement-cost}trong đó:- $TA$ = Tổng tài sản theo báo cáo- $RNP$ = Chi phí thay thế của nhà xưởng và thiết bị ròng- $HNP$ = Giá trị lịch sử (sổ sách) của nhà xưởng và thiết bị ròng- $RINV$ = Chi phí thay thế của hàng tồn kho- $HINV$ = Giá trị lịch sử (sổ sách) của hàng tồn khoViệc điều chỉnh chi phí thay thế đối với nhà xưởng và thiết bị đòi hỏi các phép tính đệ quy có tính đến tỷ lệ khấu hao và, trong các ước lượng chi tiết hơn, tỷ lệ tiến bộ kỹ thuật [@lindenberg1981tobin]. Đối với hàng tồn kho, việc điều chỉnh phụ thuộc vào phương pháp kế toán hàng tồn kho: LIFO (nhập sau, xuất trước), FIFO (nhập trước, xuất trước), giá bình quân hoặc giá bán lẻ.### Q của Tobin giản lượcTrong thực tế, việc tính đầy đủ chi phí thay thế đòi hỏi dữ liệu thường không có sẵn, đặc biệt ở các thị trường mới nổi. @gompers2003corporate phổ biến một phiên bản giản lược:$$Q_{\text{simple}} = \frac{TA + ME - BE}{TA}$$ {#eq-tobinq-simple}trong đó $ME$ là giá trị thị trường của vốn chủ sở hữu và $BE$ là giá trị sổ sách của vốn chủ sở hữu. Cách xây dựng này giả định rằng giá trị sổ sách của nợ và cổ phiếu ưu đãi xấp xỉ giá trị thị trường của chúng, và tổng tài sản xấp xỉ chi phí thay thế của cơ sở tài sản của doanh nghiệp. Dù đơn giản, thước đo này được chứng minh là tương quan tốt với các cách xây dựng phức tạp hơn và đã trở thành chuẩn mực trong nghiên cứu tài chính doanh nghiệp thực nghiệm.### Xấp xỉ của Chung và Pruitt@chung1994simple đề xuất một phép xấp xỉ khác được sử dụng rộng rãi:$$Q_{\text{CP}} = \frac{ME + PS + DEBT}{TA}$$ {#eq-tobinq-cp}trong đó $DEBT = \text{Current Liabilities} - \text{Current Assets} + \text{Book Value of Inventories} + \text{Long-term Debt}$. Cách xây dựng này nắm bắt vị thế nợ ròng chính xác hơn so với phiên bản của @gompers2003corporate.------------------------------------------------------------------------## Điểm Z của Altman: Dự báo kiệt quệ tài chính {#sec-valuation-zscore-theory}### Mô hình gốcĐiểm Z của Altman, do @altman1968financial phát triển, là một mô hình phân tích phân biệt đa biến dự báo xác suất phá sản của doanh nghiệp trong khoảng thời gian hai năm. Mô hình ban đầu được ước lượng bằng một mẫu ghép cặp gồm các doanh nghiệp sản xuất của Hoa Kỳ đã phá sản và chưa phá sản, và có dạng:$$Z = 3.3 \cdot X_1 + 0.999 \cdot X_2 + 0.6 \cdot X_3 + 1.2 \cdot X_4 + 1.4 \cdot X_5$$ {#eq-zscore-original}trong đó năm tỷ số tài chính được nêu trong @tbl-zscore-components| Biến | Công thức | Diễn giải ||---------------------|-------------------|--------------------------------|| $X_1$ | $\frac{\text{EBIT}}{\text{Total Assets}}$ | Khả năng sinh lời của tài sản || $X_2$ | $\frac{\text{Net Sales}}{\text{Total Assets}}$ | Vòng quay tổng tài sản || $X_3$ | $\frac{\text{Market Value of Equity}}{\text{Total Liabilities}}$ | Tỷ số đòn bẩy (nghịch đảo) || $X_4$ | $\frac{\text{Working Capital}}{\text{Total Assets}}$ | Thanh khoản ngắn hạn || $X_5$ | $\frac{\text{Retained Earnings}}{\text{Total Assets}}$ | Khả năng sinh lời tích lũy |: Các thành phần của điểm Z của Altman {#tbl-zscore-components}Các vùng diễn giải được nêu trong @tbl-zscore-zones| Khoảng điểm Z | Diễn giải ||-----------------------------------|-------------------------------------|| $Z > 2.99$ | Vùng an toàn-xác suất kiệt quệ tài chính thấp || $2.70 \leq Z \leq 2.99$ | Vùng xám-cần cảnh giác, rủi ro trung bình || $1.80 \leq Z < 2.70$ | Vùng kiệt quệ-rủi ro phá sản đáng kể trong vòng 2 năm || $Z < 1.80$ | Kiệt quệ nghiêm trọng-xác suất thất bại tài chính rất cao |: Các vùng diễn giải điểm Z của Altman {#tbl-zscore-zones}### Mô hình điểm Z' cho doanh nghiệp chưa niêm yếtVì mô hình gốc dùng giá trị thị trường của vốn chủ sở hữu trong $X_3$, @altman2010corporate phát triển điểm Z' cho các doanh nghiệp chưa niêm yết (không giao dịch công khai) bằng cách thay vốn hóa thị trường bằng giá trị sổ sách của vốn chủ sở hữu:$$Z' = 0.717 \cdot X_1' + 0.847 \cdot X_2' + 3.107 \cdot X_3' + 0.420 \cdot X_4' + 0.998 \cdot X_5'$$ {#eq-zscore-private}trong đó $X_4' = \frac{\text{Book Value of Equity}}{\text{Total Liabilities}}$, và các biến còn lại được định nghĩa như trong mô hình gốc nhưng với các hệ số được ước lượng lại.### Mô hình điểm Z'' cho thị trường mới nổiPhù hợp nhất với Việt Nam, @altman2010corporate cũng phát triển điểm Z'' cho các doanh nghiệp phi sản xuất và doanh nghiệp ở thị trường mới nổi:$$Z'' = 3.25 + 6.56 \cdot X_1'' + 3.26 \cdot X_2'' + 6.72 \cdot X_3'' + 1.05 \cdot X_4''$$ {#eq-zscore-emerging}trong đó:- $X_1'' = \frac{\text{Working Capital}}{\text{Total Assets}}$- $X_2'' = \frac{\text{Retained Earnings}}{\text{Total Assets}}$- $X_3'' = \frac{\text{EBIT}}{\text{Total Assets}}$- $X_4'' = \frac{\text{Book Value of Equity}}{\text{Total Liabilities}}$Lưu ý rằng mô hình này loại bỏ tỷ số doanh thu/tổng tài sản ($X_2$ trong mô hình gốc) để giảm thiểu hiệu ứng ngành và bổ sung một hệ số chặn. Các vùng phân loại được dịch chuyển tương ứng (@tbl-zscore-em-zones).| Khoảng điểm Z'' | Diễn giải ||---------------------------|----------------|| $Z'' > 2.60$ | Vùng an toàn || $1.10 \leq Z'' \leq 2.60$ | Vùng xám || $Z'' < 1.10$ | Vùng kiệt quệ |: Các vùng diễn giải điểm Z'' cho thị trường mới nổi {#tbl-zscore-em-zones}## Tuổi công ty: Đo lường mức độ trưởng thành của doanh nghiệp {#sec-valuation-age-theory}Tuổi công ty phản ánh kinh nghiệm tích lũy, uy tín và vốn tổ chức của doanh nghiệp. Các doanh nghiệp lâu đời thường có hoạt động ổn định hơn, lợi thế cạnh tranh vững chắc và dòng tiền dễ dự báo [@coad2018firm]. Tuổi thường được dùng làm biến kiểm soát trong nghiên cứu tài chính doanh nghiệp, và mối quan hệ của nó với hiệu quả hoạt động là mơ hồ về mặt lý thuyết: doanh nghiệp lâu đời được hưởng lợi từ hiệu ứng học hỏi và uy tín nhưng có thể chịu sự cứng nhắc về tổ chức và suy giảm đổi mới [@huergo2004firms].Thước đo lý tưởng là số năm kể từ khi thành lập. Khi không có ngày thành lập, các đại diện thông dụng gồm:1. **Tuổi niêm yết**: Số năm kể từ lần IPO hoặc niêm yết đầu tiên trên một sở giao dịch chứng khoán.2. **Tuổi dữ liệu**: Số năm kể từ lần xuất hiện đầu tiên trong các cơ sở dữ liệu tài chính.3. **Tuổi đăng ký thành lập**: Số năm kể từ ngày đăng ký thành lập pháp lý.Trong bối cảnh Việt Nam, chúng ta có thể sử dụng nhiều đại diện, bao gồm ngày niêm yết lần đầu trên HOSE hoặc HNX, ngày báo cáo tài chính đầu tiên có sẵn, và (khi có) ngày thành lập từ hồ sơ công ty.# Bối cảnh thị trường Việt Nam {#sec-valuation-vietnam-context}## Các đặc điểm thể chế ảnh hưởng đến thước đo định giáThị trường chứng khoán Việt Nam có một số đặc điểm thể chế quan trọng cần xem xét khi tính toán và diễn giải Q của Tobin, điểm Z của Altman và tuổi công ty.### Sở hữu nhà nước và cổ phần hóaA significant proportion of Vietnamese listed firms are former state-owned enterprises (SOEs) that underwent equitization (cổ phần hóa). These firms often retain substantial state ownership, which can affect:- **Q của Tobin**: Sở hữu nhà nước có thể làm giảm Q nếu thị trường cho rằng sự can thiệp của chính phủ làm giảm hiệu quả, hoặc có thể làm tăng Q nếu các mối liên hệ với nhà nước mang lại khả năng tiếp cận ưu đãi đối với nguồn lực và hợp đồng.- **Điểm Z**: Các doanh nghiệp nhà nước (SOE) có thể có bảo lãnh ngầm của chính phủ làm giảm rủi ro phá sản thực tế xuống thấp hơn mức điểm Z dự báo.- **Tuổi**: Tuổi hoạt động thực của các SOE đã cổ phần hóa có thể vượt xa tuổi niêm yết của chúng, gây ra khó khăn trong đo lường.### Giới hạn sở hữu nước ngoàiViệt Nam áp đặt giới hạn sở hữu nước ngoài (FOL) đối với các công ty niêm yết, thường được giới hạn ở mức 49% đối với hầu hết các ngành (có một số ngoại lệ). Ràng buộc này có thể tạo ra phần bù giá đối với các cổ phiếu tiến gần trần FOL, có khả năng làm tăng Q của Tobin của các doanh nghiệp này [@vo2015foreign].### Chuẩn mực kế toánChuẩn mực Kế toán Việt Nam (VAS) khác với Chuẩn mực Báo cáo Tài chính Quốc tế (IFRS) ở một số điểm liên quan đến các thước đo của chúng ta:- **Cơ sở giá gốc**: VAS dựa nhiều hơn vào giá gốc, có thể khiến giá trị sổ sách lệch đáng kể so với chi phí thay thế, ảnh hưởng đến cả phép tính Q lẫn điểm Z.- **Hạn chế đo lường theo giá trị hợp lý**: Không như IFRS, VAS hạn chế việc đo lường theo giá trị hợp lý đối với nhiều loại tài sản, khiến các đại diện dựa trên giá trị sổ sách kém tin cậy hơn.- **Phương pháp hàng tồn kho**: Các doanh nghiệp Việt Nam dùng nhiều phương pháp định giá hàng tồn kho (FIFO, bình quân gia quyền), ảnh hưởng đến giá trị sổ sách của hàng tồn kho và do đó đến thành phần vốn lưu động của điểm Z.### Vi cấu trúc thị trườngThị trường Việt Nam có biên độ giá hằng ngày (hiện là $\pm$ 7% trên HOSE, $\pm$ 10% trên HNX, $\pm$ 15% trên UPCoM), có thể ngăn giá đạt tới giá trị cân bằng một cách nhanh chóng. Điều này có nghĩa là vốn hóa thị trường tại một thời điểm có thể không phản ánh đầy đủ thông tin sẵn có, đưa nhiễu vào các thước đo dựa trên giá trị thị trường như Q của Tobin.```{=html}<!-- ## DataCore.vn Dataset StructureDataCore.vn provides comprehensive financial data for Vietnamese listed companies. For this chapter, we assume access to the following datasets:1. **Financial statements** (`financial_statements`): Annual and quarterly balance sheets, income statements, and cash flow statements for all listed firms.2. **Market data** (`market_data`): Daily stock prices, shares outstanding, and market capitalization.3. **Company profiles** (`company_profiles`): Firm characteristics including listing date, founding date, industry classification, exchange, and ownership structure.4. **Delisting information** (`delisting_info`): Records of firms that have been delisted, including dates and reasons. -->```# Chuẩn bị dữ liệu {#sec-valuation-data-prep}## Tải và làm sạch dữ liệu báo cáo tài chínhChúng ta bắt đầu bằng việc tải dữ liệu báo cáo tài chính hằng năm và xây dựng các biến cần thiết cho ba thước đo.```{python}#| label: simulate-data#| code-summary: "Simulate Vietnamese financial data (replace with DataCore.vn API calls)"# ============================================================================# In practice, replace this section with actual DataCore.vn API calls:## from datacore import DataCoreClient# client = DataCoreClient(api_key="your_api_key")# financials = client.get_financial_statements(# frequency="annual",# start_date="2005-01-01",# end_date="2024-12-31"# )# market = client.get_market_data(frequency="daily")# profiles = client.get_company_profiles()## For demonstration purposes, we simulate realistic Vietnamese market data.# ============================================================================np.random.seed(42)n_firms =300years =range(2008, 2025)exchanges = ["HOSE", "HNX", "UPCoM"]industries = ["Bất động sản", "Ngân hàng", "Thực phẩm & Đồ uống","Xây dựng & Vật liệu", "Công nghệ thông tin", "Bán lẻ","Dầu khí", "Thép", "Dệt may", "Dược phẩm","Điện lực", "Vận tải & Logistics", "Hóa chất","Chứng khoán", "Bảo hiểm"]# Generate firm profilesfirm_ids = [f"VN{str(i).zfill(4)}"for i inrange(1, n_firms +1)]firm_profiles = pd.DataFrame({"ticker": firm_ids,"exchange": np.random.choice(exchanges, n_firms, p=[0.5, 0.3, 0.2]),"industry": np.random.choice(industries, n_firms),"founding_year": np.random.randint(1975, 2015, n_firms),"listing_year": np.random.randint(2000, 2020, n_firms),"state_ownership_pct": np.clip( np.random.beta(2, 5, n_firms) *100, 0, 75 ).round(1),})firm_profiles["listing_year"] = np.maximum( firm_profiles["listing_year"], firm_profiles["founding_year"] +1)# Generate panel datarecords = []for _, firm in firm_profiles.iterrows(): start_year =max(firm["listing_year"], 2008)# Base financial characteristics (firm fixed effects) base_ta = np.exp(np.random.normal(14, 1.5)) # Total assets in VND millions base_profitability = np.random.normal(0.08, 0.05) base_leverage = np.random.beta(3, 3) base_turnover = np.random.gamma(2, 0.4)for year in years:if year < start_year:continueif np.random.random() <0.02: # 2% chance of delistingbreak# Time-varying components with persistence shock = np.random.normal(0, 0.15) growth = np.random.normal(0.08, 0.05) ta = base_ta * (1+ growth) ** (year - start_year) * np.exp(shock) profitability = np.clip(base_profitability + np.random.normal(0, 0.03), -0.3, 0.5) leverage = np.clip(base_leverage + np.random.normal(0, 0.05), 0.05, 0.95) lt = ta * leverage * np.random.uniform(0.4, 0.7) total_liabilities = ta * leverage ct_liabilities = total_liabilities - lt seq = ta * (1- leverage) sale = ta * np.clip(base_turnover + np.random.normal(0, 0.1), 0.1, 5) ebit = ta * profitability ni = ebit * np.random.uniform(0.6, 0.9) re = seq * np.random.uniform(-0.2, 0.8) act = ta * np.random.uniform(0.2, 0.7) lct = ct_liabilities# Market value with noise and sentiment market_premium = np.random.lognormal(0, 0.4) me = seq * market_premium prcc = me /max(np.random.uniform(50, 500), 1) csho = me /max(prcc, 0.01)# Preferred stock (rare in Vietnam, mostly zero) pstk =0if np.random.random() >0.05else seq * np.random.uniform(0, 0.1)# Net plant and equipment ppent = ta * np.random.uniform(0.1, 0.6) invt = ta * np.random.uniform(0.05, 0.3)# Deferred taxes and investment tax credit (typically small in VN) txdb = ta * np.random.uniform(0, 0.02) itcb =0 records.append({"ticker": firm["ticker"],"year": year,"datadate": pd.Timestamp(year, 12, 31),"at": ta, # Total Assets"seq": seq, # Stockholders' Equity"lt": lt, # Long-term Debt"lct": lct, # Current Liabilities"tlb": total_liabilities, # Total Liabilities"sale": sale, # Net Sales/Revenue"ebit": ebit, # EBIT"ni": ni, # Net Income"re_var": re, # Retained Earnings"act": act, # Current Assets"ppent": ppent, # Net Plant & Equipment"invt": invt, # Inventories"txdb": txdb, # Deferred Taxes"itcb": itcb, # Investment Tax Credit"pstk": pstk, # Preferred Stock"me": me, # Market Value of Equity"prcc": prcc, # Price at Calendar Year End"csho": csho, # Shares Outstanding })df = pd.DataFrame(records)df = df.merge(firm_profiles[["ticker", "exchange", "industry","founding_year", "listing_year","state_ownership_pct"]], on="ticker", how="left")print(f"Panel dimensions: {df.shape[0]:,} firm-year observations")print(f"Number of unique firms: {df['ticker'].nunique()}")print(f"Year range: {df['year'].min()}–{df['year'].max()}")print(f"Exchanges: {df['exchange'].value_counts().to_dict()}")```## Định nghĩa biến và ánh xạ@tbl-variable-mapping trình bày ánh xạ giữa tên biến chuẩn và các trường tương ứng.```{python}#| label: tbl-variable-mapping#| tbl-cap: "Ánh xạ biến"variable_map = pd.DataFrame({"Compustat Variable": ["AT", "SEQ", "LT", "LCT", "SALE", "EBIT", "NI","RE", "ACT", "PPENT", "INVT", "TXDB", "ITCB","PSTK/PSTKRV/PSTKL", "PRCC_C", "CSHO", "DLDTE", "DLRSN" ],"Description": ["Total Assets", "Stockholders' Equity", "Long-term Debt","Current Liabilities", "Net Sales/Revenue","Earnings Before Interest & Taxes", "Net Income","Retained Earnings", "Current Assets","Net Plant & Equipment", "Total Inventories","Deferred Taxes", "Investment Tax Credit","Preferred Stock (various)", "Price Close (Calendar Year)","Common Shares Outstanding", "Delisting Date","Delisting Reason" ],"DataCore.vn Equivalent": ["tong_tai_san", "von_chu_so_huu", "no_dai_han","no_ngan_han", "doanh_thu_thuan","loi_nhuan_truoc_thue_va_lai_vay", "loi_nhuan_sau_thue","loi_nhuan_chua_phan_phoi", "tai_san_ngan_han","tai_san_co_dinh_huu_hinh", "hang_ton_kho","thue_thu_nhap_hoan_lai", "N/A (not applicable in VAS)","co_phieu_uu_dai", "gia_dong_cua_cuoi_nam","so_luong_co_phieu_luu_hanh", "ngay_huy_niem_yet","ly_do_huy_niem_yet" ],"VAS Account": ["BS.100", "BS.400", "BS.330", "BS.310","IS.10", "Computed", "IS.60","BS.421", "BS.100", "BS.221", "BS.141","BS.262", "—", "BS.411b", "Market", "Market","Profile", "Profile" ]})variable_map.style.set_properties(**{"text-align": "left","font-size": "10pt"}).set_table_styles([ {"selector": "th", "props": [ ("background-color", "#1f77b4"), ("color", "white"), ("font-weight", "bold"), ("text-align", "left"), ("padding", "8px") ]}, {"selector": "td", "props": [("padding", "6px")]},])```## Kiểm tra chất lượng dữ liệuTrước khi tính bất kỳ thước đo nào, chúng ta thực hiện các kiểm tra chất lượng dữ liệu thiết yếu, đặc biệt quan trọng đối với dữ liệu Việt Nam.```{python}#| label: data-quality-checks#| code-summary: "Data quality validation"def data_quality_report(df):"""Generate a comprehensive data quality report.""" report = {}# Check for negative total assets report["Negative total assets"] = (df["at"] <0).sum()# Check for negative equity (acceptable but noteworthy) report["Negative equity"] = (df["seq"] <=0).sum()# Check for missing critical variables critical_vars = ["at", "seq", "sale", "ebit", "me"]for var in critical_vars: report[f"Missing {var}"] = df[var].isna().sum()# Check for extreme values (potential data errors) report["Extreme leverage (>100%)"] = (df["tlb"] / df["at"] >1.0).sum() report["Extreme sales/assets (>10)"] = (df["sale"] / df["at"] >10).sum()return pd.Series(report, name="Count")quality = data_quality_report(df)print("Data Quality Report")print("="*45)for item, count in quality.items(): status ="✓"if count ==0else"⚠"print(f" {status}{item}: {count:,}")# Apply filtersdf_clean = df.copy()df_clean = df_clean[df_clean["at"] >0] # Positive total assetsdf_clean = df_clean[df_clean["seq"] >0] # Positive equity (for BE calculation)print(f"\nObservations after cleaning: {len(df_clean):,} "f"(dropped {len(df) -len(df_clean):,})")```# Tính Q của Tobin {#sec-valuation-tobinq-computation}## Giá trị sổ sách của vốn chủ sở hữuTheo @daniel1997evidence, chúng ta tính giá trị sổ sách của vốn chủ sở hữu như sau:$$BE = SEQ + TXDB + ITCB - PREF$$ {#eq-book-equity}trong đó $PREF$ là giá trị cổ phiếu ưu đãi, sử dụng giá trị hoàn lại nếu có, nếu không thì dùng giá trị thanh lý, và sau cùng là giá trị ghi sổ như phương án dự phòng cuối cùng. Trong bối cảnh Việt Nam, cổ phiếu ưu đãi tương đối hiếm trong các công ty niêm yết, nên $PREF$ thường bằng không.```{python}#| label: compute-book-equity#| code-summary: "Book value of equity computation"def compute_book_equity(df):""" Compute book value of equity following Daniel and Titman (1997). In Vietnam, preferred stock is uncommon among listed firms. The investment tax credit (ITCB) is not applicable under VAS, so we set it to zero when missing. """ result = df.copy()# Preferred stock: use coalesce logic result["pref"] = result["pstk"].fillna(0)# Book equity = Shareholders' equity + Deferred taxes + ITC - Preferred result["be"] = ( result["seq"]+ result["txdb"].fillna(0)+ result["itcb"].fillna(0)- result["pref"] )return resultdf_clean = compute_book_equity(df_clean)print("Book Equity Summary Statistics (VND millions)")print(df_clean["be"].describe().apply(lambda x: f"{x:,.0f}"))```## Giá trị thị trường của vốn chủ sở hữuGiá trị thị trường của vốn chủ sở hữu được tính bằng giá cổ phiếu cuối năm dương lịch và số cổ phiếu đang lưu hành:$$ME = P_{\text{close}} \times \text{CSHO}$$ {#eq-market-equity}Đối với các doanh nghiệp Việt Nam, giá trị này lấy từ giá đóng cửa vào ngày giao dịch cuối cùng của năm tài chính. Hầu hết doanh nghiệp Việt Nam kết thúc năm tài chính vào ngày 31 tháng 12, dù một số (đặc biệt trong nông nghiệp và ngân hàng) có thể khác.```{python}#| label: compute-market-equity#| code-summary: "Market value of equity computation"# ME is already computed in our simulated data as prcc * csho# In practice with DataCore.vn:# me = df["gia_dong_cua_cuoi_nam"] * df["so_luong_co_phieu_luu_hanh"]df_clean["me"] = df_clean["prcc"] * df_clean["csho"]print("Market Equity Summary Statistics (VND millions)")print(df_clean["me"].describe().apply(lambda x: f"{x:,.0f}"))```## Q của Tobin giản lượcChúng ta triển khai phiên bản giản lược của @gompers2003corporate:$$Q_{\text{simple}} = \frac{AT + ME - BE}{AT}$$ {#eq-tobinq-implementation}Công thức này có thể viết lại thành:$$Q_{\text{simple}} = 1 + \frac{ME - BE}{AT}$$ {#eq-tobinq-rewritten}giúp cách diễn giải trở nên rõ ràng: Q của Tobin bằng một cộng với phần bù (hoặc chiết khấu) giữa giá trị thị trường và giá trị sổ sách, chia cho tổng tài sản.```{python}#| label: compute-tobinq#| code-summary: "Tobin's Q computation with multiple variants"def compute_tobins_q(df):""" Compute multiple variants of Tobin's Q. Variants: 1. Simple Q (Gompers et al., 2003) 2. Chung-Pruitt Q 3. Market-to-Book ratio (for comparison) """ result = df.copy()# --- Variant 1: Simple Q (Gompers, Ishii, Metrick 2003) --- result["tobin_q_simple"] = (result["at"] + result["me"] - result["be"]) / result["at"]# --- Variant 2: Chung-Pruitt Approximation ---# DEBT = Current Liabilities - Current Assets + Inventories + LT Debt result["debt_cp"] = ( result["lct"].fillna(0)- result["act"].fillna(0)+ result["invt"].fillna(0)+ result["lt"].fillna(0) ) result["tobin_q_cp"] = ( (result["me"] + result["pstk"].fillna(0) + result["debt_cp"]) / result["at"] )# --- Market-to-Book Ratio --- result["mtb"] = np.where(result["be"] >0, result["me"] / result["be"], np.nan)return resultdf_clean = compute_tobins_q(df_clean)# Summary statisticsq_vars = ["tobin_q_simple", "tobin_q_cp", "mtb"]q_summary = df_clean[q_vars].describe(percentiles=[0.01, 0.05, 0.25, 0.5, 0.75, 0.95, 0.99])q_summary = q_summary.round(3)q_summary.columns = ["Simple Q", "Chung-Pruitt Q", "Market-to-Book"]print("Tobin's Q Summary Statistics")print(q_summary.to_string())```## Áp dụng winsorization cho các giá trị cực đoanGiá trị Q của Tobin có thể bị ảnh hưởng nặng bởi các giá trị ngoại lai, đặc biệt ở các thị trường mới nổi nơi chất lượng dữ liệu có thể không đồng đều. Chúng ta thực hiện winsorization tại phân vị thứ 1 và thứ 99.```{python}#| label: winsorize#| code-summary: "Winsorization of extreme values"def winsorize(series, lower=0.01, upper=0.99):"""Winsorize a pandas Series at specified percentiles.""" low = series.quantile(lower) high = series.quantile(upper)return series.clip(lower=low, upper=high)# Winsorize Q measuresfor var in ["tobin_q_simple", "tobin_q_cp", "mtb"]: df_clean[f"{var}_w"] = winsorize(df_clean[var])print("Effect of Winsorization on Simple Tobin's Q:")print(f" Before: mean={df_clean['tobin_q_simple'].mean():.3f}, "f"std={df_clean['tobin_q_simple'].std():.3f}")print(f" After: mean={df_clean['tobin_q_simple_w'].mean():.3f}, "f"std={df_clean['tobin_q_simple_w'].std():.3f}")```## Phân phối chéo của Q của Tobin```{python}#| label: fig-tobinq-distribution#| fig-cap: "Phân phối của Q của Tobin trên các doanh nghiệp niêm yết Việt Nam (2024). Đường nét đứt thẳng đứng tại Q=1 biểu thị ngưỡng lý thuyết mà tại đó giá trị thị trường bằng chi phí thay thế."fig, axes = plt.subplots(1, 2, figsize=(14, 5))# Latest year distributionlatest_year = df_clean["year"].max()latest_data = df_clean[df_clean["year"] == latest_year]# Histogramaxes[0].hist( latest_data["tobin_q_simple_w"].dropna(), bins=50, color=colors["primary"], alpha=0.7, edgecolor="white")axes[0].axvline(x=1, color=colors["quaternary"], linestyle="--", linewidth=2, label="Q = 1")axes[0].set_xlabel("Tobin's Q (Simple)")axes[0].set_ylabel("Number of Firms")axes[0].set_title(f"Cross-Sectional Distribution ({latest_year})")axes[0].legend()# Box plot by exchangeexchange_data = latest_data[["exchange", "tobin_q_simple_w"]].dropna()exchanges_sorted = exchange_data.groupby("exchange")["tobin_q_simple_w"].median().sort_values().indexbox_data = [exchange_data[exchange_data["exchange"] == ex]["tobin_q_simple_w"].valuesfor ex in exchanges_sorted]bp = axes[1].boxplot(box_data, labels=exchanges_sorted, patch_artist=True, medianprops=dict(color="black", linewidth=2))box_colors = [colors["primary"], colors["secondary"], colors["tertiary"]]for patch, color inzip(bp["boxes"], box_colors): patch.set_facecolor(color) patch.set_alpha(0.7)axes[1].axhline(y=1, color=colors["quaternary"], linestyle="--", linewidth=1.5, alpha=0.7)axes[1].set_ylabel("Tobin's Q (Simple)")axes[1].set_title(f"Tobin's Q by Exchange ({latest_year})")plt.tight_layout()plt.show()```## Diễn biến chuỗi thời gian của Q của Tobin```{python}#| label: fig-tobinq-timeseries#| fig-cap: "Diễn biến của Q của Tobin trung vị trên các sàn giao dịch Việt Nam (2008–2024). Vùng tô bóng biểu thị khoảng tứ phân vị."# Compute annual statistics by exchangeannual_q = ( df_clean .groupby(["year", "exchange"])["tobin_q_simple_w"] .agg(["median", lambda x: x.quantile(0.25), lambda x: x.quantile(0.75)]) .reset_index())annual_q.columns = ["year", "exchange", "median", "q25", "q75"]fig, ax = plt.subplots(figsize=(12, 6))exchange_colors = {"HOSE": colors["primary"], "HNX": colors["secondary"],"UPCoM": colors["tertiary"]}for exchange, color in exchange_colors.items(): data = annual_q[annual_q["exchange"] == exchange] ax.plot(data["year"], data["median"], color=color, linewidth=2.5, label=exchange, marker="o", markersize=4) ax.fill_between(data["year"], data["q25"], data["q75"], color=color, alpha=0.15)ax.axhline(y=1, color="gray", linestyle="--", linewidth=1, alpha=0.7, label="Q = 1")ax.set_xlabel("Year")ax.set_ylabel("Tobin's Q (Median)")ax.set_title("Evolution of Tobin's Q in the Vietnamese Market")ax.legend(loc="upper right")ax.set_xlim(2008, latest_year)ax.xaxis.set_major_locator(mticker.MultipleLocator(2))plt.tight_layout()plt.show()```## Q của Tobin theo ngành```{python}#| label: fig-tobinq-industry#| fig-cap: "Q của Tobin trung vị theo ngành ở Việt Nam (năm gần nhất có sẵn). Các ngành được sắp xếp theo giá trị Q trung vị."latest_industry_q = ( latest_data .groupby("industry")["tobin_q_simple_w"] .agg(["median", "mean", "count"]) .reset_index() .sort_values("median", ascending=True))fig, ax = plt.subplots(figsize=(10, 8))bar_colors = [colors["quaternary"] if m <1else colors["primary"]for m in latest_industry_q["median"]]ax.barh( latest_industry_q["industry"], latest_industry_q["median"], color=bar_colors, alpha=0.8, edgecolor="white")ax.axvline(x=1, color="gray", linestyle="--", linewidth=1.5, alpha=0.7)ax.set_xlabel("Median Tobin's Q")ax.set_title(f"Tobin's Q by Industry ({latest_year})")# Add count annotationsfor i, (_, row) inenumerate(latest_industry_q.iterrows()): ax.text(row["median"] +0.02, i, f'n={int(row["count"])}', va="center", fontsize=9, color="gray")plt.tight_layout()plt.show()```# Tính điểm Z của Altman {#sec-valuation-zscore-computation}## Điểm Z gốc cho doanh nghiệp niêm yết```{python}#| label: compute-zscore#| code-summary: "Altman Z-Score computation (all three variants)"def compute_altman_z(df):""" Compute three variants of the Altman Z-Score: 1. Original Z-Score (for listed manufacturing firms) 2. Z'-Score (for private firms, using book equity) 3. Z''-Score (for emerging markets / non-manufacturing) """ result = df.copy()# Common components result["wc"] = result["act"].fillna(0) - result["lct"].fillna(0) # Working Capital# --- Original Z-Score ---# Z = 3.3*(EBIT/TA) + 0.999*(Sales/TA) + 0.6*(ME/TL) + 1.2*(WC/TA) + 1.4*(RE/TA) x1 = result["ebit"] / result["at"] x2 = result["sale"] / result["at"] x3 = np.where(result["tlb"] >0, result["me"] / result["tlb"], np.nan) x4 = result["wc"] / result["at"] x5 = result["re_var"].fillna(0) / result["at"] result["z_x1"] = x1 # Earning power result["z_x2"] = x2 # Asset turnover result["z_x3"] = x3 # Leverage (inverse) result["z_x4"] = x4 # Liquidity result["z_x5"] = x5 # Cumulative profitability result["altman_z"] = (3.3* x1 +0.999* x2 +0.6* x3 +1.2* x4 +1.4* x5)# --- Z'-Score (Private firms) --- x3_prime = np.where(result["tlb"] >0, result["be"] / result["tlb"], np.nan) result["altman_z_prime"] = (0.717* x4 +0.847* x5 +3.107* x1 +0.420* x3_prime +0.998* x2 )# --- Z''-Score (Emerging Markets) --- result["altman_z_em"] = (3.25+6.56* x4 # Working Capital / TA+3.26* x5 # Retained Earnings / TA+6.72* x1 # EBIT / TA+1.05* x3_prime # Book Equity / TL )# Classify risk zones result["z_zone"] = pd.cut( result["altman_z"], bins=[-np.inf, 1.80, 2.70, 2.99, np.inf], labels=["High Distress", "Distress", "Grey Zone", "Safe"] ) result["z_em_zone"] = pd.cut( result["altman_z_em"], bins=[-np.inf, 1.10, 2.60, np.inf], labels=["Distress", "Grey Zone", "Safe"] )return resultdf_clean = compute_altman_z(df_clean)# Winsorize Z-scoresfor var in ["altman_z", "altman_z_prime", "altman_z_em"]: df_clean[f"{var}_w"] = winsorize(df_clean[var])print("Z-Score Summary Statistics")z_summary = df_clean[["altman_z", "altman_z_prime", "altman_z_em"]].describe().round(3)z_summary.columns = ["Original Z", "Z' (Private)", "Z'' (Emerging)"]print(z_summary.to_string())```## Phân tích các thành phần của điểm ZViệc hiểu thành phần nào chi phối điểm Z đặc biệt hữu ích trong bối cảnh Việt Nam, nơi một số tỷ số có thể hành xử khác với các thị trường phát triển.```{python}#| label: fig-zscore-components#| fig-cap: "Phân phối các tỷ số thành phần của điểm Z của Altman đối với các doanh nghiệp niêm yết Việt Nam. Mỗi biểu đồ con thể hiện một thành phần được gia quyền theo hệ số của nó trong công thức điểm Z gốc."fig, axes = plt.subplots(2, 3, figsize=(15, 9))components = [ ("z_x1", 3.3, "$3.3 \\times$ EBIT/TA\n(Earning Power)"), ("z_x2", 0.999, "$0.999 \\times$ Sales/TA\n(Asset Turnover)"), ("z_x3", 0.6, "$0.6 \\times$ ME/TL\n(Leverage)"), ("z_x4", 1.2, "$1.2 \\times$ WC/TA\n(Liquidity)"), ("z_x5", 1.4, "$1.4 \\times$ RE/TA\n(Cum. Profitability)"),]latest_z = df_clean[df_clean["year"] == latest_year]for idx, (var, weight, label) inenumerate(components): ax = axes[idx //3, idx %3] weighted_vals = (latest_z[var] * weight).dropna() weighted_vals = weighted_vals[weighted_vals.between( weighted_vals.quantile(0.01), weighted_vals.quantile(0.99) )] ax.hist(weighted_vals, bins=40, color=colors["primary"], alpha=0.7, edgecolor="white") ax.axvline(x=weighted_vals.median(), color=colors["quaternary"], linestyle="--", linewidth=2, label=f"Median: {weighted_vals.median():.2f}") ax.set_title(label, fontsize=11) ax.legend(fontsize=9)# Remove empty subplotaxes[1, 2].set_visible(False)plt.suptitle(f"Z-Score Component Distributions ({latest_year})", fontsize=14, y=1.02)plt.tight_layout()plt.show()```## Phân phối các vùng rủi ro```{python}#| label: fig-zscore-zones#| fig-cap: "Tỷ lệ các doanh nghiệp niêm yết Việt Nam trong từng vùng rủi ro của điểm Z của Altman theo thời gian. Hình thể hiện cả các vùng điểm Z gốc và các vùng điểm Z'' cho thị trường mới nổi."fig, axes = plt.subplots(1, 2, figsize=(14, 6))# --- Original Z-Score Zones ---zone_counts = ( df_clean .groupby(["year", "z_zone"]) .size() .unstack(fill_value=0))zone_pcts = zone_counts.div(zone_counts.sum(axis=1), axis=0) *100zone_colors = {"Safe": colors["safe"],"Grey Zone": colors["alert"],"Distress": colors["quaternary"],"High Distress": colors["distress"],}axes[0].stackplot( zone_pcts.index,*[zone_pcts[col] for col in ["Safe", "Grey Zone", "Distress", "High Distress"]if col in zone_pcts.columns], labels=[col for col in ["Safe", "Grey Zone", "Distress", "High Distress"]if col in zone_pcts.columns], colors=[zone_colors[col] for col in ["Safe", "Grey Zone", "Distress", "High Distress"]if col in zone_pcts.columns], alpha=0.8)axes[0].set_xlabel("Year")axes[0].set_ylabel("Percentage of Firms")axes[0].set_title("Original Z-Score Risk Zones")axes[0].legend(loc="upper right", fontsize=9)axes[0].set_ylim(0, 100)# --- Emerging Market Z''-Score Zones ---em_zone_counts = ( df_clean .groupby(["year", "z_em_zone"]) .size() .unstack(fill_value=0))em_zone_pcts = em_zone_counts.div(em_zone_counts.sum(axis=1), axis=0) *100em_zone_colors = {"Safe": colors["safe"], "Grey Zone": colors["alert"],"Distress": colors["quaternary"]}axes[1].stackplot( em_zone_pcts.index,*[em_zone_pcts[col] for col in ["Safe", "Grey Zone", "Distress"]if col in em_zone_pcts.columns], labels=[col for col in ["Safe", "Grey Zone", "Distress"]if col in em_zone_pcts.columns], colors=[em_zone_colors[col] for col in ["Safe", "Grey Zone", "Distress"]if col in em_zone_pcts.columns], alpha=0.8)axes[1].set_xlabel("Year")axes[1].set_ylabel("Percentage of Firms")axes[1].set_title("Emerging Market Z''-Score Risk Zones")axes[1].legend(loc="upper right", fontsize=9)axes[1].set_ylim(0, 100)plt.tight_layout()plt.show()```## So sánh các biến thể của điểm ZMột câu hỏi thực tiễn quan trọng là biến thể điểm Z nào phù hợp nhất với các doanh nghiệp Việt Nam. Mô hình gốc được hiệu chỉnh trên các doanh nghiệp sản xuất của Hoa Kỳ, trong khi điểm Z'' được thiết kế riêng cho thị trường mới nổi và các ngành phi sản xuất.```{python}#| label: fig-zscore-comparison#| fig-cap: "So sánh điểm Z gốc và điểm Z'' cho thị trường mới nổi đối với các doanh nghiệp niêm yết Việt Nam. Các điểm nằm trên (dưới) đường 45 độ có điểm Z'' (điểm Z) cao hơn thước đo còn lại."fig, ax = plt.subplots(figsize=(8, 8))sample = latest_z.dropna(subset=["altman_z_w", "altman_z_em_w"]).sample(min(500, len(latest_z)), random_state=42)scatter = ax.scatter( sample["altman_z_w"], sample["altman_z_em_w"], c=sample["tobin_q_simple_w"], cmap="RdYlGn", alpha=0.6, s=30, edgecolor="white", linewidth=0.3)# Add reference lineslims = [min(ax.get_xlim()[0], ax.get_ylim()[0]),max(ax.get_xlim()[1], ax.get_ylim()[1])]ax.plot(lims, lims, "k--", alpha=0.3, linewidth=1, label="45° line")# Add zone boundariesax.axvline(x=1.80, color="red", linestyle=":", alpha=0.5, linewidth=1)ax.axvline(x=2.99, color="green", linestyle=":", alpha=0.5, linewidth=1)ax.axhline(y=1.10, color="red", linestyle=":", alpha=0.5, linewidth=1)ax.axhline(y=2.60, color="green", linestyle=":", alpha=0.5, linewidth=1)ax.set_xlabel("Original Z-Score")ax.set_ylabel("Emerging Market Z''-Score")ax.set_title("Z-Score vs Z''-Score for Vietnamese Firms")cbar = plt.colorbar(scatter, ax=ax, shrink=0.8)cbar.set_label("Tobin's Q")ax.legend(loc="upper left")plt.tight_layout()plt.show()```# Tính tuổi công ty {#sec-valuation-age-computation}## Nhiều đại diện cho tuổiĐối với các doanh nghiệp Việt Nam, chúng ta tính ba thước đo tuổi:$$\text{Age}_{\text{founding}} = \text{Current Year} - \text{Founding Year}$$ {#eq-age-founding}$$\text{Age}_{\text{listing}} = \text{Current Year} - \text{Listing Year}$$ {#eq-age-listing}$$\text{Age}_{\text{data}} = \text{Current Year} - \text{First Year with Data}$$ {#eq-age-data}```{python}#| label: compute-age#| code-summary: "Company age computation with multiple proxies"def compute_company_age(df):""" Compute multiple proxies for company age. For Vietnamese firms: - Founding age: based on founding/incorporation date - Listing age: based on first listing on HOSE/HNX/UPCoM - Data age: based on first year with available financial data """ result = df.copy()# Founding age result["age_founding"] = result["year"] - result["founding_year"]# Listing age result["age_listing"] = result["year"] - result["listing_year"] result["age_listing"] = result["age_listing"].clip(lower=0)# Data age (years since first available financial data) first_year = result.groupby("ticker")["year"].transform("min") result["age_data"] = result["year"] - first_year# Log of age (commonly used in regressions) result["ln_age_founding"] = np.log1p(result["age_founding"]) result["ln_age_listing"] = np.log1p(result["age_listing"])return resultdf_clean = compute_company_age(df_clean)print("Company Age Summary Statistics")age_summary = df_clean[df_clean["year"] == latest_year][ ["age_founding", "age_listing", "age_data"]].describe().round(1)age_summary.columns = ["Founding Age", "Listing Age", "Data Age"]print(age_summary.to_string())```## Phân phối tuổi```{python}#| label: fig-age-distribution#| fig-cap: "Phân phối các thước đo tuổi công ty đối với các doanh nghiệp niêm yết Việt Nam. Tuổi thành lập phản ánh mức độ trưởng thành thực sự của tổ chức, trong khi tuổi niêm yết phản ánh kinh nghiệm trên thị trường vốn."fig, axes = plt.subplots(1, 3, figsize=(15, 5))age_vars = [ ("age_founding", "Founding Age (years)", colors["primary"]), ("age_listing", "Listing Age (years)", colors["secondary"]), ("age_data", "Data Age (years)", colors["tertiary"]),]latest = df_clean[df_clean["year"] == latest_year]for ax, (var, label, color) inzip(axes, age_vars): data = latest[var].dropna() ax.hist(data, bins=30, color=color, alpha=0.7, edgecolor="white") ax.axvline(x=data.median(), color="black", linestyle="--", linewidth=2, label=f"Median: {data.median():.0f}") ax.set_xlabel(label) ax.set_ylabel("Number of Firms") ax.legend()axes[0].set_title("Founding Age")axes[1].set_title("Listing Age")axes[2].set_title("Data Age")plt.suptitle(f"Company Age Distributions ({latest_year})", fontsize=14, y=1.02)plt.tight_layout()plt.show()```## Tuổi và hiệu ứng cổ phần hóaMột đặc điểm riêng của thị trường Việt Nam là việc cổ phần hóa các SOE. Nhiều doanh nghiệp có ngày thành lập sớm hơn thị trường chứng khoán hàng chục năm, tạo ra khoảng cách lớn giữa tuổi thành lập và tuổi niêm yết.```{python}#| label: fig-age-gap#| fig-cap: "Mối quan hệ giữa tuổi thành lập và tuổi niêm yết của các doanh nghiệp Việt Nam. Khoảng cách phản ánh số năm hoạt động trước khi niêm yết, đặc biệt lớn đối với các doanh nghiệp nhà nước đã cổ phần hóa."fig, ax = plt.subplots(figsize=(8, 8))latest = df_clean[df_clean["year"] == latest_year].copy()latest["soe_flag"] = latest["state_ownership_pct"] >30# SOE proxyfor soe, label, color, marker in [ (True, "SOE (>30% state)", colors["quaternary"], "s"), (False, "Non-SOE", colors["primary"], "o"),]: subset = latest[latest["soe_flag"] == soe] ax.scatter( subset["age_listing"], subset["age_founding"], c=color, alpha=0.5, s=25, marker=marker, label=label, edgecolor="white" )# 45-degree linemax_age =max(latest["age_founding"].max(), latest["age_listing"].max())ax.plot([0, max_age], [0, max_age], "k--", alpha=0.3, label="Founding = Listing age")ax.set_xlabel("Listing Age (years)")ax.set_ylabel("Founding Age (years)")ax.set_title("Founding vs. Listing Age: The Equitization Gap")ax.legend()plt.tight_layout()plt.show()```# Phân tích kết hợp: Định giá, kiệt quệ và mức độ trưởng thành {#sec-valuation-joint-analysis}## Mối quan hệ giữa Q, điểm Z và tuổiBa thước đo này phản ánh những khía cạnh khác nhau về vị thế tài chính của doanh nghiệp, nhưng chúng không độc lập với nhau. Về mặt lý thuyết, chúng ta kỳ vọng:- **Q và Z**: Các doanh nghiệp có nhiều cơ hội tăng trưởng (Q cao) thường khỏe mạnh hơn về tài chính (Z cao), nhưng mối quan hệ không đơn điệu, giá trị Q rất cao có thể cho thấy sự định giá quá cao mang tính đầu cơ.- **Q và tuổi**: Các doanh nghiệp trẻ có thể có Q cao hơn (kỳ vọng tăng trưởng) hoặc thấp hơn (mô hình kinh doanh chưa được kiểm chứng). Mối quan hệ phụ thuộc vào vòng đời của ngành.- **Z và tuổi**: Các doanh nghiệp lâu đời thường có lợi nhuận ổn định hơn và lợi nhuận giữ lại cao hơn, góp phần làm điểm Z cao hơn, dù các doanh nghiệp rất lâu đời có thể đối mặt với năng lực cạnh tranh suy giảm.```{python}#| label: fig-joint-analysis#| fig-cap: "Mối quan hệ giữa Q của Tobin, điểm Z của Altman và tuổi công ty đối với các doanh nghiệp niêm yết Việt Nam. Kích thước bong bóng phản ánh tổng tài sản; màu sắc cho biết vùng rủi ro điểm Z'' cho thị trường mới nổi."fig, axes = plt.subplots(1, 3, figsize=(16, 5))sample = latest.dropna(subset=["tobin_q_simple_w", "altman_z_w", "age_founding"])sample = sample.sample(min(300, len(sample)), random_state=42)# Q vs Zaxes[0].scatter( sample["altman_z_w"], sample["tobin_q_simple_w"], c=sample["age_founding"], cmap="viridis", alpha=0.6, s=np.log1p(sample["at"]) *3, edgecolor="white", linewidth=0.3)axes[0].set_xlabel("Altman Z-Score")axes[0].set_ylabel("Tobin's Q")axes[0].set_title("Valuation vs. Distress Risk")axes[0].axhline(y=1, color="gray", linestyle="--", alpha=0.5)axes[0].axvline(x=1.80, color="red", linestyle=":", alpha=0.5)axes[0].axvline(x=2.99, color="green", linestyle=":", alpha=0.5)# Q vs Ageaxes[1].scatter( sample["age_founding"], sample["tobin_q_simple_w"], c=sample["altman_z_w"], cmap="RdYlGn", alpha=0.6, s=np.log1p(sample["at"]) *3, edgecolor="white", linewidth=0.3)axes[1].set_xlabel("Founding Age (years)")axes[1].set_ylabel("Tobin's Q")axes[1].set_title("Valuation vs. Maturity")axes[1].axhline(y=1, color="gray", linestyle="--", alpha=0.5)# Z vs Agescatter = axes[2].scatter( sample["age_founding"], sample["altman_z_w"], c=sample["tobin_q_simple_w"], cmap="coolwarm", alpha=0.6, s=np.log1p(sample["at"]) *3, edgecolor="white", linewidth=0.3)axes[2].set_xlabel("Founding Age (years)")axes[2].set_ylabel("Altman Z-Score")axes[2].set_title("Distress Risk vs. Maturity")axes[2].axhline(y=1.80, color="red", linestyle=":", alpha=0.5)axes[2].axhline(y=2.99, color="green", linestyle=":", alpha=0.5)plt.tight_layout()plt.show()```## Cấu trúc tương quan```{python}#| label: fig-correlation-matrix#| fig-cap: "Ma trận tương quan của các thước đo chính về định giá, kiệt quệ và mức độ trưởng thành đối với các doanh nghiệp niêm yết Việt Nam."corr_vars = ["tobin_q_simple_w", "mtb_w", "altman_z_w", "altman_z_em_w","age_founding", "age_listing","z_x1", "z_x2", "z_x3", "z_x4", "z_x5"]corr_labels = ["Tobin's Q", "M/B Ratio", "Z-Score", "Z'' (EM)","Age (Found.)", "Age (List.)","EBIT/TA", "Sales/TA", "ME/TL", "WC/TA", "RE/TA"]corr_matrix = df_clean[corr_vars].corr()corr_matrix.index = corr_labelscorr_matrix.columns = corr_labelsfig, ax = plt.subplots(figsize=(12, 10))mask = np.triu(np.ones_like(corr_matrix, dtype=bool), k=1)cmap = sns.diverging_palette(250, 15, s=75, l=40, n=9, center="light", as_cmap=True)sns.heatmap( corr_matrix, mask=mask, cmap=cmap, center=0, annot=True, fmt=".2f", square=True, linewidths=0.5, cbar_kws={"shrink": 0.8}, ax=ax, vmin=-1, vmax=1, annot_kws={"size": 9})ax.set_title("Correlation Matrix of Key Financial Measures", fontsize=14, pad=20)plt.tight_layout()plt.show()```## Phân tích hồi quy dữ liệu chéoChúng ta ước lượng một mô hình hồi quy dữ liệu chéo đơn giản để xem xét các yếu tố quyết định Q của Tobin trên thị trường Việt Nam:$$Q_{i,t} = \alpha + \beta_1 \ln(\text{Age}_{i}) + \beta_2 Z''_{i,t} + \beta_3 \text{SOE}_{i} + \beta_4 \ln(\text{TA}_{i,t}) + \varepsilon_{i,t}$$ {#eq-regression-q}```{python}#| label: regression-analysis#| code-summary: "Cross-sectional regression of Tobin's Q"from numpy.linalg import lstsq# Prepare regression datareg_data = latest.dropna( subset=["tobin_q_simple_w", "ln_age_founding", "altman_z_em_w", "at"]).copy()reg_data["ln_at"] = np.log(reg_data["at"])reg_data["soe_dummy"] = (reg_data["state_ownership_pct"] >30).astype(int)reg_data["constant"] =1.0# OLS estimationy = reg_data["tobin_q_simple_w"].valuesX = reg_data[["constant", "ln_age_founding", "altman_z_em_w","soe_dummy", "ln_at"]].valuesbetas, residuals, rank, sv = lstsq(X, y, rcond=None)y_hat = X @ betasresid = y - y_hatn, k = X.shape# Standard errors (heteroskedasticity-robust would be better)sigma2 = np.sum(resid**2) / (n - k)var_beta = sigma2 * np.linalg.inv(X.T @ X)se = np.sqrt(np.diag(var_beta))t_stats = betas / ser_squared =1- np.sum(resid**2) / np.sum((y - y.mean())**2)adj_r2 =1- (1- r_squared) * (n -1) / (n - k -1)# Display resultsvar_names = ["Constant", "ln(Age)", "Z''-Score (EM)", "SOE Dummy", "ln(Total Assets)"]print("="*65)print(" Cross-Sectional Regression: Determinants of Tobin's Q")print(f" Dependent Variable: Tobin's Q (Simple, Winsorized)")print(f" Sample: {n} firms ({latest_year})")print("="*65)print(f" {'Variable':<22}{'Coef':>10}{'Std.Err':>10}{'t-stat':>10}")print("-"*65)for name, b, s, t inzip(var_names, betas, se, t_stats): sig ="***"ifabs(t) >2.576else"**"ifabs(t) >1.96else"*"ifabs(t) >1.645else""print(f" {name:<22}{b:>10.4f}{s:>10.4f}{t:>8.2f}{sig}")print("-"*65)print(f" R-squared: {r_squared:.4f}")print(f" Adjusted R-squared: {adj_r2:.4f}")print(f" Observations: {n}")print("="*65)print(" Significance: *** p<0.01, ** p<0.05, * p<0.10")```# Quy trình hoàn chỉnh {#sec-valuation-pipeline}## Tổng hợp tất cảỞ đây chúng tôi cung cấp một hàm gọn gàng duy nhất nhận dữ liệu tài chính thô từ DataCore.vn và tạo ra bộ dữ liệu hoàn chỉnh với cả ba thước đo đã được tính.```{python}#| label: complete-pipeline#| code-summary: "Complete pipeline for computing Tobin's Q, Z-Score, and Company Age"def compute_valuation_distress_age(df, firm_profiles=None):""" Complete pipeline to compute Tobin's Q, Altman Z-Score variants, and Company Age for Vietnamese listed firms. Parameters ---------- df : pd.DataFrame Panel of firm-year financial data with columns: at, seq, lt, lct, tlb, sale, ebit, ni, re_var, act, ppent, invt, txdb, itcb, pstk, me, prcc, csho, year, ticker firm_profiles : pd.DataFrame, optional Company profiles with founding_year, listing_year Returns ------- pd.DataFrame Input data augmented with computed measures """ result = df.copy()# === Data Quality Filters === result = result[result["at"] >0] result = result[result["seq"] >0]# === Book Value of Equity (Daniel & Titman 1997) === result["pref"] = result["pstk"].fillna(0) result["be"] = ( result["seq"]+ result["txdb"].fillna(0)+ result["itcb"].fillna(0)- result["pref"] )# === Market Value of Equity ===if"me"notin result.columns or result["me"].isna().all(): result["me"] = result["prcc"] * result["csho"]# === Tobin's Q Variants ===# Simple Q (Gompers et al. 2003) result["tobin_q"] = (result["at"] + result["me"] - result["be"]) / result["at"]# Chung-Pruitt Q debt_cp = ( result["lct"].fillna(0) - result["act"].fillna(0)+ result["invt"].fillna(0) + result["lt"].fillna(0) ) result["tobin_q_cp"] = ( (result["me"] + result["pstk"].fillna(0) + debt_cp) / result["at"] )# Market-to-Book result["mtb"] = np.where(result["be"] >0, result["me"] / result["be"], np.nan)# === Altman Z-Score Variants === result["wc"] = result["act"].fillna(0) - result["lct"].fillna(0) x1 = result["ebit"] / result["at"] x2 = result["sale"] / result["at"] x3_market = np.where(result["tlb"] >0, result["me"] / result["tlb"], np.nan) x3_book = np.where(result["tlb"] >0, result["be"] / result["tlb"], np.nan) x4 = result["wc"] / result["at"] x5 = result["re_var"].fillna(0) / result["at"]# Original Z result["altman_z"] =3.3* x1 +0.999* x2 +0.6* x3_market +1.2* x4 +1.4* x5# Z' (private firms) result["altman_z_prime"] = (0.717* x4 +0.847* x5 +3.107* x1 +0.420* x3_book +0.998* x2 )# Z'' (emerging markets) result["altman_z_em"] = (3.25+6.56* x4 +3.26* x5 +6.72* x1 +1.05* x3_book )# Risk zones result["z_zone"] = pd.cut( result["altman_z"], bins=[-np.inf, 1.80, 2.70, 2.99, np.inf], labels=["High Distress", "Distress", "Grey Zone", "Safe"] ) result["z_em_zone"] = pd.cut( result["altman_z_em"], bins=[-np.inf, 1.10, 2.60, np.inf], labels=["Distress", "Grey Zone", "Safe"] )# === Company Age ===if firm_profiles isnotNone: result = result.merge( firm_profiles[["ticker", "founding_year", "listing_year"]], on="ticker", how="left", suffixes=("", "_profile") ) result["age_founding"] = result["year"] - result["founding_year"] result["age_listing"] = (result["year"] - result["listing_year"]).clip(lower=0) first_year = result.groupby("ticker")["year"].transform("min") result["age_data"] = result["year"] - first_year# === Winsorize ===for var in ["tobin_q", "tobin_q_cp", "mtb", "altman_z", "altman_z_prime", "altman_z_em"]:if var in result.columns: result[f"{var}_w"] = winsorize(result[var])return result# Demonstrate the pipelinefinal_df = compute_valuation_distress_age(df, firm_profiles)print(f"Final dataset: {final_df.shape[0]:,} observations, {final_df.shape[1]} variables")print(f"Firms: {final_df['ticker'].nunique()}")print(f"\nKey variables computed:")for var in ["tobin_q", "tobin_q_cp", "mtb", "altman_z", "altman_z_prime","altman_z_em", "age_founding", "age_listing", "age_data"]:if var in final_df.columns: non_null = final_df[var].notna().sum()print(f" {var}: {non_null:,} non-null values")```## Xuất kết quả```{python}#| label: export-results#| code-summary: "Export computed measures to CSV"# Select key output variablesoutput_vars = ["ticker", "year", "datadate", "exchange", "industry","at", "be", "me", "tobin_q", "tobin_q_w", "mtb", "mtb_w","altman_z", "altman_z_w", "altman_z_em", "altman_z_em_w","z_zone", "z_em_zone","age_founding", "age_listing", "age_data","state_ownership_pct"]export_cols = [v for v in output_vars if v in final_df.columns]export_df = final_df[export_cols].copy()# export_df.to_csv("vn_valuation_distress_age.csv", index=False)# export_df.to_parquet("vn_valuation_distress_age.parquet", index=False)print(f"Export dataset: {export_df.shape[0]:,} rows × {export_df.shape[1]} columns")print(f"\nSample output (first 5 rows):")display_cols = ["ticker", "year", "tobin_q", "altman_z", "altman_z_em","z_zone", "age_founding"]display_cols = [c for c in display_cols if c in export_df.columns]print(export_df[display_cols].head().to_string(index=False))```# Các chủ đề đặc biệt cho thị trường Việt Nam {#sec-valuation-special-topics}## Sở hữu nhà nước và định giáSở hữu nhà nước là đặc điểm nổi bật của bức tranh doanh nghiệp Việt Nam. Chúng ta xem xét sở hữu nhà nước ảnh hưởng thế nào đến cả Q của Tobin lẫn rủi ro kiệt quệ tài chính.```{python}#| label: fig-soe-analysis#| fig-cap: "Mối quan hệ giữa tỷ lệ sở hữu nhà nước và các thước đo định giá/kiệt quệ của doanh nghiệp. Biểu đồ bên trái thể hiện Q của Tobin theo sở hữu nhà nước, với đường làm trơn LOWESS. Biểu đồ bên phải thể hiện điểm Z'' theo tứ phân vị sở hữu nhà nước."fig, axes = plt.subplots(1, 2, figsize=(14, 6))latest = final_df[final_df["year"] == latest_year].dropna( subset=["tobin_q_w", "altman_z_em_w", "state_ownership_pct"])# Q vs State Ownershipaxes[0].scatter( latest["state_ownership_pct"], latest["tobin_q_w"], alpha=0.4, s=20, color=colors["primary"], edgecolor="white")# Binned meansbins = pd.cut(latest["state_ownership_pct"], bins=10)binned = latest.groupby(bins)["tobin_q_w"].mean()bin_centers = [(b.left + b.right) /2for b in binned.index]axes[0].plot(bin_centers, binned.values, color=colors["quaternary"], linewidth=3, label="Binned Mean")axes[0].set_xlabel("State Ownership (%)")axes[0].set_ylabel("Tobin's Q")axes[0].set_title("State Ownership and Firm Valuation")axes[0].axhline(y=1, color="gray", linestyle="--", alpha=0.5)axes[0].legend()# Z''-Score by SOE quartilelatest["soe_quartile"] = pd.qcut( latest["state_ownership_pct"], q=4, labels=["Q1 (Low)", "Q2", "Q3", "Q4 (High)"], duplicates="drop")soe_groups = latest.groupby("soe_quartile")["altman_z_em_w"]box_data = [group.values for name, group in soe_groups]bp = axes[1].boxplot( box_data, labels=[name for name, _ in soe_groups], patch_artist=True, medianprops=dict(color="black", linewidth=2))gradient_colors = plt.cm.Blues(np.linspace(0.3, 0.8, len(bp["boxes"])))for patch, color inzip(bp["boxes"], gradient_colors): patch.set_facecolor(color)axes[1].axhline(y=2.60, color="green", linestyle=":", alpha=0.5, label="Safe threshold")axes[1].axhline(y=1.10, color="red", linestyle=":", alpha=0.5, label="Distress threshold")axes[1].set_xlabel("State Ownership Quartile")axes[1].set_ylabel("Z''-Score (Emerging Market)")axes[1].set_title("Financial Health by State Ownership")axes[1].legend(fontsize=9)plt.tight_layout()plt.show()```## Phân tích theo sàn giao dịch```{python}#| label: tbl-exchange-summary#| tbl-cap: "Thống kê mô tả theo sàn giao dịch đối với các doanh nghiệp niêm yết Việt Nam (năm gần nhất)"exchange_summary = ( latest .groupby("exchange") .agg( n_firms=("ticker", "nunique"), median_q=("tobin_q_w", "median"), mean_q=("tobin_q_w", "mean"), median_z=("altman_z_w", "median"), mean_z_em=("altman_z_em_w", "mean"), pct_distress_z=("z_zone", lambda x: (x =="High Distress").mean() *100), pct_distress_em=("z_em_zone", lambda x: (x =="Distress").mean() *100), median_age=("age_founding", "median"), median_soe=("state_ownership_pct", "median"), ) .round(2))exchange_summary.columns = ["N Firms", "Median Q", "Mean Q", "Median Z", "Mean Z'' (EM)","% Distress (Z)", "% Distress (Z'')", "Median Age", "Median SOE %"]exchange_summary.style.set_properties(**{"text-align": "center","font-size": "10pt"}).set_table_styles([ {"selector": "th", "props": [ ("background-color", "#1f77b4"), ("color", "white"), ("text-align", "center"), ("padding", "8px") ]},]).format({"Median Q": "{:.2f}", "Mean Q": "{:.2f}","Median Z": "{:.2f}", "Mean Z'' (EM)": "{:.2f}","% Distress (Z)": "{:.1f}%", "% Distress (Z'')": "{:.1f}%","Median Age": "{:.0f}", "Median SOE %": "{:.1f}%"})```## Bản đồ nhiệt theo ngành: Định giá và kiệt quệ```{python}#| label: fig-sector-heatmap#| fig-cap: "Q của Tobin và điểm Z'' trung vị theo ngành và năm đối với các doanh nghiệp niêm yết Việt Nam. Màu ấm hơn biểu thị giá trị cao hơn."fig, axes = plt.subplots(1, 2, figsize=(16, 8))# Tobin's Q heatmapq_pivot = ( final_df .groupby(["industry", "year"])["tobin_q_w"] .median() .unstack(fill_value=np.nan))sns.heatmap( q_pivot, cmap="RdYlGn", center=1, ax=axes[0], cbar_kws={"label": "Median Q", "shrink": 0.8}, linewidths=0.5, linecolor="white", xticklabels=2)axes[0].set_title("Tobin's Q by Industry and Year")axes[0].set_xlabel("Year")axes[0].set_ylabel("")# Z''-Score heatmapz_pivot = ( final_df .groupby(["industry", "year"])["altman_z_em_w"] .median() .unstack(fill_value=np.nan))sns.heatmap( z_pivot, cmap="RdYlGn", center=2.6, ax=axes[1], cbar_kws={"label": "Median Z''", "shrink": 0.8}, linewidths=0.5, linecolor="white", xticklabels=2)axes[1].set_title("Z''-Score (EM) by Industry and Year")axes[1].set_xlabel("Year")axes[1].set_ylabel("")plt.tight_layout()plt.show()```## Xử lý các doanh nghiệp bị hủy niêm yết: Thiên kiến sống sótMột vấn đề then chốt khi đo lường kiệt quệ tài chính là thiên kiến sống sót. Nếu chỉ phân tích các doanh nghiệp hiện đang niêm yết, chúng ta bỏ sót chính những doanh nghiệp mà điểm Z được thiết kế để nhận diện, tức những doanh nghiệp đã phá sản hoặc bị hủy niêm yết.```{python}#| label: survivorship-bias#| code-summary: "Analysis of delisted firms and survivorship bias"# Simulate delisting data (replace with DataCore.vn delisting records)np.random.seed(123)n_delisted =50delisted_firms = pd.DataFrame({"ticker": [f"VN{str(i).zfill(4)}"for i inrange(n_firms +1, n_firms + n_delisted +1)],"delist_year": np.random.randint(2010, 2024, n_delisted),"delist_reason": np.random.choice( ["Bankruptcy/Liquidation", "Merger/Acquisition", "Voluntary Delisting","Regulatory Non-compliance", "Below Minimum Requirements"], n_delisted, p=[0.15, 0.25, 0.20, 0.20, 0.20] )})# Summary of delisting reasonsprint("Delisting Reasons Summary")print("="*50)reason_counts = delisted_firms["delist_reason"].value_counts()for reason, count in reason_counts.items():print(f" {reason}: {count} ({count/n_delisted*100:.0f}%)")print(f"\nTotal delisted: {n_delisted}")print(f"Currently listed: {final_df['ticker'].nunique()}")print(f"\nSurvivorship rate: "f"{final_df['ticker'].nunique()/(final_df['ticker'].nunique()+n_delisted)*100:.1f}%")```# Kiểm tra độ vững và mở rộng {#sec-valuation-robustness}## Các cách xác định Q của Tobin thay thế```{python}#| label: fig-q-variants-comparison#| fig-cap: "So sánh các biến thể của Q của Tobin: Q đơn giản (Gompers et al. 2003) so với xấp xỉ Chung-Pruitt. Tương quan cao ủng hộ việc sử dụng thước đo đơn giản hơn."fig, ax = plt.subplots(figsize=(7, 7))sample = latest.dropna(subset=["tobin_q_w", "tobin_q_cp"]).copy()sample["tobin_q_cp_w"] = winsorize(sample["tobin_q_cp"])ax.scatter( sample["tobin_q_w"], sample["tobin_q_cp_w"], alpha=0.4, s=15, color=colors["primary"], edgecolor="white")# 45-degree linelims = [min(ax.get_xlim()[0], ax.get_ylim()[0]),max(ax.get_xlim()[1], ax.get_ylim()[1])]ax.plot(lims, lims, "k--", alpha=0.3)corr = sample["tobin_q_w"].corr(sample["tobin_q_cp_w"])ax.text(0.05, 0.95, f"Correlation: {corr:.3f}", transform=ax.transAxes, fontsize=12, verticalalignment="top", bbox=dict(boxstyle="round", facecolor="wheat", alpha=0.5))ax.set_xlabel("Simple Q (Gompers et al.)")ax.set_ylabel("Chung-Pruitt Q")ax.set_title("Comparison of Tobin's Q Variants")plt.tight_layout()plt.show()```## Các thước đo điều chỉnh theo ngànhQ của Tobin và điểm Z thô có thể phản ánh đặc điểm ngành hơn là thuộc tính riêng của doanh nghiệp. Chúng ta tính các phiên bản điều chỉnh theo ngành:$$Q^{\text{adj}}_{i,t} = Q_{i,t} - \overline{Q}_{j(i),t}$$ {#eq-industry-adj-q}trong đó $\overline{Q}_{j(i),t}$ là Q của Tobin trung vị của ngành $j$ mà doanh nghiệp $i$ thuộc về trong năm $t$.```{python}#| label: industry-adjusted#| code-summary: "Industry-adjusted measures"def industry_adjust(df, var, group_var="industry"):"""Compute industry-adjusted measure (deviation from industry median).""" industry_median = df.groupby(["year", group_var])[var].transform("median")return df[var] - industry_medianfinal_df["tobin_q_adj"] = industry_adjust(final_df, "tobin_q_w")final_df["altman_z_em_adj"] = industry_adjust(final_df, "altman_z_em_w")latest_adj = final_df[final_df["year"] == latest_year]print("Industry-Adjusted Measures (Latest Year)")print(f" Tobin's Q (adjusted): mean={latest_adj['tobin_q_adj'].mean():.4f}, "f"std={latest_adj['tobin_q_adj'].std():.3f}")print(f" Z''-Score (adjusted): mean={latest_adj['altman_z_em_adj'].mean():.4f}, "f"std={latest_adj['altman_z_em_adj'].std():.3f}")```## Hồi quy dữ liệu bảng với hiệu ứng cố địnhĐể phân tích chặt chẽ hơn, chúng ta ước lượng một mô hình dữ liệu bảng với hiệu ứng cố định theo doanh nghiệp và theo năm:$$Q_{i,t} = \alpha_i + \gamma_t + \beta_1 Z''_{i,t} + \beta_2 \ln(\text{Age}_{i,t}) + \beta_3 \text{Size}_{i,t} + \varepsilon_{i,t}$$ {#eq-panel-regression}```{python}#| label: panel-regression#| code-summary: "Panel regression with year and industry fixed effects"# Simplified within-estimator (year and industry demeaning)panel = final_df.dropna( subset=["tobin_q_w", "altman_z_em_w", "age_founding", "at"]).copy()panel["ln_at"] = np.log(panel["at"])panel["ln_age"] = np.log1p(panel["age_founding"])# Demean by year-industry (proxy for fixed effects)fe_vars = ["tobin_q_w", "altman_z_em_w", "ln_age", "ln_at"]for var in fe_vars: group_mean = panel.groupby(["year", "industry"])[var].transform("mean") panel[f"{var}_dm"] = panel[var] - group_mean# OLS on demeaned datay = panel["tobin_q_w_dm"].valuesX = np.column_stack([ np.ones(len(panel)), panel["altman_z_em_w_dm"].values, panel["ln_age_dm"].values, panel["ln_at_dm"].values,])betas, _, _, _ = lstsq(X, y, rcond=None)y_hat = X @ betasresid = y - y_hatn, k = X.shapesigma2 = np.sum(resid**2) / (n - k)var_beta = sigma2 * np.linalg.inv(X.T @ X)se = np.sqrt(np.diag(var_beta))t_stats = betas / ser_squared =1- np.sum(resid**2) / np.sum((y - y.mean())**2)var_names = ["Constant", "Z''-Score (EM)", "ln(Age)", "ln(Total Assets)"]print("="*65)print(" Panel Regression: Tobin's Q with Year-Industry FE")print(f" (Within estimator via year×industry demeaning)")print("="*65)print(f" {'Variable':<22}{'Coef':>10}{'Std.Err':>10}{'t-stat':>10}")print("-"*65)for name, b, s, t inzip(var_names, betas, se, t_stats): sig ="***"ifabs(t) >2.576else"**"ifabs(t) >1.96else"*"ifabs(t) >1.645else""print(f" {name:<22}{b:>10.4f}{s:>10.4f}{t:>8.2f}{sig}")print("-"*65)print(f" R-squared (within): {r_squared:.4f}")print(f" Observations: {n:,}")print("="*65)```# Giải quyết kiệt quệ: Chế độ pháp lý đằng sau điểm Z {#sec-valuation-resolution}## Điểm Z thực sự dự báo điều gìHàm phân biệt của @altman1968financial được ước lượng trên một mẫu ghép cặp gồm các doanh nghiệp đã nộp và chưa nộp đơn phá sản. Do đó, sự kiện mà nó chấm điểm là *việc bước vào một thủ tục pháp lý cụ thể*, chứ không phải cái chết về mặt kinh tế, và càng không phải mức tổn thất khi xảy ra kiệt quệ. Sự phân biệt này dễ bị bỏ qua vì các vùng diễn giải trong @tbl-zscore-zones được diễn đạt bằng ngôn ngữ xác suất thất bại, nhưng đối với bất kỳ ai định giá một quyền đòi đối với doanh nghiệp, đối tượng liên quan là$$\mathbb{E}[\text{Loss}_i] \;=\; \underbrace{\Pr(\text{distress}_i)}_{\text{what } Z \text{ scores}} \times \underbrace{\mathbb{E}\!\left[\text{Loss}_i \mid \text{distress}_i\right]}_{\text{set by the insolvency regime}} .$$ {#eq-loss-decomposition}Nhân tố thứ hai không phải là thuộc tính của doanh nghiệp. Nó là thuộc tính của các quy tắc quy định ai kiểm soát một doanh nghiệp kiệt quệ, chi phí tái cơ cấu là bao nhiêu, chủ nợ có thể buộc thanh lý hay không, và chủ sở hữu hiện hữu có thể giữ lại vốn chủ sở hữu hay không. Việc chuyển một hàm phân biệt được ước lượng ở một khu vực pháp lý sang nơi khác đồng nghĩa với việc chuyển theo một nhân tố thứ hai ngầm định. Việc nhân tố thứ hai thực sự thay đổi đã được ghi nhận rõ: @davydenko2008bankruptcy cho thấy các vụ vỡ nợ đối với các khoản vay tương tự ở Pháp, Đức và Anh được giải quyết khác nhau đến mức các ngân hàng điều chỉnh yêu cầu tài sản đảm bảo theo bộ luật, và @schoenherr2022when chứng minh cả về lý thuyết lẫn thực nghiệm rằng mức độ thân thiện tối ưu đối với con nợ phụ thuộc vào môi trường xung quanh chứ không phải là một hằng số phổ quát.Đối với nghiên cứu về Việt Nam, điều này quan trọng gấp đôi. Các hệ số của điểm Z'' được sử dụng trong @sec-valuation-zscore-computation được hiệu chỉnh bên ngoài Việt Nam, và phân phối kết cục mà chúng ngầm định lấy làm điều kiện được tạo ra bởi một hệ thống phá sản mà Việt Nam không có.## Thí nghiệm Subchapter V {#sec-valuation-subchapterv}@hotchkiss2026can cung cấp bằng chứng gần đây rõ ràng nhất rằng nhân tố thứ hai trong @eq-loss-decomposition là một lựa chọn chính sách chứ không phải một hằng số công nghệ, và họ làm điều đó ở phân khúc mà câu hỏi này gay gắt nhất: các doanh nghiệp nhỏ.Thực tế cách điệu hóa (stylized fact) làm động lực cho bài nghiên cứu lại đảo ngược thực tế quen thuộc. Đối với các công ty đại chúng lớn của Hoa Kỳ, các vụ thanh lý theo Chapter 11 hiếm khi xảy ra và hầu hết các doanh nghiệp nộp đơn thoát ra với một phần hoặc toàn bộ hoạt động còn nguyên vẹn. Đối với doanh nghiệp nhỏ, bức tranh đảo ngược: 70% doanh nghiệp nhỏ bước vào thủ tục phá sản giai đoạn 2010-2019 nộp đơn thẳng vào thanh lý theo Chapter 7, và trong số những doanh nghiệp đã vào Chapter 11, chỉ khoảng một phần ba được xác nhận kế hoạch. Phần còn lại bị chuyển sang Chapter 7 hoặc bị tòa bác đơn. Việc bị bác đơn không phải là một cú hạ cánh mềm, vì doanh nghiệp quay lại với các chủ nợ mà không được xóa nợ và thường ngừng hoạt động [@morrison2007bankruptcy; @iverson2018get].Ba ma sát giải thích khoảng cách này. Thứ nhất, các chi phí trực tiếp của Chapter 11 phần lớn là cố định, nên chúng trở nên quá nặng nề so với một cơ sở tài sản nhỏ [@bris2006costs; @dou2021dissecting]. Thứ hai, nguyên tắc ưu tiên tuyệt đối xóa sạch vốn chủ sở hữu trước phá sản, nhưng trong một doanh nghiệp nhỏ, các mối quan hệ của chủ sở hữu kiêm nhà quản lý với nhà cung cấp và khách hàng thường *chính là* giá trị hoạt động liên tục; các chủ nợ kiêm chủ sở hữu mới không thể dễ dàng thay thế những gì họ vừa tước đoạt, và các chủ nợ thương mại cùng các ngân hàng địa phương hiếm khi muốn nắm giữ vốn chủ sở hữu ngay từ đầu. Thứ ba, các chủ nợ phân tán với thứ tự ưu tiên khác nhau tạo ra các vấn đề phối hợp, và một chủ nợ có bảo đảm ưu tiên với khoản nợ nhỏ thường thích phát mại nhanh hơn một kế hoạch được thương lượng, ngay cả khi việc tiếp tục hoạt động có giá trị hơn xét trên tổng thể.Đạo luật Tái cơ cấu Doanh nghiệp Nhỏ năm 2019 (Small Business Reorganization Act of 2019) đã tạo ra Subchapter V của Chapter 11, có hiệu lực từ ngày 19 tháng 2 năm 2020, giải quyết đồng thời cả ba ma sát này đối với các con nợ có tổng nợ không phụ thuộc điều kiện và đã xác định không vượt quá \$7.5 triệu. Mức trần để đủ điều kiện ban đầu là \$2.725 triệu và được CARES Act nâng lên \$7.5 triệu vào ngày 27 tháng 3 năm 2020, một tháng sau khi thủ tục này mở ra. Ba thay đổi then chốt là: một kế hoạch có thể được xác nhận bất chấp sự phản đối của chủ nợ mà không xóa bỏ vốn chủ sở hữu của chủ doanh nghiệp, với điều kiện doanh nghiệp cam kết dành thu nhập khả dụng dự kiến của mình để trả nợ trong ba đến năm năm; ủy ban chủ nợ và bản công bố thông tin không còn bắt buộc; và một người được ủy thác Subchapter V được chỉ định để hòa giải thay vì thay thế ban quản lý.Chính mức trần đủ điều kiện khiến đây trở thành một thí nghiệm chứ không phải một giai thoại. @tbl-subv-estimates tổng hợp các ước lượng chính.| Kết cục | Thiết kế | Ước lượng | Mức tham chiếu ||:---|:---|---:|:---|| Kế hoạch được xác nhận | OLS, 6,431 vụ dưới \$15m | $+18.4$ pp | tỷ lệ cơ sở $31.9\%$ || Kế hoạch được xác nhận | Fuzzy RDD, \$4--11m ($n=999$) | $+32.0$ pp | $17.3\%$ đối với không thuộc SubV || Kế hoạch được xác nhận | Fuzzy RDD, \$6--9m | $+49.5$ pp | $17.3\%$ đối với không thuộc SubV || Kế hoạch được xác nhận | DiD, ý định điều trị | $+12.5$ pp | ---|| Số ngày đến khi xác nhận | OLS / fuzzy RDD | $-24\%$ / $-35\%$ | trung bình 319 ngày || Tỷ lệ thu hồi của chủ nợ không bảo đảm | Fuzzy RDD | $+11.9$ pp | ---|| Khả năng tồn tại sau phá sản | Fuzzy RDD, \$4--11m | $+21$ pp | không có ý nghĩa ở \$6--9m |: Tác động ước lượng của điều kiện đủ hưởng Subchapter V đối với kết cục Chapter 11 của doanh nghiệp nhỏ, từ @hotchkiss2026can. "pp" là điểm phần trăm. Giai đoạn một là mức nhảy $41.9$ pp trong việc sử dụng Subchapter V tại ngưỡng ($F = 71.2$) ở băng thông rộng và $37.1$ pp ($F = 19.7$) ở băng thông hẹp. {#tbl-subv-estimates}Hai đặc điểm của bảng này đáng được nhấn mạnh, ngoài các con số riêng lẻ.Thứ nhất là tác động rất lớn so với tỷ lệ cơ sở. Một doanh nghiệp ngay dưới ngưỡng có xác suất tái cơ cấu cao gấp hơn hai lần so với một doanh nghiệp tương tự ngay trên ngưỡng. Trong khoảng này, việc một doanh nghiệp nhỏ kiệt quệ có tồn tại được hay không phụ thuộc vào thủ tục mà nó được phép sử dụng nhiều hơn là bất cứ điều gì trên bảng cân đối kế toán. Hệ quả đối với @eq-loss-decomposition là nhân tố tổn thất có điều kiện là một tham số chính sách.Thứ hai là phản bác hiển nhiên không đứng vững. Một chế độ cho phép chủ sở hữu giữ vốn chủ sở hữu bất chấp sự phản đối của chủ nợ, theo lập luận chuẩn, sẽ giữ cho các doanh nghiệp không khả thi tiếp tục tồn tại gây thiệt hại cho chủ nợ; hiệu quả hoạt động kém sau phá sản của các doanh nghiệp lớn đã thoát khỏi thủ tục phá sản từ lâu đã được xem là bằng chứng cho chính thiên lệch duy trì hoạt động đó [@hotchkiss1995postbankruptcy; @morrison2007bankruptcy]. Ở đây, tỷ lệ thu hồi kỳ vọng của chủ nợ không bảo đảm *tăng* 11.9 điểm phần trăm và khả năng tồn tại sau phá sản tăng lên chứ không giảm. Lợi ích từ việc tránh một cuộc thanh lý tốn kém dường như được chia sẻ chứ không bị tái phân phối, đúng như kỳ vọng nếu tỷ lệ thanh lý trước cải cách phản ánh chi phí giao dịch và thất bại phối hợp chứ không phải việc phân loại đúng giữa doanh nghiệp khả thi và không khả thi.## Đọc bằng chứng từ góc nhìn Việt NamBốn hàm ý được áp dụng sang bối cảnh Việt Nam, nhưng không hàm ý nào áp dụng một cách máy móc.**Vùng kiệt quệ mang một ý nghĩa khác ở đây.** Khung pháp lý chính thức về mất khả năng thanh toán của Việt Nam là Luật Phá sản số 51/2014/QH13, có hiệu lực từ ngày 1 tháng 1 năm 2015, quy định cả thủ tục phục hồi kinh doanh và thanh lý. Tuy nhiên, như đã trình bày trong @sec-missing-delisting, các trường hợp rời khỏi nhóm doanh nghiệp niêm yết Việt Nam quan sát được chủ yếu là hủy niêm yết bắt buộc do lỗ vượt vốn điều lệ, không nộp báo cáo tài chính và xử lý vi phạm của cơ quan quản lý, chứ không phải các thủ tục tái cơ cấu dưới sự giám sát của tòa án tạo ra một tỷ lệ thu hồi quan sát được. Do đó, nội dung thực nghiệm của điểm Z'' dưới 1.10 ở Việt Nam gần với "kỳ vọng bị hủy niêm yết và lợi nhuận cuối kỳ âm lớn" hơn là "kỳ vọng một quy trình có giám sát với tỷ lệ thu hồi của chủ nợ đo lường được". Đây chính là lý do việc ước tính lợi nhuận hủy niêm yết trong @sec-missing-delisting không phải là một chi tiết kỹ thuật: đối với các doanh nghiệp Việt Nam, nó đang làm công việc mà hồ sơ vụ án của tòa án phá sản đảm nhiệm trong dữ liệu của Hoa Kỳ.**Việt Nam không có cơ sở dữ liệu tương đương FJC.** Thiết kế của Hotchkiss--Iverson--Zheng dựa trên một cuộc điều tra toàn bộ công khai, ở cấp độ từng vụ việc, về các hồ sơ nộp đơn với nợ phải trả được ghi nhận tại thời điểm nộp đơn, bổ sung bằng các bảng kê thu thập thủ công từ hồ sơ tòa án. Việt Nam không có dữ liệu nào tương đương, và việc xây dựng nó sẽ là một đóng góp nghiên cứu độc lập. Cho đến khi nó tồn tại, nghiên cứu kiệt quệ tài chính ở Việt Nam phần lớn bị giới hạn trong nhóm doanh nghiệp niêm yết, vốn là lát cắt *kém* đại diện nhất của tổng thể doanh nghiệp nhỏ mà lý thuyết hướng đến.**Ma sát tái triển khai tài sản có thể lớn hơn.** @bernstein2019asset cho thấy tài sản của các doanh nghiệp nhỏ bị thanh lý ở Hoa Kỳ được tái triển khai kém và cuối cùng bị sử dụng dưới công suất, đó là cơ chế khiến việc thanh lý quá mức gây tốn kém cho xã hội. Thị trường thứ cấp mỏng đối với thiết bị vốn đã qua sử dụng và sự phức tạp về hành chính khi chuyển nhượng quyền sử dụng đất khiến ma sát này nhiều khả năng nghiêm trọng hơn ở Việt Nam, dù chúng tôi không biết có ước lượng trực tiếp nào.**Dư địa cải cách vẫn còn rộng mở.** @hotchkiss2026can ghi nhận rằng ít nhất mười một quốc gia đã áp dụng các thủ tục mất khả năng thanh toán đơn giản hóa cho doanh nghiệp nhỏ trong thập kỷ qua, một số trong khu vực, và @gurrea2024reinventing khảo sát cải cách mất khả năng thanh toán ở các nền kinh tế mới nổi một cách cụ thể. Việt Nam không nằm trong nhóm áp dụng. Đối với nhà nghiên cứu, điều này có hai mặt: không có thí nghiệm tự nhiên sẵn có kiểu này ở Việt Nam để khai thác, nhưng câu hỏi đánh giá ex-ante hoàn toàn bỏ ngỏ và khuôn mẫu nhận diện dưới đây có thể chuyển giao.## Quy tắc ngưỡng như thiết kế nghiên cứu {#sec-valuation-threshold-designs}Nội dung phương pháp luận của @hotchkiss2026can đáng được tách khỏi nội dung thể chế, vì các ngưỡng đủ điều kiện có ở khắp nơi trong quy định của Việt Nam và thiết kế này có thể chuyển giao ngay cả khi nội dung cụ thể thì không.### Gián đoạn hồi quy mờ (Fuzzy Regression Discontinuity)Điều kiện đủ hưởng là một hàm tất định của biến chạy, nhưng *việc tham gia* thì không: 39% doanh nghiệp đủ điều kiện trong mẫu của bài nghiên cứu vẫn chọn Chapter 11 truyền thống, và một số ít doanh nghiệp có vẻ không đủ điều kiện đã được chấp nhận sau khi tòa án phân loại lại một phần nợ phải trả của họ thành nợ phụ thuộc điều kiện. Do đó, việc điều trị nhảy tại ngưỡng mà không đi từ không lên một, đó là trường hợp mờ. Đặt $s_i = L_i - c$ cho biến chạy đã được dời gốc về ngưỡng và $B_i = \mathbf{1}\{s_i \leq 0\}$ cho điều kiện đủ hưởng. Thiết kế là bình phương tối thiểu hai giai đoạn với $B_i$ là biến công cụ bị loại trừ:$$D_i = \alpha + \pi B_i + f(s_i) + B_i \cdot g(s_i) + X_i'\gamma + u_i$$ {#eq-rdd-first-stage}$$y_i = \tilde{\alpha} + \beta \widehat{D}_i + \tilde{f}(s_i) + B_i \cdot \tilde{g}(s_i) + X_i'\tilde{\gamma} + \varepsilon_i$$ {#eq-rdd-second-stage}trong đó $D_i$ chỉ thị việc sử dụng thực tế thủ tục đơn giản hóa, còn $f$ và $g$ là các đa thức bậc thấp được ước lượng riêng ở mỗi phía của ngưỡng [@imbens2008regression; @lee2010regression]. Trong trường hợp vừa đủ nhận diện, $\beta$ bằng tỷ số giữa mức nhảy dạng rút gọn của $y$ và mức nhảy giai đoạn một $\pi$, đó là dạng Wald của bộ ước lượng và là cách hữu ích nhất để đọc nó. Điều $\beta$ nhận diện là một tác động điều trị trung bình cục bộ: tác động đối với các doanh nghiệp gần ngưỡng sử dụng thủ tục *vì* họ đủ điều kiện. Đó không phải là tác động đối với một doanh nghiệp có nợ phải trả \$1 triệu, và cũng không phải là tác động của việc bắt buộc áp dụng thủ tục.### Điều gì làm thiết kế đáng tin cậyBốn kiểm tra đảm nhiệm vai trò này, và cả bốn đều được báo cáo trong bài nghiên cứu.1. **Tính liên tục của mật độ.** Nếu các doanh nghiệp thao túng biến chạy để đủ điều kiện, mật độ của $s_i$ nhảy tại ngưỡng và phép so sánh diễn ra giữa các nhóm tự chọn. Kiểm định @mccrary2008manipulation không tìm thấy sự gián đoạn ($p = 0.25$). Lập luận thể chế củng cố lập luận thống kê: một doanh nghiệp kiệt quệ không thể dễ dàng thanh toán nợ để xuống dưới một mức trần, và bản thân mức trần được nâng lên bất ngờ một tháng sau khi thủ tục mở ra.2. **Tính trơn của các hiệp biến.** Đòn bẩy, tỷ trọng nợ có bảo đảm, tổng tài sản, tình trạng nộp đơn chung và số lượng chủ nợ đều liên tục qua ngưỡng, cả riêng lẻ lẫn đồng thời.3. **Độ vững theo đặc tả donut-hole.** Loại bỏ các vụ việc trong dải \$7--7.5 triệu, nơi mọi sự thao túng sẽ tập trung, hầu như không làm thay đổi các hệ số.4. **Độ nhạy theo băng thông, được báo cáo trung thực.** Tác động xác nhận là $+32.0$ pp trong khoảng \$4--11 triệu và $+49.5$ pp trong khoảng \$6--9 triệu. Thu hẹp cửa sổ củng cố nhận diện nhưng làm giảm sức mạnh thống kê, và bài nghiên cứu cho thấy cả hai mặt của sự đánh đổi đó: ước lượng điểm tăng, nhưng tác động lên khả năng tồn tại có ý nghĩa ở cửa sổ rộng lại không có ý nghĩa ở cửa sổ hẹp. Báo cáo đường đi của băng thông không phải là một nghi thức kiểm tra độ vững; nó là kết quả chính. Lựa chọn băng thông theo dữ liệu với suy luận hiệu chỉnh thiên lệch [@calonico2014robust] là phần bổ sung tự nhiên, không phải là sự thay thế cho việc trình bày đường đi đó.Có một mối đe dọa mà không kiểm tra nội bộ nào có thể giải quyết, đó là sự chọn lọc vào chính mẫu. Nếu điều kiện đủ hưởng khiến các doanh nghiệp lẽ ra sẽ tái cơ cấu ngoài tòa phải nộp đơn, thì phép so sánh bị nhiễm ngay cả khi có sự gián đoạn hoàn hảo. Phản hồi của bài nghiên cứu là một khuôn mẫu hữu ích: thay vì bác bỏ mối đe dọa bằng lập luận, nó định lượng mức độ chọn lọc cần thiết để lật ngược kết quả, và cho thấy việc loại bỏ ngẫu nhiên 29 vụ Subchapter V tái cơ cấu làm ước lượng chuyển từ 32.0 sang 29.1 điểm phần trăm, trong khi để đưa nó về không cần loại bỏ ít nhất 120 vụ.### Sai biệt trong sai biệt như ý định điều trịVì thủ tục này chưa tồn tại trước tháng 2 năm 2020, cùng một ngưỡng hỗ trợ một thiết kế thứ hai,$$y_i = \alpha + \beta_1 \text{Treated}_i + \beta_2 \text{Post}_t + \beta_3\,(\text{Treated}_i \times \text{Post}_t) + X_i'\gamma + \varepsilon_i$$ {#eq-did-subv}với các doanh nghiệp dưới mức trần là nhóm được điều trị và các doanh nghiệp ngay trên mức trần là nhóm đối chứng chưa bao giờ được điều trị. Ở đây $\beta_3$ là tác động ý định điều trị, và nó nhỏ hơn ước lượng RDD vì hai lý do cộng dồn: không phải mọi doanh nghiệp đủ điều kiện đều sử dụng thủ tục, và mẫu trước năm 2020 chỉ có thể được chia theo *tổng* nợ phải trả chứ không phải nợ không phụ thuộc điều kiện, nên một số doanh nghiệp thực sự đủ điều kiện bị phân loại nhầm vào nhóm đối chứng. Sự đối chiếu này rất đáng học hỏi. Chia ITT là 12.5 điểm phần trăm cho giai đoạn một là 42 điểm phần trăm cho ra 29.8, gần với ước lượng RDD là 32.0. Một ITT và một LATE trông không nhất quán thường là cùng một tham số chia cho các mẫu số khác nhau.### Điều chỉnh thiết kế cho Việt NamQuy định của Việt Nam có rất nhiều quy tắc ranh giới rõ ràng: các điều kiện niêm yết và hủy niêm yết gắn với lỗ lũy kế so với vốn điều lệ, với số năm thua lỗ liên tiếp và với ý kiến kiểm toán; các định nghĩa dựa trên quy mô quyết định khả năng tiếp cận các chương trình hỗ trợ và ưu đãi thuế; trần sở hữu nước ngoài. Mỗi quy tắc đều là một ứng viên cho biến chạy (forcing variable).Lời cảnh báo là kiểm định thao túng, vốn gần như một thủ tục hình thức trong @hotchkiss2026can, trở thành yếu tố then chốt ở đây. Một doanh nghiệp Hoa Kỳ kiệt quệ không thể dễ dàng trả bớt nợ để lọt xuống dưới mức trần nợ phải trả. Một doanh nghiệp Việt Nam tiến gần ngưỡng được xác định theo lỗ lũy kế, doanh thu hoặc số lao động *được báo cáo* thường có thể làm được, và các động cơ quản trị dồn tích được ghi nhận trong chương quản trị lợi nhuận cung cấp cả động cơ lẫn phương tiện. Bất kỳ RDD nào của Việt Nam xây dựng trên một ngưỡng kế toán đều cần kiểm định mật độ, một đặc tả donut-hole (loại bỏ các quan sát sát ngưỡng) và một lập luận về lý do ngày báo cáo đi trước việc doanh nghiệp biết đến quy tắc --- và cần sẵn sàng kết luận rằng thiết kế không hiệu quả. Các quy tắc ngưỡng cũng thay đổi; nội dung chính xác và ngày có hiệu lực của thông tư điều chỉnh phải được đối chiếu với giai đoạn mẫu chứ không được mặc định.## Triển khai: Fuzzy RDD từ đầu {#sec-valuation-rdd-implementation}Không tồn tại bảng dữ liệu phá sản cấp vụ việc nào của Việt Nam, vì vậy chúng ta mô phỏng một bảng mà quá trình sinh dữ liệu được hiệu chỉnh theo các ước lượng trong @tbl-subv-estimates: tỷ lệ xác nhận cơ sở $17\%$, tỷ lệ tham gia khoảng $60\%$ trong số các doanh nghiệp đủ điều kiện, và tác động cục bộ thực là $32$ điểm phần trăm. Vì biết trước giá trị thực, bộ ước lượng có thể được kiểm tra so với nó, và vấn đề chọn lọc thúc đẩy thiết kế này có thể được cố ý đưa vào. Độ phức tạp vụ việc không quan sát được làm tăng tỷ lệ tham gia và giảm xác suất xác nhận cơ sở, nên phép so sánh ngây thơ giữa doanh nghiệp sử dụng và không sử dụng thủ tục bị chệch *xuống dưới* --- cùng chiều mà @hotchkiss2026can lập luận là áp dụng trong dữ liệu của họ, nơi các doanh nghiệp nộp đơn theo Subchapter V thậm chí còn kiệt quệ hơn các doanh nghiệp nộp đơn theo Chapter 11 truyền thống.```{python}#| label: rdd-simulate#| code-summary: "Simulate a threshold-eligibility insolvency regime"rng = np.random.default_rng(2026)CUTOFF =7.5# eligibility ceiling, in millions of currency unitsTAU =0.32# true local effect on the probability of confirmationn_draw =2000liab = CUTOFF + rng.normal(0.0, 2.5, n_draw)liab = liab[(liab >2.0) & (liab <13.0)]n = liab.size# Unobserved case complexity: raises take-up, lowers baseline success.complexity = rng.normal(0.0, 1.0, n)eligible = (liab <= CUTOFF).astype(float)# Take-up is imperfect on both sides: some eligible firms decline the# simplified track, and a few ineligible ones are admitted after the court# reclassifies part of their liabilities as contingent.p_take = np.where(eligible ==1.0, np.clip(0.60+0.12* complexity, 0.05, 0.95),0.03)simplified = (rng.random(n) < p_take).astype(float)p_conf = np.clip(0.17+0.010* (liab - CUTOFF) -0.05* complexity + TAU * simplified,0.01, 0.99,)confirmed = (rng.random(n) < p_conf).astype(float)# A covariate that is smooth through the threshold, for the placebo check.leverage =3.0+0.15* (liab - CUTOFF) + rng.normal(0.0, 1.2, n)print(f"Cases simulated: {n:,}")print(f"Eligible (below cutoff): {eligible.mean():6.1%}")print(f"Use simplified track | eligible: {simplified[eligible ==1].mean():6.1%}")print(f"Use simplified track | above: {simplified[eligible ==0].mean():6.1%}")print(f"Plan confirmed (overall): {confirmed.mean():6.1%}")```Bộ máy ước lượng đủ ngắn để viết ra đầy đủ. Bình phương tối thiểu có trọng số với sai số chuẩn vững với phương sai thay đổi là khối xây dựng cơ bản; bình phương tối thiểu hai giai đoạn là cùng phép đại số được áp dụng cho phép chiếu của biến hồi quy nội sinh lên tập biến công cụ.```{python}#| label: rdd-estimators#| code-summary: "Weighted least squares, weighted 2SLS, and the fuzzy RD wrapper"from math import erfc, sqrtdef tri_weights(s, h):"""Triangular kernel weights on the centred running variable."""return np.clip(1.0- np.abs(s) / h, 0.0, None)def robust_wls(X, y, w):"""WLS coefficients with HC1 standard errors.""" Xw = X * w[:, None] XtWX = X.T @ Xw beta = np.linalg.solve(XtWX, Xw.T @ y) e = y - X @ beta G = X * (w * e)[:, None] bread = np.linalg.inv(XtWX) n_obs, k = X.shape V = bread @ (G.T @ G) @ bread * (n_obs /max(n_obs - k, 1))return beta, np.sqrt(np.diag(V))def robust_2sls(X, Z, y, w):"""Weighted 2SLS with HC1 standard errors; Z must have as many columns as X.""" Zw = Z * w[:, None] Xhat = Z @ np.linalg.solve(Z.T @ Zw, Zw.T @ X) A = Xhat.T @ (X * w[:, None]) beta = np.linalg.solve(A, (Xhat * w[:, None]).T @ y) e = y - X @ beta G = Xhat * (w * e)[:, None] Ainv = np.linalg.inv(A) n_obs, k = X.shape V = Ainv @ (G.T @ G) @ Ainv.T * (n_obs /max(n_obs - k, 1))return beta, np.sqrt(np.diag(V))def fuzzy_rd(running, treat, outcome, cutoff=CUTOFF, h=3.5, donut=0.0):""" Local-linear fuzzy RD with separate slopes on each side of the cutoff. Returns the first stage, the reduced form (intent-to-treat), and the 2SLS local average treatment effect, all estimated on the same sample. """ s = running - cutoff m = (np.abs(s) <= h) & (np.abs(s) >= donut) s, d, y = s[m], treat[m], outcome[m] below = (s <=0).astype(float) w = tri_weights(s, h) one = np.ones_like(s) Z = np.column_stack([one, below, s, below * s]) # instrument set X = np.column_stack([one, d, s, below * s]) # structural regressors b_fs, se_fs = robust_wls(Z, d, w) b_rf, se_rf = robust_wls(Z, y, w) b_iv, se_iv = robust_2sls(X, Z, y, w)return {"h": h, "n": int(m.sum()),"first_stage": b_fs[1], "first_stage_se": se_fs[1],"F": (b_fs[1] / se_fs[1]) **2,"itt": b_rf[1], "itt_se": se_rf[1],"late": b_iv[1], "late_se": se_iv[1],"wald": b_rf[1] / b_fs[1], }```Giờ đây có thể đặt phép so sánh ngây thơ và ước lượng RD cạnh nhau.```{python}#| label: rdd-main#| code-summary: "Naive OLS versus the fuzzy RD estimate"b_naive, se_naive = robust_wls( np.column_stack([np.ones(n), simplified]), confirmed, np.ones(n))main = fuzzy_rd(liab, simplified, confirmed, h=3.5)print("="*66)print(" Effect on the probability of confirming a plan")print("="*66)print(f" True local effect (by construction) {TAU:>10.3f}")print(f" Naive OLS, users vs non-users {b_naive[1]:>10.3f}"f" (se {se_naive[1]:.3f})")print("-"*66)print(f" Fuzzy RD, bandwidth +/-{main['h']:.1f}, n = {main['n']:,}")print(f" First stage (eligibility -> use) {main['first_stage']:>10.3f}"f" (F = {main['F']:.1f})")print(f" Reduced form (intent-to-treat) {main['itt']:>10.3f}"f" (se {main['itt_se']:.3f})")print(f" 2SLS local average treatment effect {main['late']:>10.3f}"f" (se {main['late_se']:.3f})")print(f" Wald ratio, ITT / first stage {main['wald']:>10.3f}")print("="*66)```Tỷ số Wald và hệ số 2SLS trùng khớp đến độ chính xác của máy tính, vì mô hình vừa đủ nhận diện. Phép so sánh ngây thơ đánh giá thấp tác động thực, đúng như câu chuyện chọn lọc dự báo.Tiếp theo là độ nhạy theo băng thông và đặc tả donut-hole. Mục đích của bảng không phải là tìm đặc tả có hệ số lớn nhất mà là xem ước lượng và độ chính xác của nó biến đổi cùng nhau như thế nào.```{python}#| label: rdd-bandwidth#| code-summary: "Bandwidth path and donut-hole robustness"rows = []for h in [1.5, 2.0, 2.5, 3.0, 3.5]: r = fuzzy_rd(liab, simplified, confirmed, h=h) rows.append({"Bandwidth": f"+/-{h:.1f}", "N": r["n"],"First stage": r["first_stage"], "F": r["F"],"LATE": r["late"], "SE": r["late_se"],"t": r["late"] / r["late_se"]})r_donut = fuzzy_rd(liab, simplified, confirmed, h=3.5, donut=0.5)rows.append({"Bandwidth": "+/-3.5 donut", "N": r_donut["n"],"First stage": r_donut["first_stage"], "F": r_donut["F"],"LATE": r_donut["late"], "SE": r_donut["late_se"],"t": r_donut["late"] / r_donut["late_se"]})bw_table = pd.DataFrame(rows)print(f"Bandwidth path for the fuzzy RD estimate (true effect = {TAU:.2f})")print(bw_table.to_string(index=False, float_format=lambda v: f"{v:8.3f}"))```Tiếp theo là hai kiểm tra tính hợp lệ. Kiểm định mật độ tìm sự dồn tụ (bunching) ngay dưới ngưỡng, vốn cho thấy các doanh nghiệp quản lý biến chạy để đủ điều kiện; kiểm tra hiệp biến ước lượng dạng rút gọn trên một biến mà việc điều trị không thể ảnh hưởng.```{python}#| label: rdd-validity#| code-summary: "Density continuity test and covariate smoothness placebo"def density_jump(x, cutoff=CUTOFF, h=3.5, binw=0.25, n_boot=400, seed=7):""" McCrary-style test: a local-linear density fitted separately on each side of the cutoff, with a bootstrap standard error for the log difference. """ n_bins =int(round(2* h / binw)) edges = np.linspace(-h, h, n_bins +1) mid = (edges[:-1] + edges[1:]) /2.0def one_jump(sample): s = sample - cutoff s = s[np.abs(s) <= h] dens = np.histogram(s, bins=edges)[0] / (sample.size * binw) fitted = []for side in (-1.0, 1.0): m = (mid * side) >0 A = np.column_stack([np.ones(int(m.sum())), mid[m]]) b, _ = robust_wls(A, dens[m], tri_weights(mid[m], h)) fitted.append(max(b[0], 1e-12))return np.log(fitted[1]) - np.log(fitted[0]) theta = one_jump(x) boot_rng = np.random.default_rng(seed) draws = np.array([ one_jump(x[boot_rng.integers(0, x.size, x.size)]) for _ inrange(n_boot) ]) se = draws.std(ddof=1) z = theta / se if se >0else0.0return theta, se, erfc(abs(z) / sqrt(2.0))theta, se_theta, p_density = density_jump(liab)cov_check = fuzzy_rd(liab, simplified, leverage, h=3.5)print("Validity checks")print("-"*66)print(f" Density log-jump at the cutoff {theta:>8.3f}"f" (se {se_theta:.3f}, p = {p_density:.3f})")print(f" Leverage jump at the cutoff {cov_check['itt']:>8.3f}"f" (se {cov_check['itt_se']:.3f}, "f"t = {cov_check['itt'] / cov_check['itt_se']:.2f})")print("-"*66)print(" Neither should be distinguishable from zero.")``````{python}#| label: fig-rdd-discontinuity#| fig-cap: "Gián đoạn hồi quy mờ tại một ngưỡng đủ điều kiện. Biểu đồ bên trái thể hiện giai đoạn một: mức tham gia thủ tục đơn giản hóa nhảy gián đoạn tại mức trần nhưng không đi từ không lên một, đó là điều làm cho thiết kế là mờ chứ không phải sắc nét. Biểu đồ bên phải thể hiện dạng rút gọn: xác suất xác nhận kế hoạch giảm mạnh đối với các doanh nghiệp ngay trên mức trần. Các điểm là trung bình theo nhóm; các đường là hồi quy tuyến tính cục bộ được ước lượng riêng ở mỗi phía."bins = np.linspace(CUTOFF -3.5, CUTOFF +3.5, 29)idx = np.digitize(liab, bins) -1mids = (bins[:-1] + bins[1:]) /2.0fig, axes = plt.subplots(1, 2, figsize=(14, 5))panels = [ (axes[0], simplified, "First stage: take-up of the simplified track","Share using the procedure"), (axes[1], confirmed, "Reduced form: plan confirmation","Share confirming a plan"),]for ax, series, title, ylab in panels: means = np.array([ series[idx == b].mean() if (idx == b).sum() >0else np.nanfor b inrange(len(bins) -1) ]) ax.scatter(mids, means, s=34, color=colors["primary"], alpha=0.85, zorder=3, label="Binned mean")for side, col in [(-1.0, colors["tertiary"]), (1.0, colors["quaternary"])]: m = ((mids - CUTOFF) * side >0) &~np.isnan(means) A = np.column_stack([np.ones(int(m.sum())), mids[m] - CUTOFF]) b, _ = robust_wls(A, means[m], tri_weights(mids[m] - CUTOFF, 3.5)) grid = np.linspace(mids[m].min(), mids[m].max(), 50) ax.plot(grid, b[0] + b[1] * (grid - CUTOFF), color=col, linewidth=2) ax.axvline(CUTOFF, color=colors["distress"], linestyle="--", linewidth=2, label="Eligibility ceiling") ax.set_xlabel("Non-contingent liabilities at filing (millions)") ax.set_ylabel(ylab) ax.set_title(title) ax.legend(loc="best")plt.tight_layout()plt.show()```Cuối cùng là phần tương ứng của sai biệt trong sai biệt. Nhóm giai đoạn trước nộp đơn trước khi thủ tục tồn tại, và biến chỉ thị điều trị của nó phải được xây dựng từ *tổng* nợ phải trả, vì sự phân chia nợ không phụ thuộc điều kiện không quan sát được trước khi quy tắc tạo ra lý do để ghi nhận nó. Sai số đo lường đó làm suy giảm ước lượng ý định điều trị, và việc điều chỉnh tỷ lệ theo giai đoạn một khôi phục tham số cấu trúc.```{python}#| label: rdd-did#| code-summary: "Difference-in-differences intent-to-treat, and rescaling to a LATE"did_rng = np.random.default_rng(20200219)def make_cohort(size, post):"""One filing cohort; the simplified track exists only when post is True.""" nc_liab = CUTOFF + did_rng.normal(0.0, 2.5, size) total_liab = nc_liab + did_rng.gamma(1.5, 0.6, size) # contingent claims cplx = did_rng.normal(0.0, 1.0, size) can_use = (nc_liab <= CUTOFF) &bool(post) p_use = np.where(can_use, np.clip(0.60+0.12* cplx, 0.05, 0.95), 0.0) used = (did_rng.random(size) < p_use).astype(float) p_c = np.clip(0.17+0.010* (nc_liab - CUTOFF) -0.05* cplx + TAU * used,0.01, 0.99)return pd.DataFrame({"total_liab": total_liab,"used": used,"confirmed": (did_rng.random(size) < p_c).astype(float),"post": float(post), })panel = pd.concat([make_cohort(4000, False), make_cohort(4000, True)], ignore_index=True)panel = panel[(panel["total_liab"] >=4.0) & (panel["total_liab"] <=11.0)].copy()panel["treated"] = (panel["total_liab"] <= CUTOFF).astype(float)D = np.column_stack([ np.ones(len(panel)), panel["treated"].to_numpy(), panel["post"].to_numpy(), (panel["treated"] * panel["post"]).to_numpy(),])unit_w = np.ones(len(panel))b_itt, se_itt = robust_wls(D, panel["confirmed"].to_numpy(), unit_w)b_first, se_first = robust_wls(D, panel["used"].to_numpy(), unit_w)print("="*66)print(f" Difference-in-differences, n = {len(panel):,}"f" (true effect = {TAU:.2f})")print("="*66)print(f" Treated x Post on confirmation (ITT) {b_itt[3]:>8.3f}"f" (se {se_itt[3]:.3f})")print(f" Treated x Post on take-up (1st stage) {b_first[3]:>8.3f}"f" (se {se_first[3]:.3f})")print(f" Rescaled: ITT / first stage {b_itt[3] / b_first[3]:>8.3f}")print("="*66)```ITT rơi xa dưới tác động thực vì hầu hết các doanh nghiệp được điều trị trên danh nghĩa không bao giờ sử dụng thủ tục và một số bị phân loại nhầm theo tổng nợ phải trả thay vì nợ không phụ thuộc điều kiện. Chia cho giai đoạn một khôi phục tham số, đó là cùng phép đối chiếu mà @hotchkiss2026can báo cáo là $12.5 / 0.42 = 29.8$ điểm phần trăm so với ước lượng RDD là $32.0$.Khuôn mẫu là điều có thể chuyển giao. Với một quy tắc ngưỡng của Việt Nam, một bảng dữ liệu cấp vụ việc hoặc cấp doanh nghiệp ghi nhận biến chạy theo cách quy tắc đo lường, và một lập luận đáng tin cậy rằng các doanh nghiệp không thể tự định vị quanh ngưỡng, các đoạn mã tương tự cho ra giai đoạn một, một LATE, một đường đi băng thông và hai kiểm tra tính hợp lệ quyết định liệu toàn bộ điều này có ý nghĩa hay không.# Các cân nhắc thực tiễn và hạn chế {#sec-valuation-limitations}## Các hạn chế đã biết của Q của Tobin ở Việt NamMột số vấn đề ảnh hưởng đến độ tin cậy của các ước lượng Q của Tobin đối với doanh nghiệp Việt Nam:1. **Giá trị sổ sách làm đại diện cho chi phí thay thế**: Thước đo Q giản lược giả định rằng giá trị sổ sách của tài sản xấp xỉ chi phí thay thế. Với việc VAS dựa nhiều vào giá gốc, giả định này có thể gây vấn đề hơn so với các nước áp dụng IFRS, đặc biệt đối với các doanh nghiệp có quyền sử dụng đất đáng kể hoặc tài sản hữu hình tuổi thọ dài.2. **Hiệu ứng vi cấu trúc thị trường**: Biên độ giá hằng ngày của Việt Nam có thể ngăn giá thị trường đạt tới cân bằng, có khả năng làm méo mó thành phần giá trị thị trường. Giới hạn sở hữu nước ngoài có thể tạo ra phần bù giá nhân tạo đối với một số cổ phiếu.3. **Sự hiếm gặp của cổ phiếu ưu đãi**: Dù điều này đơn giản hóa phép tính (hầu hết doanh nghiệp Việt Nam không có cổ phiếu ưu đãi), nó có nghĩa là phép tính BE bị chi phối bởi vốn cổ phần phổ thông, có thể không nắm bắt hết mọi quyền đòi của chủ sở hữu.4. **Hiệu ứng niêm yết chéo**: Một số doanh nghiệp Việt Nam niêm yết trên nhiều nơi (HOSE, HNX, UPCoM, hoặc thậm chí các sàn nước ngoài). Cần thận trọng để sử dụng dữ liệu giá và số cổ phiếu nhất quán.## Các hạn chế đã biết của điểm Z của Altman ở Việt Nam1. **Mẫu hiệu chỉnh**: Điểm Z gốc được ước lượng trên các doanh nghiệp sản xuất của Hoa Kỳ giữa thế kỷ 20. Điểm Z'' cho thị trường mới nổi phù hợp hơn nhưng vẫn được ước lượng trên một mẫu không phải của Việt Nam.2. **Khác biệt kế toán**: Các chuẩn mực kế toán VAS tạo ra các tỷ số tài chính có tính chất phân phối khác với dữ liệu US GAAP hoặc IFRS, có khả năng ảnh hưởng đến độ chính xác phân loại của hàm phân biệt.3. **Ngân hàng và doanh nghiệp tài chính**: Điểm Z không được thiết kế cho các định chế tài chính, vốn có cấu trúc bảng cân đối kế toán khác biệt căn bản. Ngân hàng, công ty bảo hiểm và công ty chứng khoán nên được loại trừ hoặc phân tích riêng.4. **Bảo lãnh ngầm**: Các SOE và doanh nghiệp liên kết với các tập đoàn kinh tế lớn có thể có sự hỗ trợ ngầm làm giảm rủi ro vỡ nợ thực tế xuống dưới dự báo của điểm Z.## Khuyến nghị cho các nhà nghiên cứuDựa trên phân tích của chúng tôi, chúng tôi đưa ra các khuyến nghị sau cho các nhà nghiên cứu làm việc với dữ liệu Việt Nam:1. **Sử dụng biến thể điểm Z'' (thị trường mới nổi)** làm thước đo kiệt quệ chính cho các doanh nghiệp phi tài chính của Việt Nam.2. **Báo cáo nhiều biến thể Q** (đơn giản và Chung-Pruitt) để chứng minh độ vững.3. **Winsorization tại 1%/99%** để giảm thiểu tác động của lỗi dữ liệu và các giá trị ngoại lai cực đoan.4. **Tính các thước đo điều chỉnh theo ngành** khi thực hiện so sánh chéo.5. **Sử dụng tuổi thành lập** thay vì tuổi niêm yết khi có sẵn, nhưng báo cáo cả hai để phân biệt mức độ trưởng thành của tổ chức với kinh nghiệm trên thị trường vốn.6. **Loại trừ các doanh nghiệp tài chính** khỏi phân tích điểm Z.7. **Tính đến sở hữu nhà nước** như một biến điều tiết trong các nghiên cứu về định giá và kiệt quệ.8. **Đừng đọc điểm Z như một dự báo thu hồi.** Nó chấm điểm xác suất kiệt quệ, không phải điều mà hệ thống pháp luật làm với một doanh nghiệp kiệt quệ; xem @sec-valuation-resolution.# Tóm tắt {#sec-valuation-summary}Chương này trình bày cách tiếp cận đối với ba thước đo cơ bản của tài chính doanh nghiệp (tức Q của Tobin, điểm Z của Altman và tuổi công ty). Chúng tôi đã trình bày nền tảng lý thuyết của từng thước đo và cung cấp nhiều hình minh họa về các mô thức cắt ngang và chuỗi thời gian.Các phát hiện chính từ phân tích các doanh nghiệp niêm yết Việt Nam gồm:1. **Q của Tobin** biến thiên đáng kể giữa các ngành và các sàn giao dịch, với các ngành công nghệ và hướng đến người tiêu dùng thường có mức định giá cao hơn. Các doanh nghiệp niêm yết trên HOSE có xu hướng có giá trị Q cao hơn các doanh nghiệp trên HNX hoặc UPCoM, phản ánh cả sự khác biệt về chất lượng doanh nghiệp lẫn hiệu ứng thanh khoản.2. **Điểm Z của Altman** cho thấy một tỷ lệ đáng kể các doanh nghiệp Việt Nam hoạt động trong hoặc gần vùng kiệt quệ, dù biến thể phù hợp rất quan trọng; điểm Z'' cho thị trường mới nổi cho phép phân loại tinh tế hơn mô hình gốc. Sức khỏe tài chính có biến thiên chuỗi thời gian đáng kể, với sự suy giảm rõ rệt trong các giai đoạn kinh tế suy thoái.3. **Tuổi công ty** ở Việt Nam đòi hỏi xử lý cẩn thận do việc cổ phần hóa các SOE, tạo ra khoảng cách lớn giữa tuổi thành lập và tuổi niêm yết. Sự phân biệt này có ý nghĩa quan trọng về bản chất để hiểu mối quan hệ giữa mức độ trưởng thành, định giá và sự ổn định tài chính.4. **Giải quyết kiệt quệ** là một câu hỏi tách biệt với dự báo kiệt quệ, và điểm Z chỉ nói về vế sau. @hotchkiss2026can cho thấy chỉ riêng một thay đổi trong thủ tục mất khả năng thanh toán đã làm xác suất một doanh nghiệp nhỏ của Hoa Kỳ tái cơ cấu thay vì thanh lý tăng hơn gấp đôi, mà không gây hại đến tỷ lệ thu hồi của chủ nợ. Vì các trường hợp rời khỏi thị trường ở Việt Nam chủ yếu là hủy niêm yết bắt buộc chứ không phải tái cơ cấu dưới sự giám sát của tòa án, một điểm Z'' của Việt Nam trong vùng kiệt quệ ứng với một phân phối kết cục khác biệt đáng kể so với cùng điểm số đó trong mẫu mà các hệ số được ước lượng. @sec-valuation-resolution phát triển luận điểm này và triển khai các thiết kế gián đoạn hồi quy mờ và sai biệt trong sai biệt mà các ngưỡng đủ điều kiện cho phép.