43  Các công cụ ước lượng và nhận dạng trong tài chính doanh nghiệp

Tài chính doanh nghiệp nghiên cứu cách các doanh nghiệp đưa ra quyết định đầu tư, tài trợ và chi trả trong điều kiện có các ma sát thực tế (chẳng hạn thuế, bất cân xứng thông tin, xung đột đại diện, chi phí giao dịch và ràng buộc tài chính). Khác với định giá tài sản, nơi đối tượng quan tâm chính là lợi nhuận kỳ vọng và các phần bù rủi ro được ước lượng từ dữ liệu thị trường, các công cụ ước lượng trong tài chính doanh nghiệp gắn với dữ liệu kế toán và quản trị ở cấp doanh nghiệp, và cách diễn giải kinh tế của chúng phụ thuộc rất nhiều vào môi trường thể chế mà doanh nghiệp hoạt động.

Chương này xây dựng bộ công cụ kinh tế lượng cốt lõi cho tài chính doanh nghiệp thực nghiệm và áp dụng vào các doanh nghiệp niêm yết Việt Nam. Các công cụ ước lượng mà chúng ta xem xét (gồm hồi quy đầu tư-\(Q\), kiểm định độ nhạy dòng tiền, các yếu tố quyết định cấu trúc vốn, mô hình làm mượt chi trả và các biến đại diện cho chi phí đại diện) là xương sống của tài liệu tài chính doanh nghiệp hiện đại. Mỗi công cụ ước lượng hàm chứa những giả định lý thuyết cụ thể, và mỗi công cụ đều từng là đối tượng của các tranh luận phương pháp luận đáng kể. Chúng ta đặc biệt chú ý đến các thách thức về nhận dạng: những điều kiện để một hệ số hồi quy có thể được diễn giải theo nghĩa nhân quả hoặc cấu trúc, thay vì chỉ là một mối liên hệ mô tả.

Các doanh nghiệp Việt Nam có những đặc điểm riêng tương tác với các công cụ ước lượng này theo những cách có ý nghĩa kinh tế. Sở hữu nhà nước vẫn còn phổ biến và tạo ra các vấn đề đại diện khác về bản chất so với bối cảnh sở hữu phân tán trong tài liệu Anh-Mỹ. Sở hữu gia đình tập trung, cấu trúc kim tự tháp và sở hữu chéo tạo ra các động cơ tunneling (rút ruột tài sản) được ghi nhận bởi Johnson và c.s. (2000) và Claessens và c.s. (2002). Hệ thống ngân hàng bị chi phối bởi các ngân hàng thương mại nhà nước, những ngân hàng có thể ra quyết định cho vay theo tiêu chí chính trị chứ không hoàn toàn theo tiêu chí kinh tế, khiến việc diễn giải các thước đo ràng buộc tài chính trở nên phức tạp. Và chính sách cổ tức chịu sự định hình của các yêu cầu quy định, bao gồm tỷ lệ chi trả tối thiểu đối với doanh nghiệp nhà nước, điều không có tương đương ở các thị trường phát triển hơn.

Hiện mã
import pandas as pd
import numpy as np
from scipy import stats
import statsmodels.api as sm
import statsmodels.formula.api as smf
from linearmodels.panel import PanelOLS, PooledOLS
import plotnine as p9
from mizani.formatters import percent_format, comma_format
import warnings
warnings.filterwarnings("ignore")
Hiện mã
# DataCore.vn API
from datacore import DataCore
dc = DataCore()

# Load annual firm-level financial data
firm_annual = dc.get_firm_financials(
    start_date="2008-01-01",
    end_date="2024-12-31",
    frequency="annual"
)

# Load ownership data
ownership = dc.get_ownership_data(
    start_date="2008-01-01",
    end_date="2024-12-31"
)

# Load stock returns (monthly)
monthly_returns = dc.get_monthly_returns(
    start_date="2008-01-01",
    end_date="2024-12-31"
)

# Load market and factor returns
factors = dc.get_factor_returns(
    start_date="2008-01-01",
    end_date="2024-12-31"
)

print(f"Firm-year observations: {len(firm_annual)}")
print(f"Unique firms: {firm_annual['ticker'].nunique()}")
print(f"Year range: {firm_annual['year'].min()}–{firm_annual['year'].max()}")

43.1 Hồi quy đầu tư-\(Q\)

43.1.1 \(Q\) của Tobin: trực giác và lý thuyết

Khung đầu tư-\(Q\) là mô hình cấu trúc chuẩn mực về đầu tư của doanh nghiệp. Ý tưởng cốt lõi, được Hayashi (1982) hình thức hóa, rất thanh nhã: trong điều kiện thị trường vốn hoàn hảo và hiệu suất không đổi theo quy mô đối với công nghệ sản xuất và chi phí điều chỉnh, tỷ lệ đầu tư của doanh nghiệp phải là một thống kê đủ của một đại lượng quan sát được duy nhất (tức là tỷ số giữa giá trị thị trường của vốn đã lắp đặt và chi phí thay thế của nó).

Gọi \(V_t\) là giá trị thị trường của tài sản doanh nghiệp tại thời điểm \(t\) và \(K_t\) là chi phí thay thế của trữ lượng vốn. \(Q\) của Tobin là:

\[ Q_t = \frac{V_t}{K_t} \tag{43.1}\]

Khi \(Q > 1\), thị trường định giá một đơn vị vốn đã lắp đặt cao hơn chi phí thay thế của nó, báo hiệu rằng doanh nghiệp nên đầu tư. Khi \(Q < 1\), doanh nghiệp nên thoái vốn. Trong môi trường không ma sát của Hayashi (1982), \(Q\) biên (giá trị bóng của một đơn vị vốn bổ sung) bằng \(Q\) bình quân (tỷ số giữa tổng giá trị thị trường và tổng chi phí thay thế), và chính sách đầu tư tối ưu là:

\[ \frac{I_{i,t}}{K_{i,t-1}} = \frac{1}{\alpha}\left(Q_{i,t} - 1\right) \tag{43.2}\]

trong đó \(\alpha\) chi phối độ lồi của chi phí điều chỉnh. Dạng thực nghiệm tương ứng là hồi quy:

\[ \frac{I_{i,t}}{K_{i,t-1}} = \beta_0 + \beta_1 Q_{i,t} + \varepsilon_{i,t} \tag{43.3}\]

Theo cách diễn giải cấu trúc, \(\beta_1 = 1/\alpha > 0\) và \(Q\) là biến giải thích duy nhất. Bất kỳ biến bổ sung nào xuất hiện với ý nghĩa thống kê đều hàm ý rằng các giả định nền tảng bị vi phạm (chẳng hạn ma sát tài chính, vấn đề đại diện, sai số đo lường trong \(Q\), hoặc sự lệch khỏi hiệu suất không đổi theo quy mô).

43.1.2 Các vấn đề đo lường

Đối tượng lý thuyết là \(Q\) biên (tức là giá trị của đồng đầu tư kế tiếp), vốn không quan sát được. Biến đại diện thực nghiệm là \(Q\) bình quân, thường được xây dựng như sau:

\[ Q_{i,t}^{\text{avg}} = \frac{\text{Market Value of Equity} + \text{Book Value of Debt}}{\text{Book Value of Total Assets}} \tag{43.4}\]

Biến đại diện này làm phát sinh một số vấn đề đã được ghi nhận đầy đủ trong tài liệu.

Vấn đề 1: Biên \(\neq\) bình quân. Đẳng thức \(q^{\text{marginal}} = Q^{\text{average}}\) đòi hỏi hiệu suất không đổi theo quy mô ở cả sản xuất lẫn chi phí điều chỉnh (Hayashi 1982). Với hiệu suất giảm dần theo quy mô (phù hợp về mặt thực nghiệm với hầu hết doanh nghiệp), \(Q\) bình quân phóng đại \(Q\) biên đối với các doanh nghiệp có \(Q\) cao và đánh giá thấp nó đối với các doanh nghiệp có \(Q\) thấp. Abel và Eberly (1994) suy ra chênh lệch này bằng phương pháp giải tích.

Vấn đề 2: Sai số đo lường ở tử số. Giá trị thị trường của vốn chủ sở hữu phản ánh tâm lý thị trường, bong bóng và nhu cầu của nhà đầu tư nhiễu (noise trader) bên cạnh các yếu tố nền tảng. P. Bond, Edmans, và Goldstein (2012) trình bày một phân tích toàn diện. Tại thị trường Việt Nam, nơi nhà đầu tư cá nhân chiếm ưu thế và biên độ giá hạn chế mức điều chỉnh hằng ngày, giá thị trường có thể lệch kéo dài khỏi giá trị cơ bản.

Vấn đề 3: Sai số đo lường ở mẫu số. Giá trị sổ sách của tài sản phản ánh nguyên giá lịch sử, lịch khấu hao và các quy ước kế toán, có thể xấp xỉ kém chi phí thay thế. Điều này đặc biệt có vấn đề ở Việt Nam, nơi việc đánh giá lại tài sản cố định diễn ra không thường xuyên và lạm phát trong lịch sử từng biến động mạnh, tạo ra chênh lệch giữa nguyên giá lịch sử và chi phí thay thế.

Vấn đề 4: Thiên lệch sai số trong biến số. Do \(Q\) thực nghiệm là biến đại diện có nhiễu của \(Q\) thực, các ước lượng OLS của \(\beta_1\) trong Phương trình 43.3 chịu thiên lệch suy giảm cổ điển (tức là \(\hat{\beta}_1\) bị lệch về phía không). Erickson và Whited (2012) phát triển một công cụ ước lượng cumulant bậc cao hiệu chỉnh thiên lệch này mà không cần biến công cụ bên ngoài.

Hiện mã
# Construct Tobin's Q and investment variables
panel = firm_annual.copy()

# Tobin's Q: (Market cap + Book debt) / Total assets
panel["tobins_q"] = (
    (panel["market_cap"] + panel["total_debt"]) /
    panel["total_assets"]
)

# Investment rate: Capital expenditure / Lagged total assets
panel = panel.sort_values(["ticker", "year"])
panel["lag_assets"] = panel.groupby("ticker")["total_assets"].shift(1)
panel["lag_ppe"] = panel.groupby("ticker")["ppe_net"].shift(1)

panel["inv_rate"] = panel["capex"] / panel["lag_assets"]
panel["inv_rate_ppe"] = panel["capex"] / panel["lag_ppe"]

# Cash flow / Assets
panel["cf_assets"] = panel["operating_cf"] / panel["lag_assets"]

# Sales growth
panel["lag_revenue"] = panel.groupby("ticker")["revenue"].shift(1)
panel["sales_growth"] = (
    (panel["revenue"] - panel["lag_revenue"]) / panel["lag_revenue"]
)

# Winsorize at 1st and 99th percentiles
def winsorize(s, lower=0.01, upper=0.99):
    return s.clip(s.quantile(lower), s.quantile(upper))

for col in ["tobins_q", "inv_rate", "cf_assets", "sales_growth"]:
    panel[col] = winsorize(panel[col])

panel_clean = panel.dropna(
    subset=["tobins_q", "inv_rate", "cf_assets"]
).copy()

print(f"Clean panel: {len(panel_clean)} firm-years, "
      f"{panel_clean['ticker'].nunique()} firms")
Bảng 43.1: Thống kê mô tả: các biến đầu tư và Q
Hiện mã
summary_vars = ["inv_rate", "tobins_q", "cf_assets", "sales_growth"]
summary = panel_clean[summary_vars].describe(
    percentiles=[0.05, 0.25, 0.5, 0.75, 0.95]
).T.round(4)

summary.columns = ["N", "Mean", "Std", "Min", "5%", "25%",
                    "Median", "75%", "95%", "Max"]
summary
Hiện mã
# Baseline investment-Q regression with firm and year fixed effects
panel_clean = panel_clean.set_index(["ticker", "year"])

# Model 1: Q only
model1 = PanelOLS(
    panel_clean["inv_rate"],
    panel_clean[["tobins_q"]],
    entity_effects=True,
    time_effects=True,
    check_rank=False
).fit(cov_type="clustered", cluster_entity=True)

# Model 2: Q + Cash Flow
model2 = PanelOLS(
    panel_clean["inv_rate"],
    panel_clean[["tobins_q", "cf_assets"]],
    entity_effects=True,
    time_effects=True,
    check_rank=False
).fit(cov_type="clustered", cluster_entity=True)

# Model 3: Q + Cash Flow + Sales Growth
model3 = PanelOLS(
    panel_clean["inv_rate"],
    panel_clean[["tobins_q", "cf_assets", "sales_growth"]],
    entity_effects=True,
    time_effects=True,
    check_rank=False
).fit(cov_type="clustered", cluster_entity=True)

panel_clean = panel_clean.reset_index()
Bảng 43.2: Hồi quy đầu tư-Q với hiệu ứng cố định theo doanh nghiệp và năm
Hiện mã
results_table = pd.DataFrame({
    "Q Only": {
        "Tobin's Q": f"{model1.params['tobins_q']:.4f}",
        "": f"({model1.std_errors['tobins_q']:.4f})",
        "Cash Flow/Assets": "",
        " ": "",
        "Sales Growth": "",
        "  ": "",
        "R² (within)": f"{model1.rsquared_within:.4f}",
        "N": f"{int(model1.nobs)}"
    },
    "Q + CF": {
        "Tobin's Q": f"{model2.params['tobins_q']:.4f}",
        "": f"({model2.std_errors['tobins_q']:.4f})",
        "Cash Flow/Assets": f"{model2.params['cf_assets']:.4f}",
        " ": f"({model2.std_errors['cf_assets']:.4f})",
        "Sales Growth": "",
        "  ": "",
        "R² (within)": f"{model2.rsquared_within:.4f}",
        "N": f"{int(model2.nobs)}"
    },
    "Q + CF + SG": {
        "Tobin's Q": f"{model3.params['tobins_q']:.4f}",
        "": f"({model3.std_errors['tobins_q']:.4f})",
        "Cash Flow/Assets": f"{model3.params['cf_assets']:.4f}",
        " ": f"({model3.std_errors['cf_assets']:.4f})",
        "Sales Growth": f"{model3.params['sales_growth']:.4f}",
        "  ": f"({model3.std_errors['sales_growth']:.4f})",
        "R² (within)": f"{model3.rsquared_within:.4f}",
        "N": f"{int(model3.nobs)}"
    }
})

results_table

43.1.3 Diễn giải trong điều kiện có ma sát thị trường

Hệ số của \(Q\) trong Bảng 43.2 có thể được diễn giải theo nhiều cách tùy thuộc vào các giả định được duy trì:

Diễn giải cấu trúc. Nếu các điều kiện Hayashi thỏa mãn, \(\hat{\beta}_1\) ước lượng nghịch đảo của tham số chi phí điều chỉnh: \(\hat{\beta}_1 = 1/\hat{\alpha}\). Hệ số càng lớn hàm ý chi phí điều chỉnh càng thấp. Tuy nhiên, sai số đo lường trong \(Q\) làm \(\hat{\beta}_1\) chệch xuống, nên ước lượng OLS thô chỉ cho một cận dưới của \(1/\alpha\).

Diễn giải dạng rút gọn. Khi không có các điều kiện Hayashi, \(\hat{\beta}_1\) nắm bắt mối liên hệ giữa định giá thị trường và cường độ đầu tư. Mối liên hệ này phản ánh sự pha trộn của các cơ hội đầu tư thực sự (kênh lý thuyết \(Q\)), việc định giá sai của thị trường mà các nhà quản lý khai thác (kênh định thời điểm thị trường của Baker, Stein, và Wurgler (2003)), và quan hệ nhân quả ngược (các thông báo đầu tư làm thay đổi giá trị thị trường).

Câu đố về hệ số dòng tiền. Ý nghĩa thống kê của \(\hat{\beta}_2\) đối với dòng tiền đã là chủ đề của một cuộc tranh luận kéo dài 35 năm. Fazzari, Hubbard, và Petersen (1987) diễn giải nó là bằng chứng cho thấy doanh nghiệp đối mặt với ràng buộc tài chính: khi đã kiểm soát các cơ hội đầu tư (\(Q\)), dòng tiền lẽ ra không liên quan trong một thế giới không ma sát, nên ý nghĩa thống kê của nó hàm ý rằng nguồn vốn nội bộ nới lỏng các ràng buộc đang có hiệu lực. Kaplan và Zingales (1997) phản biện rằng dòng tiền đại diện cho các cơ hội đầu tư không được thước đo \(Q\) nhiễu nắm bắt, khiến hệ số dòng tiền chỉ là sản phẩm phụ của sai số đo lường chứ không phải bằng chứng về ràng buộc. Erickson và Whited (2012) cho thấy việc hiệu chỉnh sai số đo lường trong \(Q\) làm giảm đáng kể (nhưng không triệt tiêu) hệ số dòng tiền, ủng hộ một quan điểm trung dung.

43.1.4 Hạn chế ở các thị trường mới nổi

Khung đầu tư-\(Q\) đối mặt với những thách thức được khuếch đại tại thị trường Việt Nam.

Giao dịch mỏng và biên độ giá. Giá thị trường điều chỉnh chậm theo thông tin, nên \(Q\) đo tại cuối năm tài chính có thể không phản ánh tập cơ hội đầu tư hiện tại của doanh nghiệp. Biên độ giá \(\pm 7\%\) (HOSE) và \(\pm 10\%\) (HNX) nén tử số của \(Q\) một cách cơ học, làm suy giảm mối quan hệ đầu tư-\(Q\).

Sở hữu nhà nước. Đối với doanh nghiệp nhà nước (SOE), các quyết định đầu tư có thể bị chi phối bởi chỉ đạo chính sách thay vì sự tối ưu theo lý thuyết \(Q\). Việc đưa SOE vào hồi quy mà không có các số hạng tương tác làm nhiễu mối quan hệ cấu trúc.

Giao dịch với các bên liên quan. Tunneling thông qua các giao dịch với bên liên quan có nghĩa là đầu tư đo được có thể bao gồm chi tiêu vốn mang lại lợi ích cho cổ đông kiểm soát thay vì tối đa hóa giá trị doanh nghiệp. Hệ số đầu tư-\(Q\) ở các doanh nghiệp có tunneling phản ánh mối quan hệ giữa định giá thị trường và hành vi chiếm đoạt, chứ không phải phân bổ vốn hiệu quả.

Hiện mã
# Create Q-decile bins for clean visualization
plot_data = panel_clean.copy()
plot_data["q_bin"] = pd.qcut(
    plot_data["tobins_q"], q=20, duplicates="drop"
)

binned = (
    plot_data.groupby("q_bin", observed=True)
    .agg(
        mean_q=("tobins_q", "mean"),
        mean_inv=("inv_rate", "mean"),
        se_inv=("inv_rate", lambda x: x.std() / np.sqrt(len(x)))
    )
    .reset_index()
)

(
    p9.ggplot(binned, p9.aes(x="mean_q", y="mean_inv"))
    + p9.geom_pointrange(
        p9.aes(ymin="mean_inv - 1.96*se_inv",
               ymax="mean_inv + 1.96*se_inv"),
        color="#2E5090", size=0.5
    )
    + p9.geom_smooth(method="lm", color="#C0392B", se=False, size=0.8)
    + p9.labs(
        x="Tobin's Q (Vingtile Mean)",
        y="Investment Rate (I/A)",
        title="Investment-Q Relationship: Binned Scatter"
    )
    + p9.theme_minimal()
    + p9.theme(figure_size=(10, 6))
)
Hình 43.1
Hiện mã
# Merge ownership data
panel_with_own = panel_clean.merge(
    ownership[["ticker", "year", "state_ownership_pct",
               "foreign_ownership_pct", "insider_ownership_pct"]],
    on=["ticker", "year"],
    how="left"
)

panel_with_own["soe_dummy"] = (
    panel_with_own["state_ownership_pct"] > 50
).astype(int)

panel_with_own["q_x_soe"] = (
    panel_with_own["tobins_q"] * panel_with_own["soe_dummy"]
)
panel_with_own["cf_x_soe"] = (
    panel_with_own["cf_assets"] * panel_with_own["soe_dummy"]
)

# Regression with SOE interactions
panel_soe = panel_with_own.dropna(
    subset=["inv_rate", "tobins_q", "cf_assets", "soe_dummy"]
).set_index(["ticker", "year"])

model_soe = PanelOLS(
    panel_soe["inv_rate"],
    panel_soe[["tobins_q", "cf_assets", "soe_dummy",
               "q_x_soe", "cf_x_soe"]],
    entity_effects=True,
    time_effects=True,
    check_rank=False
).fit(cov_type="clustered", cluster_entity=True)

panel_soe = panel_soe.reset_index()
Bảng 43.3: Hồi quy đầu tư-Q với các tương tác sở hữu nhà nước
Hiện mã
soe_results = pd.DataFrame({
    "Coefficient": model_soe.params.round(4),
    "Std Error": model_soe.std_errors.round(4),
    "t-stat": model_soe.tstats.round(3),
    "p-value": model_soe.pvalues.round(4)
})

soe_results

Hệ số âm của \(Q \times \text{SOE}\) cho thấy độ nhạy đầu tư-\(Q\) bị suy giảm ở doanh nghiệp nhà nước, phù hợp với việc đầu tư của SOE bị chi phối bởi các nhân tố phi thị trường. Tương tác giữa dòng tiền và tình trạng SOE cho thấy các doanh nghiệp nhà nước đối mặt với ràng buộc tài chính chặt hơn hay lỏng hơn. Đây là câu hỏi có hàm ý chính sách trực tiếp đối với cải cách SOE.

43.1.5 Hiệu chỉnh sai số đo lường của Erickson-Whited

Erickson và Whited (2012) phát triển một công cụ ước lượng GMM sử dụng các moment bậc cao của dữ liệu để nhận dạng độ dốc đầu tư-\(Q\) khi có sai số đo lường, mà không cần biến công cụ bên ngoài. Ý tưởng then chốt là nếu sai số đo lường \(\eta\) trong \(Q\) độc lập với \(Q^*\) thực và sai số cấu trúc \(\varepsilon\), thì các cumulant bậc ba nhận dạng được tỷ số tín hiệu trên nhiễu.

Mô hình là:

\[ \frac{I_{i,t}}{K_{i,t-1}} = \beta_0 + \beta_1 Q_{i,t}^* + \gamma X_{i,t} + \varepsilon_{i,t}, \qquad Q_{i,t} = Q_{i,t}^* + \eta_{i,t} \tag{43.5}\]

trong đó \(Q_{i,t}^*\) là \(Q\) thực không quan sát được và \(\eta_{i,t}\) là sai số đo lường. Công cụ ước lượng OLS \(\hat{\beta}_1^{\text{OLS}}\) hội tụ về \(\beta_1 \cdot \lambda\) với \(\lambda = \text{Var}(Q^*) / (\text{Var}(Q^*) + \text{Var}(\eta)) < 1\) là tỷ số tín hiệu trên nhiễu. Công cụ ước lượng Erickson-Whited khôi phục đồng thời \(\beta_1\) và \(\lambda\).

Hiện mã
def erickson_whited_gmm(y, Q_obs, X=None, order=3):
    """
    Simplified Erickson-Whited (2012) measurement error correction
    using third-order cumulants.

    Parameters
    ----------
    y : array
        Dependent variable (investment rate).
    Q_obs : array
        Observed (mismeasured) Q.
    X : array or None
        Additional controls (partialled out first).
    order : int
        Cumulant order for identification (3 or 5).

    Returns
    -------
    dict : Corrected beta, signal-to-noise ratio, OLS beta.
    """
    if X is not None:
        # Partial out controls via OLS
        X_aug = sm.add_constant(X)
        y = y - X_aug @ np.linalg.lstsq(X_aug, y, rcond=None)[0]
        Q_obs = Q_obs - X_aug @ np.linalg.lstsq(X_aug, Q_obs, rcond=None)[0]

    # Demean
    y_dm = y - y.mean()
    q_dm = Q_obs - Q_obs.mean()
    n = len(y)

    # Second moments
    m_yq = np.mean(y_dm * q_dm)
    m_qq = np.mean(q_dm**2)

    # OLS beta
    beta_ols = m_yq / m_qq

    # Third-order cumulants for identification
    k3_q = np.mean(q_dm**3)
    k2y_q = np.mean(y_dm * q_dm**2)

    if abs(k3_q) < 1e-10:
        return {
            "beta_corrected": np.nan,
            "lambda_snr": np.nan,
            "beta_ols": beta_ols,
            "note": "Insufficient skewness for identification"
        }

    # Corrected beta: beta = kappa_{y,q,q} / kappa_{q,q,q}
    beta_ew = k2y_q / k3_q

    # Signal-to-noise ratio
    # lambda = kappa_{q,q,q}^2 / (kappa_{q,q} * kappa_{q,q,q,q,q})
    # Simplified: lambda = beta_ols / beta_ew
    lambda_snr = beta_ols / beta_ew if abs(beta_ew) > 1e-10 else np.nan

    return {
        "beta_corrected": beta_ew,
        "lambda_snr": lambda_snr,
        "beta_ols": beta_ols,
        "attenuation_pct": round((1 - lambda_snr) * 100, 1) if not np.isnan(lambda_snr) else np.nan
    }

# Apply to Vietnamese data
ew_data = panel_clean.dropna(subset=["inv_rate", "tobins_q", "cf_assets"])

ew_result = erickson_whited_gmm(
    y=ew_data["inv_rate"].values,
    Q_obs=ew_data["tobins_q"].values,
    X=ew_data["cf_assets"].values.reshape(-1, 1)
)

print("Erickson-Whited Measurement Error Correction:")
for k, v in ew_result.items():
    if isinstance(v, float):
        print(f"  {k}: {v:.4f}")
    else:
        print(f"  {k}: {v}")

43.1.6 \(q\) biên từ giá trị thị trường

Cách hiệu chỉnh của Erickson-Whited coi \(Q\) của Tobin là thước đo có nhiễu của đúng đối tượng. Gala, Gomes, và Liu (2026) lập luận rằng nó còn là thước đo của sai đối tượng. Lý thuyết \(Q\) nói rằng đầu tư phản ứng với \(q\) biên, tức giá trị bóng của một đơn vị vốn bổ sung, \(q = \partial V / \partial K\). \(Q = V/K\) (bình quân) chỉ bằng \(q\) biên dưới các điều kiện thuần nhất rất hẹp của Hayashi (1982), và không cách hiệu chỉnh nào đối với sai số đo lường cổ điển có thể thu hẹp khoảng cách đến từ việc đặc tả sai mô hình. Điểm then chốt của họ là hàm giá trị không phải là không quan sát được như vẻ ngoài. Giá trị thị trường của doanh nghiệp chính là hàm giá trị, được quan sát có nhiễu, và các đối số của nó (trữ lượng vốn và năng suất của doanh nghiệp) đo lường được. Do đó có thể thu được \(q\) biên bằng cách ước lượng hàm giá trị rồi lấy đạo hàm của nó.

Công cụ ước lượng gồm hai bước. Thứ nhất, hồi quy logarit của giá trị thị trường trên mỗi đơn vị vốn theo một đa thức của logarit vốn, \(k_{i,t} = \ln K_{i,t}\), và logarit năng suất, \(a_{i,t} = \ln A_{i,t}\), với hiệu ứng cố định theo doanh nghiệp và năm:

\[ v_{i,t} \equiv \ln Q_{i,t} = \sum_{j_k=0}^{n_k} \sum_{j_a=0}^{n_a} c_{j_k, j_a}\, k_{i,t}^{j_k} a_{i,t}^{j_a} + \alpha_i + \tau_t + \varepsilon_{i,t}. \tag{43.6}\]

Các hiệu ứng năm hấp thụ các biến trạng thái toàn nền kinh tế, chẳng hạn tỷ lệ chiết khấu, mà không cần phải đo chúng, còn các hiệu ứng doanh nghiệp hấp thụ tính không đồng nhất bất biến theo thời gian trong giá đầu vào và khấu hao. Các tác giả nhận thấy rằng một đa thức bậc hai đầy đủ (các số hạng tuyến tính, bình phương và tương tác) nắm bắt được biến thiên của giá trị thị trường, và các số hạng bậc cao hơn được chọn bằng Lasso thích nghi thay đổi không đáng kể. Thứ hai, lấy đạo hàm của hàm giá trị đã khớp. Vì \(V = QK\),

\[ q_{i,t} = \frac{\partial V_{i,t}}{\partial K_{i,t}} = \widehat{Q}_{i,t}\left(1 + \frac{\partial \hat{v}_{i,t}}{\partial k_{i,t}}\right), \qquad \frac{\partial \hat{v}_{i,t}}{\partial k_{i,t}} = \hat{c}_{1,0} + 2\hat{c}_{2,0}\, k_{i,t} + \hat{c}_{1,1}\, a_{i,t}, \tag{43.7}\]

trong đó \(\widehat{Q}_{i,t} = \exp(\hat{v}_{i,t})\) là giá trị khớp của Phương trình 43.6, mà các tác giả gọi là Fitted \(Q\). \(Q\) khớp là \(Q\) bình quân đã được loại bỏ mọi biến thiên không liên quan đến các biến trạng thái cơ bản, nên nó là một hiệu chỉnh trực tiếp, ở cấp quan sát, đối với sai số đo lường cổ điển, kể cả sai số đến từ việc định giá sai trên thị trường chứng khoán. \(q\) biên đi xa hơn và hiệu chỉnh cả việc đặc tả sai mô hình. Sự tương đương \(q = Q\) của Hayashi đúng chính xác khi \(\partial v / \partial k = 0\), tức là khi mọi hệ số của các số hạng có chứa \(k\) đều bằng không, do đó Phương trình 43.6 cũng cung cấp một kiểm định Wald cho giả định mà tài liệu đầu tư-\(Q\) đã duy trì suốt bốn thập kỷ. Các tác giả bác bỏ nó một cách dứt khoát.

Các phát hiện từ các doanh nghiệp sản xuất trong Compustat giai đoạn 1973–2019, trong phiên bản bài nghiên cứu chưa xuất bản, cho thấy các khác biệt rất lớn.

  • Mức độ. \(q\) biên bình quân là 0,81, so với 1,33 của \(Q\) khớp và 2,87 của \(Q\) Tobin, và nó ít biến động hơn nhiều. \(q\) biên luôn nằm dưới \(Q\) khớp, đúng như tính lõm của hàm giá trị đòi hỏi.
  • Chi phí điều chỉnh. Vì đầu tư tối ưu tối đa hóa \(qI - \Phi(I, K)\), đại lượng này phải không âm, nên \(q\) biên là cận trên của tổng chi phí điều chỉnh (gồm cả giá mua) trên mỗi đơn vị đầu tư. \(q\) biên giới hạn chúng ở mức 81% trung bình; nếu coi \(Q\) Tobin là \(q\) biên thì sẽ cho phép tới 287%. Các tham số chi phí điều chỉnh bậc hai ước lượng giảm từ khoảng 4,5 với \(Q\) Tobin xuống khoảng 1,3 với \(q\) biên.
  • Hồi quy đầu tư. Trong hồi quy của đầu tư theo \(Q\) với hiệu ứng doanh nghiệp và năm, hệ số góc của \(Q\) Tobin là 0,007 và \(R^2\) within khoảng 0,03; với \(q\) biên thì hệ số góc là 0,38 và \(R^2\) within khoảng 0,49. Hệ số dòng tiền, trọng tâm của cuộc tranh luận về ràng buộc tài chính được thảo luận bên dưới, co về không khi dùng \(q\) biên.
  • Khoảng cách ngày càng nới rộng. Trong phiên bản đã xuất bản, các tác giả cho thấy khoảng cách giữa \(q\) biên và \(Q\) Tobin đã nới rộng theo thời gian, chủ yếu do sức mạnh thị trường và vốn vô hình, hai lực làm tăng giá trị doanh nghiệp mà không làm tăng giá trị của một đơn vị vốn vật chất bổ sung (Peters và Taylor 2017).

Quy trình này không cần giả định nào về dạng của chi phí điều chỉnh, nhân tố chiết khấu ngẫu nhiên hay công nghệ sản xuất ngoài tính khả vi, đó là lý do các tác giả mô tả \(q\) thu được là gần như không phụ thuộc mô hình (quasi-model-free). Nó đòi hỏi một điều dễ bị làm sai. Đạo hàm trong Phương trình 43.7 giữ năng suất cố định, nên \(a_{i,t}\) phải đo trạng thái ngoại sinh, chứ không phải một kết quả biến động cơ học theo \(K\). Các tác giả ước lượng nó bằng các phương pháp hàm sản xuất (Olley và Pakes 1996; Ackerberg, Caves, và Frazer 2015). Tỷ số doanh thu trên vốn là một thay thế kém: giữ \(\ln(Y/K)\) cố định trong khi thay đổi \(K\) ngầm giả định hiệu suất không đổi theo quy mô, đúng là giả định mà phương pháp này được thiết kế để tránh.

Công cụ ước lượng chỉ cần vài dòng mã. Hàm dưới đây cài đặt phiên bản bậc hai của Phương trình 43.6 và Phương trình 43.7, trả về \(Q\) khớp và \(q\) biên cho mọi cặp doanh nghiệp-năm, và báo cáo kiểm định Wald của giả thuyết \(q = Q\).

Two-step projection estimator of marginal q
def estimate_marginal_q(df, v="ln_q", k="ln_k", a="ln_a",
                        entity="ticker", time="year"):
    """
    Projection estimator of marginal q (Gala, Gomes, and Liu).

    Step 1: regress v = ln(V/K) on a complete second-order polynomial in
            k = ln K and a = ln A with firm and year fixed effects.
    Step 2: differentiate the fitted value function with respect to k,
            q = Fitted Q * (1 + dv/dk).
    """
    d = df.dropna(subset=[v, k, a]).copy()
    d["k_sq"] = d[k] ** 2
    d["a_sq"] = d[a] ** 2
    d["k_x_a"] = d[k] * d[a]
    d = d.set_index([entity, time])

    terms = [k, a, "k_sq", "a_sq", "k_x_a"]
    fit = PanelOLS(
        d[v], d[terms], entity_effects=True, time_effects=True,
        check_rank=False
    ).fit(cov_type="clustered", cluster_entity=True)

    c = fit.params
    # Fitted value function includes the estimated firm and year effects
    v_hat = fit.fitted_values.iloc[:, 0] + fit.estimated_effects.iloc[:, 0]
    dv_dk = c[k] + 2 * c["k_sq"] * d[k] + c["k_x_a"] * d[a]

    d["fitted_q"] = np.exp(v_hat)
    d["dv_dk"] = dv_dk
    d["marginal_q"] = d["fitted_q"] * (1 + dv_dk)

    # Wald test of Hayashi's q = Q: all coefficients on terms in k are zero
    R = np.zeros((3, len(terms)))
    for row, term in enumerate([k, "k_sq", "k_x_a"]):
        R[row, terms.index(term)] = 1.0
    qq_test = fit.wald_test(R, np.zeros(3))

    return d.reset_index(), fit, qq_test

Trước khi áp dụng, cần kiểm tra rằng công cụ ước lượng khôi phục được \(q\) biên khi biết trước giá trị thực. Phép mô phỏng dưới đây xây dựng một bảng dữ liệu của 600 doanh nghiệp trong 15 năm với hàm giá trị lõm, cho đầu tư phản ứng với \(q\) biên thực với tham số chi phí điều chỉnh bậc hai bằng 2,5, và làm nhiễu \(Q\) quan sát bằng sai số đo lường có phân phối log-chuẩn. Không có gì trong đó được hiệu chuẩn theo Việt Nam; mục đích duy nhất của nó là cho thấy mỗi thước đo \(Q\) tác động thế nào đến hồi quy đầu tư khi đã biết quá trình sinh dữ liệu.

Simulate a panel with a known marginal q
rng_q = np.random.default_rng(20260819)
n_firms, n_years = 600, 15
firm_id = np.repeat(np.arange(n_firms), n_years)
year_id = np.tile(np.arange(n_years), n_firms)

# State variables: log capital and persistent log productivity
ln_k = (np.repeat(rng_q.normal(4.5, 1.5, n_firms), n_years)
        + rng_q.normal(0, 0.4, n_firms * n_years))
a_mean = rng_q.normal(0.0, 0.3, n_firms)
ln_a = np.empty(n_firms * n_years)
for i in range(n_firms):
    path = np.empty(n_years)
    shocks = rng_q.normal(0, 0.25, n_years)
    path[0] = a_mean[i] + shocks[0]
    for t in range(1, n_years):
        path[t] = a_mean[i] + 0.7 * (path[t - 1] - a_mean[i]) + shocks[t]
    ln_a[i * n_years:(i + 1) * n_years] = path

# True concave value function v = ln(V/K) and the implied marginal q
c_true = {"k": -0.50, "a": 0.55, "k_sq": 0.025, "a_sq": 0.30, "k_x_a": -0.05}
v_true = (1.5
          + np.repeat(rng_q.normal(0, 0.3, n_firms), n_years)
          + np.tile(rng_q.normal(0, 0.15, n_years), n_firms)
          + c_true["k"] * ln_k + c_true["a"] * ln_a
          + c_true["k_sq"] * ln_k**2 + c_true["a_sq"] * ln_a**2
          + c_true["k_x_a"] * ln_k * ln_a)
dv_dk_true = c_true["k"] + 2 * c_true["k_sq"] * ln_k + c_true["k_x_a"] * ln_a
q_true = np.exp(v_true) * (1 + dv_dk_true)

# Investment responds to true marginal q; observed Q is measured with error
gamma_true = 2.5
sim_q = pd.DataFrame({
    "ticker": firm_id, "year": year_id, "ln_k": ln_k, "ln_a": ln_a,
    "ln_q": v_true + rng_q.normal(0, 0.5, n_firms * n_years),
    "inv_rate": (q_true - 0.4) / gamma_true
                + rng_q.normal(0, 0.03, n_firms * n_years),
    "q_true": q_true,
})
sim_q["tobins_q"] = np.exp(sim_q["ln_q"])

sim_est, sim_fit, sim_qq = estimate_marginal_q(sim_q)
print(f"Wald test of q = Q: chi2 = {sim_qq.stat:.1f}, p = {sim_qq.pval:.4f}")
print(f"Correlation of estimated with true marginal q: "
      f"{sim_est['marginal_q'].corr(sim_est['q_true']):.3f}")
Wald test of q = Q: chi2 = 469.0, p = 0.0000
Correlation of estimated with true marginal q: 0.970
Hiện mã
def fe_slope(data, y, x):
    d = data.set_index(["ticker", "year"])
    res = PanelOLS(d[y], d[[x]], entity_effects=True, time_effects=True,
                   check_rank=False).fit(cov_type="clustered",
                                         cluster_entity=True)
    return res.params[x], res.std_errors[x], res.rsquared_within

rows = []
for label, col in [("Tobin's Q (observed)", "tobins_q"),
                   ("Fitted Q", "fitted_q"),
                   ("Marginal q (estimated)", "marginal_q"),
                   ("Marginal q (true)", "q_true")]:
    slope, se, r2 = fe_slope(sim_est, "inv_rate", col)
    rows.append({"Q measure": label,
                 "Mean": sim_est[col].mean(),
                 "Slope of I/K": slope,
                 "Std. error": se,
                 "Within R²": r2,
                 "Implied adjustment cost (1/slope)": 1 / slope})

pd.DataFrame(rows).set_index("Q measure").round(3)
Bảng 43.4: Hồi quy đầu tư theo các thước đo Q thay thế (bảng dữ liệu mô phỏng, tham số chi phí điều chỉnh thực bằng 2,5)
Mean Slope of I/K Std. error Within R² Implied adjustment cost (1/slope)
Q measure
Tobin's Q (observed) 1.258 0.028 0.003 0.163 35.199
Fitted Q 1.118 0.190 0.004 0.813 5.275
Marginal q (estimated) 0.753 0.381 0.007 0.849 2.626
Marginal q (true) 0.745 0.397 0.002 0.873 2.519

Phép mô phỏng tái tạo thứ hạng trong bài báo. \(Q\) Tobin quan sát được có giá trị trung bình cao nhất và liên hệ yếu nhất với đầu tư: hệ số góc của nó hàm ý một tham số chi phí điều chỉnh gấp hơn mười lần giá trị thực, chính là các chi phí điều chỉnh lớn đến mức phi lý quen thuộc của tài liệu đầu tư-\(Q\). \(Q\) khớp loại bỏ sai số đo lường và phần lớn thiên lệch, nhưng vì nó vẫn là \(Q\) bình quân nên nó phóng đại \(q\) biên, và hệ số góc của nó chỉ bằng khoảng một nửa giá trị thực. \(q\) biên ước lượng khôi phục được cả mức và hệ số góc của chuỗi thực. Phần chênh lệch còn lại phản ánh sai số ước lượng ở bước đầu, đó là lý do suy luận về các hệ số ở bước hai nên bootstrap toàn bộ quy trình theo doanh nghiệp thay vì coi \(\hat{q}\) như dữ liệu.

Áp dụng công cụ ước lượng này cho các doanh nghiệp niêm yết Việt Nam theo cùng các bước, với vốn được đo bằng PPE ròng đầu năm, \(V\) bằng giá trị thị trường của vốn chủ sở hữu cộng nợ sổ sách, và năng suất bằng phần dư hàm sản xuất doanh thu được ước lượng theo từng ngành.

Marginal q for Vietnamese listed firms
mq = panel.copy()

# Capital stock: beginning-of-year net PPE (gross PPE if available)
mq["K"] = mq["lag_ppe"]
mq = mq[(mq["K"] > 0) & (mq["revenue"] > 0)].copy()

# Average Q on capital and investment rate on capital
mq["tobins_q_k"] = (mq["market_cap"] + mq["total_debt"]) / mq["K"]
mq = mq[mq["tobins_q_k"] > 0].copy()
mq["ln_q"] = np.log(mq["tobins_q_k"])
mq["ln_k"] = np.log(mq["K"])
mq["inv_rate_k"] = mq["capex"] / mq["K"]
mq["cf_k"] = mq["operating_cf"] / mq["K"]

# Productivity: residual of a within-firm revenue production function,
# estimated separately by industry. A control-function estimator
# (Olley-Pakes, Levinsohn-Petrin, Ackerberg-Caves-Frazer) is preferable
# when labor and materials data are available.
mq["ln_y"] = np.log(mq["revenue"])
theta = {}
for ind, g in mq.groupby("industry"):
    g = g.set_index(["ticker", "year"])
    if g.index.get_level_values(0).nunique() < 10:
        continue
    pf = PanelOLS(g["ln_y"], g[["ln_k"]], entity_effects=True,
                  time_effects=True, check_rank=False).fit()
    theta[ind] = pf.params["ln_k"]
mq["theta"] = mq["industry"].map(theta)
mq["ln_a"] = mq["ln_y"] - mq["theta"] * mq["ln_k"]

# Trim the tails of the regression variables at 0.5% and 99.5%
for col in ["ln_q", "ln_k", "ln_a", "inv_rate_k", "cf_k"]:
    lo, hi = mq[col].quantile([0.005, 0.995])
    mq = mq[mq[col].between(lo, hi)]

# Keep firms with at least two observations
mq = mq[mq.groupby("ticker")["year"].transform("count") >= 2]

vn_est, vn_fit, vn_qq = estimate_marginal_q(mq)
print(vn_fit.summary)
print(f"Wald test of q = Q: chi2 = {vn_qq.stat:.1f}, p = {vn_qq.pval:.4f}")
print(f"Share of firm-years with negative marginal q: "
      f"{(vn_est['marginal_q'] < 0).mean():.3f}")
Bảng 43.5: Đầu tư theo Q của Tobin, Q khớp và q biên: các doanh nghiệp niêm yết Việt Nam
Hiện mã
vn_rows = []
for label, col in [("Tobin's Q", "tobins_q_k"),
                   ("Fitted Q", "fitted_q"),
                   ("Marginal q", "marginal_q")]:
    d = vn_est.set_index(["ticker", "year"])
    for with_cf in [False, True]:
        regressors = [col, "cf_k"] if with_cf else [col]
        res = PanelOLS(d["inv_rate_k"], d[regressors], entity_effects=True,
                       time_effects=True, check_rank=False).fit(
            cov_type="clustered", cluster_entity=True)
        vn_rows.append({
            "Q measure": label,
            "Cash flow": "Yes" if with_cf else "No",
            "Slope on Q": f"{res.params[col]:.3f} ({res.std_errors[col]:.3f})",
            "Slope on CF/K": (f"{res.params['cf_k']:.3f} "
                              f"({res.std_errors['cf_k']:.3f})")
                             if with_cf else "",
            "Within R²": round(res.rsquared_within, 3),
            "N": int(res.nobs),
        })

pd.DataFrame(vn_rows)

Một số đặc điểm của bối cảnh Việt Nam ảnh hưởng đến việc triển khai và diễn giải.

\(Q\) khớp là câu trả lời tự nhiên cho giá nhiễu. Các vấn đề đo lường đã liệt kê ở phần trước của mục này (định giá sai do nhà đầu tư cá nhân, biên độ giá nén tử số, giao dịch mỏng) đều là những dạng biến thiên của giá trị thị trường không liên quan đến trạng thái cơ bản của doanh nghiệp. Phép chiếu ở bước đầu loại bỏ đúng phần biến thiên đó, nên ở Việt Nam mức lợi từ \(Q\) khớp so với \(Q\) quan sát có thể lớn hơn so với dữ liệu Mỹ.

Trữ lượng vốn cần được định nghĩa một cách có chủ đích. PPE sổ sách xấp xỉ kém chi phí thay thế khi tài sản cố định hiếm khi được đánh giá lại, và quyền sử dụng đất, vốn về kinh tế là một phần vốn của các doanh nghiệp bất động sản, khu công nghiệp và nhiều doanh nghiệp sản xuất, lại được ghi nhận là tài sản vô hình theo chuẩn mực kế toán Việt Nam. Hãy báo cáo kết quả khi có và không có quyền sử dụng đất trong \(K\). Hiệu ứng cố định theo doanh nghiệp hấp thụ phần lớn sai số tỷ lệ bất biến theo thời gian trong vốn đo được, nhưng không hấp thụ được một lần đánh giá lại xảy ra giữa mẫu, chẳng hạn khi cổ phần hóa.

Dữ liệu năng suất là ràng buộc then chốt. Các công cụ ước lượng hàm kiểm soát cần dữ liệu lao động hoặc đầu vào trung gian. Số lượng nhân viên xuất hiện trong nhiều báo cáo thường niên nhưng không nhất quán trong các cơ sở dữ liệu, nên phần dư doanh thu dùng ở trên là phương án dự phòng. Điểm yếu chính của nó, tương quan giữa vốn và cú sốc năng suất đồng thời, làm \(\theta\) chệch lên và dịch chuyển năng suất đo được tương ứng.

Các biến trạng thái bổ sung có thể đưa vào hàm giá trị. Sở hữu nhà nước, room ngoại và việc thuộc tập đoàn kinh doanh đều có thể ảnh hưởng đến giá trị doanh nghiệp. Phép chiếu cho phép đưa chúng vào như các biến trạng thái bổ sung, nhưng chỉ khi chúng ngoại sinh đối với các quyết định hiện tại của doanh nghiệp, vì \(q\) biên được nhận dạng từ các trạng thái ngoại sinh (chú thích của các tác giả về nhận dạng nói rất rõ điều này).

Xem lại các kết quả trước đó với \(q\) biên. Tương tác sở hữu nhà nước trong Bảng 43.3 và các kiểm định độ nhạy dòng tiền bên dưới được chạy với \(Q\) bình quân. Nếu, như trong dữ liệu Mỹ, \(q\) biên loại bỏ dòng tiền, thì phần lớn những gì có vẻ là ràng buộc tài chính trong các hồi quy đầu tư của Việt Nam thực chất là các cơ hội đầu tư bị đo sai. Nếu dòng tiền vẫn còn ý nghĩa, đặc biệt ở các doanh nghiệp ngoài nhà nước có khả năng tiếp cận ngân hàng hạn chế, đó là bằng chứng về ràng buộc mạnh hơn bất kỳ kết quả nào thu được với \(Q\) bình quân.

43.2 Độ nhạy dòng tiền của đầu tư

43.2.1 Giả thuyết ràng buộc tài chính

Tài liệu về độ nhạy dòng tiền của đầu tư (CFSI) kiểm định xem các quyết định đầu tư của doanh nghiệp có bị ràng buộc bởi mức sẵn có của nguồn vốn nội bộ hay không. Trong thế giới Modigliani-Miller, vốn nội bộ và vốn bên ngoài có thể thay thế hoàn hảo cho nhau, nên dòng tiền lẽ ra không liên quan đến đầu tư sau khi kiểm soát các cơ hội đầu tư. Cách tiếp cận CFSI, do Fazzari, Hubbard, và Petersen (1987) tiên phong, phân loại doanh nghiệp là bị ràng buộc hay không bị ràng buộc tài chính dựa trên các đặc điểm quan sát được và kiểm định xem các doanh nghiệp bị ràng buộc có độ nhạy của đầu tư đối với dòng tiền cao hơn hay không.

Hồi quy đầu tư mở rộng là:

\[ \frac{I_{i,t}}{K_{i,t-1}} = \beta_0 + \beta_1 Q_{i,t} + \beta_2 \frac{CF_{i,t}}{K_{i,t-1}} + \varepsilon_{i,t} \tag{43.8}\]

Giả thuyết CFSI dự đoán \(\beta_2^{\text{constrained}} > \beta_2^{\text{unconstrained}} > 0\): các doanh nghiệp bị ràng buộc dựa nhiều hơn vào dòng tiền nội bộ để tài trợ đầu tư vì tài chính bên ngoài đắt đỏ hoặc không có sẵn.

43.2.2 Tranh luận FHP-KZ

Fazzari, Hubbard, và Petersen (1987) (FHP) phân loại doanh nghiệp theo tỷ lệ chi trả cổ tức và nhận thấy các doanh nghiệp chi trả thấp (được cho là bị ràng buộc) có độ nhạy dòng tiền cao hơn đáng kể. Kaplan và Zingales (1997) (KZ) thách thức cách diễn giải này trên hai căn cứ:

Phê phán 1: sai số đo lường của \(Q\). Nếu \(Q\) là biến đại diện có nhiễu cho các cơ hội đầu tư thực, và dòng tiền tương quan với sai số đo lường (vì cả hai cùng phản ứng với các cú sốc cầu), thì hệ số dòng tiền nắm bắt các cơ hội đầu tư bị bỏ sót, chứ không phải ràng buộc tài chính.

Phê phán 2: Vi phạm tính đơn điệu. KZ cho thấy các doanh nghiệp mà FHP phân loại là “bị ràng buộc nhiều nhất” (doanh nghiệp chi trả thấp) thường là các doanh nghiệp tăng trưởng nhanh chọn giữ lại lợi nhuận để đầu tư, chứ không phải các doanh nghiệp bị từ chối tài trợ bên ngoài. Sử dụng thông tin định tính từ các báo cáo thường niên, KZ phân loại lại doanh nghiệp và nhận thấy thứ hạng CFSI đảo ngược: các doanh nghiệp được đánh giá là thực sự bị ràng buộc theo chính công bố của họ có CFSI thấp hơn các doanh nghiệp không bị ràng buộc.

Cách giải quyết, như Farre-Mensa và Ljungqvist (2016) lập luận, là không có biến đại diện đơn lẻ nào xác định đáng tin cậy các doanh nghiệp bị ràng buộc tài chính. Mỗi biến đại diện (quy mô, tuổi, tỷ lệ chi trả, xếp hạng trái phiếu, chỉ số KZ, chỉ số WW, chỉ số SA) nắm bắt một khía cạnh khác nhau của môi trường tài chính, và kiểm định CFSI không phải là phép kiểm định sạch cho bất kỳ lý thuyết đơn lẻ nào.

43.2.3 Các chỉ số ràng buộc

Chúng ta cài đặt ba thước đo ràng buộc tổng hợp được sử dụng rộng rãi nhất.

Chỉ số KZ (Kaplan và Zingales 1997; Lamont, Polk, và Saaá-Requejo 2001):

\[ \text{KZ}_{i,t} = -1.002 \cdot \frac{CF_{i,t}}{K_{i,t-1}} + 0.283 \cdot Q_{i,t} + 3.139 \cdot \frac{D_{i,t}}{A_{i,t}} - 39.368 \cdot \frac{\text{Div}_{i,t}}{K_{i,t-1}} - 1.315 \cdot \frac{C_{i,t}}{K_{i,t-1}} \tag{43.9}\]

Chỉ số WW (Whited và Wu 2006):

\[ \text{WW}_{i,t} = -0.091 \cdot \frac{CF_{i,t}}{A_{i,t}} - 0.062 \cdot \mathbb{1}(\text{Div} > 0) + 0.021 \cdot \frac{D_{i,t}}{A_{i,t}} - 0.044 \cdot \ln(A_{i,t}) + 0.102 \cdot \text{ISG}_{i,t} - 0.035 \cdot \text{SG}_{i,t} \tag{43.10}\]

trong đó ISG là tăng trưởng doanh thu ngành và SG là tăng trưởng doanh thu của doanh nghiệp.

Chỉ số SA (Hadlock và Pierce 2010):

\[ \text{SA}_{i,t} = -0.737 \cdot \text{Size}_{i,t} + 0.043 \cdot \text{Size}_{i,t}^2 - 0.040 \cdot \text{Age}_{i,t} \tag{43.11}\]

trong đó Size \(= \ln(\text{Total Assets})\) và Age là số năm kể từ khi niêm yết. Hadlock và Pierce (2010) lập luận rằng chỉ số SA được ưu tiên hơn vì nó chỉ dùng các đặc điểm ngoại sinh của doanh nghiệp (quy mô và tuổi), tránh được tính nội sinh vốn có trong các chỉ số dựa trên dòng tiền và đòn bẩy.

Hiện mã
# Compute financial constraint indices
panel_fc = panel_clean.copy()

# Lagged PPE for KZ scaling
panel_fc["lag_ppe"] = panel_fc.groupby("ticker")["ppe_net"].shift(1)

# KZ Index
panel_fc["kz_index"] = (
    -1.002 * panel_fc["cf_assets"]
    + 0.283 * panel_fc["tobins_q"]
    + 3.139 * (panel_fc["total_debt"] / panel_fc["total_assets"])
    - 39.368 * (panel_fc["dividends"] / panel_fc["lag_assets"])
    - 1.315 * (panel_fc["cash"] / panel_fc["lag_assets"])
)

# SA Index
panel_fc["log_assets"] = np.log(panel_fc["total_assets"])
panel_fc["listing_age"] = panel_fc["year"] - panel_fc["listing_year"]

panel_fc["sa_index"] = (
    -0.737 * panel_fc["log_assets"]
    + 0.043 * panel_fc["log_assets"]**2
    - 0.040 * panel_fc["listing_age"]
)

# WW Index (simplified: using firm-level variables)
panel_fc["div_dummy"] = (panel_fc["dividends"] > 0).astype(int)
panel_fc["leverage"] = panel_fc["total_debt"] / panel_fc["total_assets"]

# Industry sales growth
panel_fc["isg"] = panel_fc.groupby(
    ["industry", "year"]
)["sales_growth"].transform("median")

panel_fc["ww_index"] = (
    -0.091 * panel_fc["cf_assets"]
    - 0.062 * panel_fc["div_dummy"]
    + 0.021 * panel_fc["leverage"]
    - 0.044 * panel_fc["log_assets"]
    + 0.102 * panel_fc["isg"]
    - 0.035 * panel_fc["sales_growth"]
)
Bảng 43.6: Phân phối của các chỉ số ràng buộc tài chính
Hiện mã
constraint_vars = ["kz_index", "sa_index", "ww_index"]
constraint_summary = (
    panel_fc[constraint_vars]
    .describe(percentiles=[0.1, 0.25, 0.5, 0.75, 0.9])
    .T.round(4)
)
constraint_summary

43.2.4 Kiểm định CFSI chia mẫu

Chúng ta phân loại doanh nghiệp thành nhóm bị ràng buộc và không bị ràng buộc theo từng chỉ số và so sánh độ nhạy dòng tiền của đầu tư giữa các nhóm.

Hiện mã
def cfsi_by_group(data, group_var, threshold="median"):
    """
    Estimate cash flow sensitivity of investment by constraint group.

    Parameters
    ----------
    data : DataFrame
        Panel data with inv_rate, tobins_q, cf_assets, group_var.
    group_var : str
        Variable used for classification.
    threshold : str
        "median" for sample split or "tercile" for top/bottom third.

    Returns
    -------
    dict : Coefficient estimates by group.
    """
    df = data.dropna(subset=["inv_rate", "tobins_q", "cf_assets", group_var])

    if threshold == "median":
        median_val = df[group_var].median()
        df["constrained"] = (df[group_var] >= median_val).astype(int)
    elif threshold == "tercile":
        t33 = df[group_var].quantile(0.33)
        t67 = df[group_var].quantile(0.67)
        df = df[(df[group_var] <= t33) | (df[group_var] >= t67)]
        df["constrained"] = (df[group_var] >= t67).astype(int)

    results = {}
    for group_name, group_label in [(0, "Unconstrained"), (1, "Constrained")]:
        subset = df[df["constrained"] == group_name].copy()
        if len(subset) < 100:
            continue

        subset = subset.set_index(["ticker", "year"])
        model = PanelOLS(
            subset["inv_rate"],
            subset[["tobins_q", "cf_assets"]],
            entity_effects=True,
            time_effects=True,
            check_rank=False
        ).fit(cov_type="clustered", cluster_entity=True)

        results[group_label] = {
            "beta_Q": model.params["tobins_q"],
            "se_Q": model.std_errors["tobins_q"],
            "beta_CF": model.params["cf_assets"],
            "se_CF": model.std_errors["cf_assets"],
            "R2_within": model.rsquared_within,
            "N": int(model.nobs)
        }

    return pd.DataFrame(results).T

# Run for each constraint index
cfsi_kz = cfsi_by_group(panel_fc, "kz_index", "median")
cfsi_sa = cfsi_by_group(panel_fc, "sa_index", "median")
cfsi_ww = cfsi_by_group(panel_fc, "ww_index", "median")
Bảng 43.7: Độ nhạy dòng tiền theo phân loại ràng buộc tài chính
Hiện mã
# Combine results
cfsi_all = pd.concat({
    "KZ Index": cfsi_kz,
    "SA Index": cfsi_sa,
    "WW Index": cfsi_ww
})

cfsi_display = cfsi_all[["beta_CF", "se_CF", "beta_Q", "se_Q", "N"]].round(4)
cfsi_display

43.2.5 Các đặc tả thay thế

Kiểm định CFSI cơ sở đã được mở rộng theo nhiều hướng:

Mô hình đầu tư động. S. Bond và c.s. (2003) lập luận rằng hồi quy tĩnh Phương trình 43.8 bỏ sót thành phần tự hồi quy của đầu tư. Cách tiếp cận phương trình Euler, suy ra trực tiếp từ bài toán tối ưu động của doanh nghiệp, cho ra:

\[ \frac{I_{i,t}}{K_{i,t-1}} = \gamma_1 \frac{I_{i,t-1}}{K_{i,t-2}} + \gamma_2 \left(\frac{Y_{i,t}}{K_{i,t-1}}\right) + \gamma_3 \frac{CF_{i,t}}{K_{i,t-1}} + \varepsilon_{i,t} \tag{43.12}\]

Đặc tả này tránh hoàn toàn việc cần đến \(Q\), qua đó né được vấn đề sai số đo lường.

Phụ thuộc vào tài chính bên ngoài. Rajan và Zingales (1998) đề xuất dùng nhu cầu kỹ thuật về tài chính bên ngoài ở cấp ngành làm công cụ cho ràng buộc tài chính. Các ngành đòi hỏi về mặt công nghệ nhiều vốn bên ngoài hơn sẽ chịu ảnh hưởng không cân xứng từ phát triển tài chính và các ràng buộc ở cấp doanh nghiệp.

Hiện mã
# Euler equation investment model (dynamic panel)
panel_euler = panel_fc.copy().sort_values(["ticker", "year"])

panel_euler["lag_inv_rate"] = panel_euler.groupby("ticker")["inv_rate"].shift(1)
panel_euler["revenue_assets"] = panel_euler["revenue"] / panel_euler["lag_assets"]

euler_data = panel_euler.dropna(
    subset=["inv_rate", "lag_inv_rate", "revenue_assets", "cf_assets"]
).set_index(["ticker", "year"])

model_euler = PanelOLS(
    euler_data["inv_rate"],
    euler_data[["lag_inv_rate", "revenue_assets", "cf_assets"]],
    entity_effects=True,
    time_effects=True,
    check_rank=False
).fit(cov_type="clustered", cluster_entity=True)

euler_data = euler_data.reset_index()
Bảng 43.8: Mô hình đầu tư phương trình Euler
Hiện mã
euler_results = pd.DataFrame({
    "Coefficient": model_euler.params.round(4),
    "Std Error": model_euler.std_errors.round(4),
    "t-stat": model_euler.tstats.round(3),
    "p-value": model_euler.pvalues.round(4)
})
euler_results

43.3 Các mô hình lựa chọn tài trợ

43.3.1 Các yếu tố quyết định cấu trúc vốn

Hai lý thuyết chi phối về cấu trúc vốn (tức là lý thuyết đánh đổi và lý thuyết trật tự phân hạng) đưa ra các dự đoán khác nhau về các yếu tố quyết định đòn bẩy. Frank và Goyal (2009) cung cấp bản tổng hợp thực nghiệm toàn diện nhất, xác định sáu biến “cốt lõi” dự đoán đòn bẩy một cách đáng tin cậy trên nhiều mẫu và đặc tả.

Hồi quy cấu trúc vốn cơ sở là:

\[ \text{Lev}_{i,t} = \beta_0 + \boldsymbol{\beta}' \mathbf{X}_{i,t} + \alpha_i + \delta_t + \varepsilon_{i,t} \tag{43.13}\]

trong đó \(\text{Lev}_{i,t}\) là đòn bẩy sổ sách (\(D / A\)) hoặc đòn bẩy thị trường (\(D / (D + E^{\text{mkt}})\)), và \(\mathbf{X}_{i,t}\) gồm các yếu tố quyết định cốt lõi.

Bảng 43.9 tóm tắt các dự đoán lý thuyết.

Bảng 43.9: Dự đoán cấu trúc vốn theo từng lý thuyết
Yếu tố quyết định Đánh đổi Trật tự phân hạng Cách đo
Khả năng sinh lời + (lá chắn thuế) − (ít cần tài trợ bên ngoài) EBITDA / Tài sản
Quy mô + (chi phí kiệt quệ thấp hơn) + (ít bất cân xứng thông tin hơn) ln(Tổng tài sản)
Tính hữu hình + (giá trị tài sản đảm bảo) + (ít lựa chọn bất lợi hơn) PPE / Tài sản
Tăng trưởng (MTB) − (đầu tư dưới mức) + (nhu cầu tài trợ) Giá thị trường / Giá sổ sách
Đòn bẩy trung vị ngành + (mục tiêu) không rõ Trung vị ngành
Biến động khả năng sinh lời − (rủi ro kiệt quệ) không rõ σ(EBITDA/A) trượt
Hiện mã
# Construct capital structure variables
cs = panel_fc.copy()

# Book leverage
cs["book_leverage"] = cs["total_debt"] / cs["total_assets"]

# Market leverage
cs["market_leverage"] = cs["total_debt"] / (
    cs["total_debt"] + cs["market_cap"]
)

# Profitability
cs["profitability"] = cs["ebitda"] / cs["total_assets"]

# Tangibility
cs["tangibility"] = cs["ppe_net"] / cs["total_assets"]

# Size
cs["size"] = np.log(cs["total_assets"])

# Market-to-Book
cs["mtb"] = cs["market_cap"] / cs["book_equity"]

# Industry median leverage
cs["ind_median_lev"] = cs.groupby(
    ["industry", "year"]
)["book_leverage"].transform("median")

# Rolling profitability volatility (3-year)
cs = cs.sort_values(["ticker", "year"])
cs["profit_vol"] = (
    cs.groupby("ticker")["profitability"]
    .transform(lambda x: x.rolling(3, min_periods=2).std())
)

# Winsorize
for col in ["book_leverage", "market_leverage", "profitability",
            "tangibility", "mtb", "profit_vol"]:
    cs[col] = winsorize(cs[col])

cs_clean = cs.dropna(
    subset=["book_leverage", "profitability", "size",
            "tangibility", "mtb", "ind_median_lev"]
)
Hiện mã
# Capital structure regressions
cs_panel = cs_clean.set_index(["ticker", "year"])

regressors = ["profitability", "size", "tangibility",
              "mtb", "ind_median_lev"]

# Book leverage
model_book = PanelOLS(
    cs_panel["book_leverage"],
    cs_panel[regressors],
    entity_effects=True,
    time_effects=True,
    check_rank=False
).fit(cov_type="clustered", cluster_entity=True)

# Market leverage
model_mkt = PanelOLS(
    cs_panel["market_leverage"],
    cs_panel[regressors],
    entity_effects=True,
    time_effects=True,
    check_rank=False
).fit(cov_type="clustered", cluster_entity=True)

cs_panel = cs_panel.reset_index()
Bảng 43.10: Các yếu tố quyết định cấu trúc vốn: đòn bẩy sổ sách và thị trường
Hiện mã
cs_table = pd.DataFrame({
    "Book Leverage": [
        f"{model_book.params[v]:.4f} ({model_book.std_errors[v]:.4f})"
        for v in regressors
    ] + [f"{model_book.rsquared_within:.4f}", str(int(model_book.nobs))],
    "Market Leverage": [
        f"{model_mkt.params[v]:.4f} ({model_mkt.std_errors[v]:.4f})"
        for v in regressors
    ] + [f"{model_mkt.rsquared_within:.4f}", str(int(model_mkt.nobs))]
}, index=regressors + ["R² (within)", "N"])

cs_table

43.3.2 Kiểm định trật tự phân hạng

Lý thuyết trật tự phân hạng (Myers 1984) dự đoán rằng doanh nghiệp ưu tiên tài chính nội bộ, rồi đến nợ, rồi đến vốn cổ phần. Shyam-Sunder và Myers (1999) đề xuất một kiểm định trực tiếp: nếu trật tự phân hạng đúng một cách nghiêm ngặt, thâm hụt tài chính (đầu tư trừ nguồn vốn nội bộ) phải được tài trợ từng đồng một bằng nợ:

\[ \Delta D_{i,t} = \alpha + \beta_{\text{PO}} \cdot \text{DEF}_{i,t} + \varepsilon_{i,t} \tag{43.14}\]

trong đó \(\text{DEF}_{i,t} = \text{Div}_{i,t} + \text{Capex}_{i,t} + \Delta W_{i,t} - CF_{i,t}\) là thâm hụt tài chính và \(\Delta D_{i,t}\) là phát hành nợ ròng. Một trật tự phân hạng nghiêm ngặt hàm ý \(\hat{\alpha} = 0\) và \(\hat{\beta}_{\text{PO}} = 1\). Frank và Goyal (2003) cho thấy hệ số này thường thấp hơn nhiều so với 1, đặc biệt đối với các doanh nghiệp lớn và các doanh nghiệp phát hành cổ phiếu.

Hiện mã
# Construct financing deficit
po = cs.copy().sort_values(["ticker", "year"])
po["lag_debt"] = po.groupby("ticker")["total_debt"].shift(1)
po["net_debt_issuance"] = po["total_debt"] - po["lag_debt"]

# Financing deficit = Div + Capex + ΔWC - CF
po["delta_wc"] = po["working_capital"] - po.groupby(
    "ticker"
)["working_capital"].shift(1)

po["fin_deficit"] = (
    po["dividends"] + po["capex"]
    + po["delta_wc"].fillna(0) - po["operating_cf"]
)

# Scale by lagged assets
for col in ["net_debt_issuance", "fin_deficit"]:
    po[col] = po[col] / po["lag_assets"]

po_clean = po.dropna(
    subset=["net_debt_issuance", "fin_deficit"]
)

# Winsorize
for col in ["net_debt_issuance", "fin_deficit"]:
    po_clean[col] = winsorize(po_clean[col])

# Pecking order regression
po_panel = po_clean.set_index(["ticker", "year"])

model_po = PanelOLS(
    po_panel["net_debt_issuance"],
    po_panel[["fin_deficit"]],
    entity_effects=True,
    time_effects=True,
    check_rank=False
).fit(cov_type="clustered", cluster_entity=True)

po_panel = po_panel.reset_index()

print(f"Pecking order coefficient: {model_po.params['fin_deficit']:.4f}")
print(f"  (se = {model_po.std_errors['fin_deficit']:.4f})")
print(f"  H0: β = 1, t = "
      f"{(model_po.params['fin_deficit'] - 1) / model_po.std_errors['fin_deficit']:.3f}")

43.3.3 Các thước đo định thời điểm thị trường

Baker và Wurgler (2002) lập luận rằng cấu trúc vốn phần lớn là kết quả tích lũy của việc định thời điểm thị trường (tức là doanh nghiệp phát hành cổ phiếu khi định giá cao và mua lại khi định giá thấp). Biến then chốt của họ là tỷ số giá thị trường trên giá sổ sách bình quân gia quyền theo tài chính bên ngoài:

\[ \left(\frac{M}{B}\right)_{i,t}^{efwa} = \sum_{s=\text{IPO}}^{t-1} \frac{e_s + d_s}{\sum_{r=\text{IPO}}^{t-1}(e_r + d_r)} \cdot \left(\frac{M}{B}\right)_{i,s} \tag{43.15}\]

trong đó \(e_s\) và \(d_s\) là phát hành vốn cổ phần ròng và phát hành nợ ròng trong năm \(s\). Biến này nắm bắt các mức định giá lịch sử tại đó doanh nghiệp đã huy động vốn. Giả thuyết định thời điểm thị trường dự đoán rằng \(\left(M/B\right)^{efwa}\) cao hơn gắn với đòn bẩy hiện tại thấp hơn (tức là các doanh nghiệp từng phát hành cổ phiếu ở mức định giá cao có đòn bẩy thấp một cách dai dẳng).

Hiện mã
# External-Finance-Weighted Average M/B
def compute_efwa_mtb(group):
    """Compute Baker-Wurgler EFWA M/B for one firm."""
    g = group.sort_values("year").copy()

    # Net issuance each year
    g["net_equity"] = g["equity_issuance"].fillna(0)
    g["net_debt"] = g["net_debt_issuance"].fillna(0)
    g["total_issuance"] = (
        g["net_equity"].abs() + g["net_debt"].abs()
    ).replace(0, np.nan)

    efwa_values = []
    for idx in range(1, len(g)):
        past = g.iloc[:idx]
        weights = past["total_issuance"] / past["total_issuance"].sum()
        weights = weights.fillna(0)
        efwa = (weights * past["mtb"]).sum()
        efwa_values.append(efwa)

    g = g.iloc[1:].copy()
    g["efwa_mtb"] = efwa_values
    return g[["ticker", "year", "efwa_mtb"]]

mt = po_clean.copy()
mt["equity_issuance"] = mt["market_cap"] - mt.groupby(
    "ticker"
)["market_cap"].shift(1) - mt["net_income"]

efwa_data = (
    mt.groupby("ticker", group_keys=False)
    .apply(compute_efwa_mtb)
    .reset_index(drop=True)
)

# Merge and regress
mt_merged = cs_clean.merge(efwa_data, on=["ticker", "year"], how="left")
mt_clean = mt_merged.dropna(
    subset=["market_leverage", "efwa_mtb", "profitability",
            "size", "tangibility", "mtb"]
)

mt_panel = mt_clean.set_index(["ticker", "year"])

model_mt = PanelOLS(
    mt_panel["market_leverage"],
    mt_panel[["efwa_mtb", "mtb", "profitability", "size", "tangibility"]],
    entity_effects=True,
    time_effects=True,
    check_rank=False
).fit(cov_type="clustered", cluster_entity=True)

mt_panel = mt_panel.reset_index()
Bảng 43.11: Định thời điểm thị trường và cấu trúc vốn
Hiện mã
mt_results = pd.DataFrame({
    "Coefficient": model_mt.params.round(4),
    "Std Error": model_mt.std_errors.round(4),
    "t-stat": model_mt.tstats.round(3),
    "p-value": model_mt.pvalues.round(4)
})
mt_results

Hệ số âm của \(\text{EFWA}_{M/B}\) sau khi kiểm soát \(M/B\) hiện tại (đại diện cho các cơ hội đầu tư hiện tại) ủng hộ giả thuyết định thời điểm thị trường: các doanh nghiệp từng huy động vốn ở mức định giá cao duy trì đòn bẩy thấp một cách dai dẳng.

43.4 Các công cụ ước lượng chính sách chi trả

43.4.1 Làm mượt cổ tức

Lintner (1956) đã xác lập mô hình nền tảng về hành vi cổ tức: doanh nghiệp nhắm tới một tỷ lệ chi trả mục tiêu và điều chỉnh cổ tức từng phần về phía mục tiêu mỗi năm. Mô hình điều chỉnh từng phần là:

\[ \Delta D_{i,t} = \alpha_i + \lambda(\tau \cdot E_{i,t} - D_{i,t-1}) + \varepsilon_{i,t} \tag{43.16}\]

trong đó \(D_{i,t}\) là cổ tức trên mỗi cổ phiếu, \(E_{i,t}\) là thu nhập trên mỗi cổ phiếu, \(\tau\) là tỷ lệ chi trả mục tiêu, và \(\lambda \in (0, 1)\) là tốc độ điều chỉnh. \(\lambda\) thấp hàm ý làm mượt mạnh (tức là doanh nghiệp điều chỉnh cổ tức chậm về phía mục tiêu). Sắp xếp lại:

\[ D_{i,t} = \alpha_i + (1 - \lambda) D_{i,t-1} + \lambda \tau \cdot E_{i,t} + \varepsilon_{i,t} \tag{43.17}\]

Hệ số của cổ tức trễ, \((1 - \lambda)\), đo mức độ làm mượt. Giá trị gần 1 cho thấy làm mượt gần như hoàn toàn; giá trị gần 0 cho thấy không làm mượt (điều chỉnh đầy đủ).

Hiện mã
# Construct dividend and earnings variables
div = panel_fc.copy().sort_values(["ticker", "year"])

div["lag_dps"] = div.groupby("ticker")["dividends_per_share"].shift(1)
div["delta_dps"] = div["dividends_per_share"] - div["lag_dps"]

# Only firms with positive dividends in both periods
div_clean = div.dropna(
    subset=["dividends_per_share", "lag_dps", "eps"]
).query("lag_dps > 0 and dividends_per_share > 0")

# Lintner regression
div_panel = div_clean.set_index(["ticker", "year"])

model_lintner = PanelOLS(
    div_panel["dividends_per_share"],
    div_panel[["lag_dps", "eps"]],
    entity_effects=True,
    time_effects=True,
    check_rank=False
).fit(cov_type="clustered", cluster_entity=True)

div_panel = div_panel.reset_index()

# Extract structural parameters
lambda_hat = 1 - model_lintner.params["lag_dps"]
tau_hat = model_lintner.params["eps"] / lambda_hat

print(f"Lintner Model Estimates:")
print(f"  Speed of adjustment (λ): {lambda_hat:.4f}")
print(f"  Target payout ratio (τ): {tau_hat:.4f}")
print(f"  Smoothing coefficient (1-λ): {model_lintner.params['lag_dps']:.4f}")
Bảng 43.12: Mô hình điều chỉnh từng phần của Lintner
Hiện mã
lintner_table = pd.DataFrame({
    "Coefficient": model_lintner.params.round(4),
    "Std Error": model_lintner.std_errors.round(4),
    "t-stat": model_lintner.tstats.round(3),
    "p-value": model_lintner.pvalues.round(4)
})
lintner_table
Hiện mã
payout = panel_fc.copy()
payout["payout_ratio"] = payout["dividends"] / payout["net_income"]
payout = payout[
    (payout["net_income"] > 0) &
    (payout["payout_ratio"].between(0, 2))
]

payout_ts = (
    payout.groupby("year")
    .agg(
        median_payout=("payout_ratio", "median"),
        mean_payout=("payout_ratio", "mean"),
        q25=("payout_ratio", lambda x: x.quantile(0.25)),
        q75=("payout_ratio", lambda x: x.quantile(0.75)),
        pct_payers=("payout_ratio", lambda x: (x > 0).mean())
    )
    .reset_index()
)

(
    p9.ggplot(payout_ts, p9.aes(x="year"))
    + p9.geom_ribbon(
        p9.aes(ymin="q25", ymax="q75"),
        fill="#2E5090", alpha=0.2
    )
    + p9.geom_line(
        p9.aes(y="median_payout"),
        color="#2E5090", size=1
    )
    + p9.geom_line(
        p9.aes(y="mean_payout"),
        color="#C0392B", linetype="dashed", size=0.7
    )
    + p9.labs(
        x="Year",
        y="Dividend Payout Ratio",
        title="Payout Ratio: Median (Solid) and Mean (Dashed)"
    )
    + p9.theme_minimal()
    + p9.theme(figure_size=(10, 5))
)
Hình 43.2

43.4.2 Tính không đồng nhất của việc làm mượt: SOE so với doanh nghiệp tư nhân

Chính sách cổ tức ở Việt Nam chịu sự định hình của các yêu cầu quy định. Tổng công ty Đầu tư và Kinh doanh vốn nhà nước (SCIC) và các bộ chủ quản trong lịch sử đã yêu cầu các SOE phân phối mức cổ tức tối thiểu, đôi khi với cái giá là giảm tái đầu tư. Điều này tạo ra một sự bất đối xứng căn bản: cổ tức của SOE một phần do chính sách quyết định chứ không phải kết quả của bài toán tối ưu Lintner.

Hiện mã
# Merge SOE indicator
div_with_soe = div_clean.merge(
    ownership[["ticker", "year", "state_ownership_pct"]],
    on=["ticker", "year"],
    how="left"
)
div_with_soe["soe"] = (div_with_soe["state_ownership_pct"] > 50).astype(int)

# Estimate Lintner model separately for SOEs and private firms
lintner_results = {}
for label, soe_val in [("Private", 0), ("SOE", 1)]:
    subset = div_with_soe[div_with_soe["soe"] == soe_val].copy()
    if len(subset) < 100:
        continue

    subset_panel = subset.set_index(["ticker", "year"])
    model = PanelOLS(
        subset_panel["dividends_per_share"],
        subset_panel[["lag_dps", "eps"]],
        entity_effects=True,
        time_effects=True,
        check_rank=False
    ).fit(cov_type="clustered", cluster_entity=True)

    lam = 1 - model.params["lag_dps"]
    tau = model.params["eps"] / lam if abs(lam) > 0.01 else np.nan

    lintner_results[label] = {
        "Smoothing (1-λ)": round(model.params["lag_dps"], 4),
        "Speed of adj (λ)": round(lam, 4),
        "Target payout (τ)": round(tau, 4),
        "N": int(model.nobs)
    }

pd.DataFrame(lintner_results).T

43.4.3 Mua lại cổ phiếu

Mua lại cổ phiếu là một hiện tượng tương đối mới ở thị trường Việt Nam, dần có sức hút khi các quy định phát triển. Khác với cổ tức, việc mua lại linh hoạt hơn và không tạo ra kỳ vọng về các khoản chi trả trong tương lai. Quyết định mua lại có thể được mô hình hóa như sau:

\[ \text{Repurchase}_{i,t} = \mathbb{1}\left(\beta_0 + \beta_1 \frac{CF_{i,t}}{A_{i,t}} + \beta_2 Q_{i,t} + \beta_3 \text{Lev}_{i,t} + \beta_4 \frac{\text{Cash}_{i,t}}{A_{i,t}} + \boldsymbol{\gamma}' \mathbf{Z}_{i,t} + \varepsilon_{i,t} > 0\right) \tag{43.18}\]

Hiện mã
# Identify repurchase years
repurchase = panel_fc.copy()
repurchase["repurchase_dummy"] = (
    repurchase["share_repurchases"] > 0
).astype(int)

repurchase["cash_assets"] = repurchase["cash"] / repurchase["total_assets"]

# Probit model for repurchase decision
rep_clean = repurchase.dropna(
    subset=["repurchase_dummy", "cf_assets", "tobins_q",
            "book_leverage", "cash_assets", "log_assets"]
)

probit_model = smf.probit(
    "repurchase_dummy ~ cf_assets + tobins_q + book_leverage "
    "+ cash_assets + log_assets + C(year)",
    data=rep_clean
).fit(disp=False, cov_type="cluster", cov_kwds={"groups": rep_clean["ticker"]})
Bảng 43.13: Mô hình Probit: các yếu tố quyết định việc mua lại cổ phiếu
Hiện mã
# Extract non-year-dummy coefficients
main_vars = ["cf_assets", "tobins_q", "book_leverage",
             "cash_assets", "log_assets"]

probit_results = pd.DataFrame({
    "Coefficient": probit_model.params[main_vars].round(4),
    "Std Error": probit_model.bse[main_vars].round(4),
    "z-stat": probit_model.tvalues[main_vars].round(3),
    "p-value": probit_model.pvalues[main_vars].round(4),
    "Marginal Effect": (
        probit_model.get_margeff().margeff[:len(main_vars)]
    ).round(4)
})
probit_results

43.4.4 Các cách diễn giải theo đại diện và tín hiệu

Chính sách chi trả được diễn giải qua hai lăng kính cạnh tranh:

Quan điểm đại diện (Jensen 1986; La Porta và c.s. 2000): Cổ tức là cơ chế buộc doanh nghiệp nhả ra dòng tiền tự do mà các nhà quản lý nếu không sẽ lãng phí vào việc xây dựng đế chế hoặc hưởng đặc quyền. Theo quan điểm này, các doanh nghiệp có quản trị yếu hơn phải chịu áp lực chi trả cổ tức lớn hơn như một công cụ cam kết. La Porta và c.s. (2000) phân biệt mô hình “kết quả” (cổ tức là kết quả của áp lực hiệu quả từ cổ đông thiểu số) với mô hình “thay thế” (các doanh nghiệp quản trị yếu chi trả cổ tức cao để xây dựng uy tín đối xử công bằng).

Quan điểm tín hiệu (Bhattacharya 1979; Miller và Rock 1985): Cổ tức truyền tải thông tin riêng về lợi nhuận kế toán tương lai. Vì cổ tức tốn kém để làm giả (chúng đòi hỏi tiền mặt thực), chúng đóng vai trò là tín hiệu đáng tin cậy. Cách diễn giải theo tín hiệu dự đoán rằng các thay đổi cổ tức phải dự báo được các thay đổi lợi nhuận kế toán trong tương lai.

Hiện mã
# Test dividend signaling: do dividend changes predict future earnings?
signal = panel_fc.copy().sort_values(["ticker", "year"])

signal["delta_div"] = signal.groupby("ticker")["dividends"].diff()
signal["div_increase"] = (signal["delta_div"] > 0).astype(int)
signal["div_decrease"] = (signal["delta_div"] < 0).astype(int)

# Future earnings change
signal["lead_earnings"] = signal.groupby("ticker")["net_income"].shift(-1)
signal["delta_earnings_lead"] = (
    (signal["lead_earnings"] - signal["net_income"]) /
    signal["total_assets"]
)

# Current earnings change (control)
signal["lag_earnings"] = signal.groupby("ticker")["net_income"].shift(1)
signal["delta_earnings_curr"] = (
    (signal["net_income"] - signal["lag_earnings"]) /
    signal["total_assets"]
)

signal_clean = signal.dropna(
    subset=["delta_earnings_lead", "div_increase",
            "div_decrease", "delta_earnings_curr"]
)

# Regression: future earnings change on dividend change indicators
signal_model = smf.ols(
    "delta_earnings_lead ~ div_increase + div_decrease "
    "+ delta_earnings_curr + C(year) + C(industry)",
    data=signal_clean
).fit(cov_type="cluster", cov_kwds={"groups": signal_clean["ticker"]})

print("Dividend Signaling Test:")
for var in ["div_increase", "div_decrease", "delta_earnings_curr"]:
    print(f"  {var}: {signal_model.params[var]:.4f} "
          f"(t = {signal_model.tvalues[var]:.3f})")

43.5 Các biến đại diện cho chi phí đại diện

43.5.1 Tập trung sở hữu và các vấn đề đại diện

Khung đại diện của Jensen và Meckling (2019) xác định sự tách biệt giữa sở hữu và kiểm soát là nguồn gốc căn bản của chi phí đại diện trong doanh nghiệp. Ở các nền kinh tế sở hữu tập trung như Việt Nam, xung đột đại diện chủ đạo không phải giữa các cổ đông phân tán và nhà quản lý chuyên nghiệp (vấn đề đại diện Berle-Means) mà là giữa cổ đông kiểm soát và cổ đông thiểu số (vấn đề đại diện giữa các chủ sở hữu, principal-principal, Young và c.s. (2008)).

Các cơ chế chính mà qua đó cổ đông kiểm soát chiếm đoạt lợi ích riêng gồm: tunneling thông qua các giao dịch với bên liên quan (Johnson và c.s. 2000), chuyển hướng các cơ hội của doanh nghiệp, thù lao quá mức và các đợt phát hành cổ phiếu gây pha loãng. Mức độ của các chi phí này phụ thuộc vào cấu trúc sở hữu, sự bảo vệ pháp lý đối với cổ đông thiểu số và cường độ giám sát.

Hiện mã
# Merge ownership data comprehensively
agency = panel_fc.merge(
    ownership[["ticker", "year", "state_ownership_pct",
               "foreign_ownership_pct", "insider_ownership_pct",
               "largest_shareholder_pct", "top5_shareholder_pct",
               "board_size", "independent_directors_pct",
               "ceo_duality"]],
    on=["ticker", "year"],
    how="left"
)

# Ownership concentration measures
# Herfindahl of top-5 shareholdings
agency["ownership_hhi"] = agency["top5_shareholder_pct"]**2

# Excess control rights (proxy: difference between
# largest shareholder and second largest)
agency["control_wedge"] = (
    agency["largest_shareholder_pct"] -
    (agency["top5_shareholder_pct"] - agency["largest_shareholder_pct"]) / 4
)

43.5.2 Các thước đo dòng tiền tự do

Jensen (1986) lập luận rằng chi phí đại diện của dòng tiền tự do là vấn đề trung tâm ở các doanh nghiệp tạo ra tiền vượt quá các cơ hội đầu tư có NPV dương. Thước đo chuẩn là:

\[ \text{FCF}_{i,t} = \frac{\text{Operating CF}_{i,t} - \text{Depreciation}_{i,t} - \text{Required Capex}_{i,t}}{\text{Total Assets}_{i,t}} \tag{43.19}\]

Trong thực tế, “capex bắt buộc” không quan sát được, nên các nhà nghiên cứu dùng dòng tiền hoạt động trừ chi tiêu vốn làm biến đại diện, hoặc thêm tương tác của dòng tiền với \(Q\) thấp (xác định các doanh nghiệp có dòng tiền nhưng không có cơ hội đầu tư):

\[ \text{FCF Overinvestment} = \frac{CF_{i,t}}{A_{i,t}} \times \mathbb{1}(Q_{i,t} < 1) \tag{43.20}\]

Hiện mã
# Free cash flow measures
agency["fcf"] = (agency["operating_cf"] - agency["capex"]) / agency["total_assets"]

agency["low_q"] = (agency["tobins_q"] < 1).astype(int)
agency["fcf_low_q"] = agency["fcf"] * agency["low_q"]

# Asset utilization (inverse proxy for agency costs)
agency["asset_turnover"] = agency["revenue"] / agency["total_assets"]

# SGA ratio (proxy for discretionary spending / empire building)
agency["sga_ratio"] = agency["sga_expenses"] / agency["revenue"]

43.5.3 Các cơ chế giám sát và biến quản trị

Chúng ta xây dựng một chỉ số tổng hợp về chất lượng quản trị dựa trên các cơ chế giám sát quan sát được:

Hiện mã
# Governance quality indicators
agency["foreign_monitor"] = (
    agency["foreign_ownership_pct"] > 20
).astype(int)

agency["board_independence"] = agency["independent_directors_pct"]

agency["no_duality"] = (1 - agency["ceo_duality"]).astype(int)

# Related-party transaction intensity (if available)
# agency["rpt_ratio"] = agency["related_party_transactions"] / agency["revenue"]
Bảng 43.14: Thống kê mô tả: các biến đại diện chi phí đại diện và biến quản trị
Hiện mã
agency_vars = [
    "largest_shareholder_pct", "state_ownership_pct",
    "foreign_ownership_pct", "fcf", "fcf_low_q",
    "asset_turnover", "board_independence"
]

agency_summary = (
    agency[agency_vars].dropna()
    .describe(percentiles=[0.1, 0.25, 0.5, 0.75, 0.9])
    .T.round(4)
)
agency_summary

43.5.4 Chi phí đại diện và giá trị doanh nghiệp

Chúng ta kiểm định xem các biến đại diện chi phí đại diện có liên hệ với giá trị doanh nghiệp (\(Q\) của Tobin) và hiệu quả hoạt động (ROA) hay không, khi kiểm soát các yếu tố quyết định chuẩn:

\[ Q_{i,t} = \beta_0 + \beta_1 \text{Own}_{i,t} + \beta_2 \text{Own}_{i,t}^2 + \boldsymbol{\gamma}'\mathbf{X}_{i,t} + \alpha_i + \delta_t + \varepsilon_{i,t} \tag{43.21}\]

Số hạng bậc hai của sở hữu nắm bắt tính phi tuyến của Morck, Shleifer, và Vishny (1988): ở mức thấp, sở hữu của nhà quản lý gắn kết động cơ (tác động dương lên \(Q\)); ở mức cao, sự cố thủ chiếm ưu thế (tác động âm).

Hiện mã
# Agency cost and valuation regression
agency["largest_sq"] = agency["largest_shareholder_pct"]**2

val_data = agency.dropna(
    subset=["tobins_q", "largest_shareholder_pct", "foreign_ownership_pct",
            "fcf", "size", "profitability", "leverage"]
).copy()

val_panel = val_data.set_index(["ticker", "year"])

model_val = PanelOLS(
    val_panel["tobins_q"],
    val_panel[["largest_shareholder_pct", "largest_sq",
               "foreign_ownership_pct", "fcf",
               "size", "profitability", "leverage"]],
    entity_effects=True,
    time_effects=True,
    check_rank=False
).fit(cov_type="clustered", cluster_entity=True)

val_panel = val_panel.reset_index()
Bảng 43.15: Các biến đại diện chi phí đại diện và giá trị doanh nghiệp (Q của Tobin)
Hiện mã
val_results = pd.DataFrame({
    "Coefficient": model_val.params.round(4),
    "Std Error": model_val.std_errors.round(4),
    "t-stat": model_val.tstats.round(3),
    "p-value": model_val.pvalues.round(4)
})
val_results
Hiện mã
# Binned scatter: largest shareholder vs Q
own_bins = val_data.copy()
own_bins["own_bin"] = pd.qcut(
    own_bins["largest_shareholder_pct"], q=20, duplicates="drop"
)

own_binned = (
    own_bins.groupby("own_bin", observed=True)
    .agg(
        mean_own=("largest_shareholder_pct", "mean"),
        mean_q=("tobins_q", "mean"),
        se_q=("tobins_q", lambda x: x.std() / np.sqrt(len(x)))
    )
    .reset_index()
)

(
    p9.ggplot(own_binned, p9.aes(x="mean_own", y="mean_q"))
    + p9.geom_pointrange(
        p9.aes(ymin="mean_q - 1.96*se_q",
               ymax="mean_q + 1.96*se_q"),
        color="#2E5090", size=0.5
    )
    + p9.geom_smooth(method="loess", color="#C0392B", se=False, size=0.8)
    + p9.labs(
        x="Largest Shareholder Ownership (%)",
        y="Tobin's Q",
        title="Ownership Concentration and Firm Value"
    )
    + p9.theme_minimal()
    + p9.theme(figure_size=(10, 6))
)
Hình 43.3

Dạng quan hệ hình chữ U ngược, nếu có, sẽ phù hợp với sự đánh đổi giữa gắn kết động cơ và cố thủ của Morck-Shleifer-Vishny. Tại thị trường Việt Nam, dạng quan hệ này có thể khác vì cổ đông kiểm soát chủ đạo thường là Nhà nước, với hàm mục tiêu bao gồm các mục tiêu không nhằm tối đa hóa giá trị (việc làm, phát triển vùng, kiểm soát các ngành chiến lược).

43.6 Liên kết các quyết định doanh nghiệp với lợi nhuận

43.6.1 Các hiện tượng bất thường dựa trên đầu tư

Tài liệu định giá tài sản đã ghi nhận rằng các quyết định đầu tư của doanh nghiệp dự báo sự khác biệt lợi nhuận trong mặt cắt ngang (tức là các “hiện tượng bất thường về đầu tư”). Nền tảng lý thuyết là lý thuyết \(q\) của đầu tư áp dụng vào định giá tài sản (Cochrane 1991; Liu, Whited, và Zhang 2009): doanh nghiệp đầu tư nhiều hơn khi tỷ lệ chiết khấu của các dự án thấp hơn. Do đó, đầu tư cao báo hiệu lợi nhuận kỳ vọng thấp.

Hiệu ứng đầu tư. Titman, Wei, và Xie (2004) và Cooper, Gulen, và Schill (2008) ghi nhận rằng các doanh nghiệp có tăng trưởng tài sản cao đạt lợi nhuận thấp hơn sau đó. Biến tăng trưởng tài sản là:

\[ \text{AG}_{i,t} = \frac{A_{i,t} - A_{i,t-1}}{A_{i,t-1}} \tag{43.22}\]

Hiệu ứng đầu tư trên tài sản. Fama và French (2006) và Hou, Xue, và Zhang (2015) cho thấy chi tiêu vốn chia cho tài sản dự báo lợi nhuận theo chiều âm.

Hiệu ứng khả năng sinh lời. Novy-Marx (2013) cho thấy lợi nhuận gộp (doanh thu trừ giá vốn hàng bán, chia cho tài sản) dự báo lợi nhuận theo chiều dương. Điều này phù hợp với lý thuyết \(q\): khi kiểm soát đầu tư, các doanh nghiệp sinh lời hơn phải có tỷ lệ chiết khấu cao hơn (nếu không họ sẽ đầu tư nhiều hơn).

Hiện mã
# Construct anomaly variables
anomaly = panel_fc.copy().sort_values(["ticker", "year"])

# Asset growth
anomaly["asset_growth"] = (
    (anomaly["total_assets"] - anomaly["lag_assets"]) /
    anomaly["lag_assets"]
)

# Investment-to-assets
anomaly["inv_to_assets"] = anomaly["capex"] / anomaly["lag_assets"]

# Gross profitability
anomaly["gross_profit"] = (
    (anomaly["revenue"] - anomaly["cogs"]) / anomaly["total_assets"]
)

# ROE
anomaly["roe"] = anomaly["net_income"] / anomaly["book_equity"]

# Winsorize
for col in ["asset_growth", "inv_to_assets", "gross_profit", "roe"]:
    anomaly[col] = winsorize(anomaly[col])
Hiện mã
# Portfolio sorts: quintiles on asset growth
# Merge with monthly returns (using June rebalancing)
anomaly_june = anomaly.copy()
anomaly_june["formation_year"] = anomaly_june["year"]

# Create quintile assignments
anomaly_june["ag_quintile"] = anomaly_june.groupby("year")[
    "asset_growth"
].transform(lambda x: pd.qcut(x, 5, labels=[1, 2, 3, 4, 5],
                                duplicates="drop"))

# Merge with forward returns
monthly_with_signal = monthly_returns.copy()
monthly_with_signal["formation_year"] = np.where(
    monthly_with_signal["date"].dt.month >= 7,
    monthly_with_signal["date"].dt.year,
    monthly_with_signal["date"].dt.year - 1
)

portfolios = monthly_with_signal.merge(
    anomaly_june[["ticker", "formation_year", "ag_quintile",
                   "asset_growth", "gross_profit"]],
    on=["ticker", "formation_year"],
    how="inner"
)

# Compute equal-weighted quintile returns
ag_returns = (
    portfolios.groupby(["date", "ag_quintile"])
    .agg(port_ret=("ret", "mean"))
    .reset_index()
)

# Long-short: Q1 (low growth) - Q5 (high growth)
ag_wide = ag_returns.pivot(
    index="date", columns="ag_quintile", values="port_ret"
)
ag_wide["L-S"] = ag_wide[1] - ag_wide[5]
Bảng 43.16: Lợi nhuận danh mục theo nhóm ngũ phân vị tăng trưởng tài sản
Hiện mã
quintile_summary = ag_wide.describe().T[["mean", "std"]].copy()
quintile_summary["mean_ann"] = quintile_summary["mean"] * 12
quintile_summary["std_ann"] = quintile_summary["std"] * np.sqrt(12)
quintile_summary["sharpe"] = (
    quintile_summary["mean_ann"] / quintile_summary["std_ann"]
)

# t-statistics
for col in ag_wide.columns:
    t_stat = ag_wide[col].mean() / (ag_wide[col].std() / np.sqrt(len(ag_wide)))
    quintile_summary.loc[col, "t_stat"] = t_stat

quintile_summary = quintile_summary[
    ["mean_ann", "std_ann", "sharpe", "t_stat"]
].round(4)

quintile_summary.columns = [
    "Ann. Return", "Ann. Vol", "Sharpe Ratio", "t-stat"
]
quintile_summary
Hiện mã
cumret = ag_wide[["L-S"]].copy()
cumret.columns = ["Long-Short"]
cumret = cumret.dropna()
cumret["cumulative"] = (1 + cumret["Long-Short"]).cumprod()
cumret = cumret.reset_index()

(
    p9.ggplot(cumret, p9.aes(x="date", y="cumulative"))
    + p9.geom_line(color="#2E5090", size=0.8)
    + p9.geom_hline(yintercept=1, linetype="dashed", color="gray")
    + p9.labs(
        x="",
        y="Cumulative Return (Growth of $1)",
        title="Investment Anomaly: Low – High Asset Growth"
    )
    + p9.theme_minimal()
    + p9.theme(figure_size=(12, 5))
)
Hình 43.4

43.6.2 Các hiện tượng bất thường về tài trợ

Các quyết định tài trợ của doanh nghiệp cũng dự báo lợi nhuận. Pontiff và Woodgate (2008) ghi nhận rằng phát hành cổ phiếu ròng dự báo lợi nhuận theo chiều âm: các doanh nghiệp phát hành cổ phiếu đạt lợi nhuận tương lai thấp hơn, trong khi các doanh nghiệp mua lại cổ phiếu đạt lợi nhuận cao hơn. Điều này phù hợp với cả việc nhà quản lý định thời điểm thị trường lẫn một nhân tố rủi ro dựa trên phát hành.

Biến phát hành cổ phiếu ròng thường được đo như sau:

\[ \text{NSI}_{i,t} = \ln\left(\frac{\text{Split-Adjusted Shares}_{i,t}}{\text{Split-Adjusted Shares}_{i,t-1}}\right) \tag{43.23}\]

NSI dương cho biết phát hành cổ phiếu ròng; NSI âm cho biết mua lại ròng.

Hiện mã
# Net Stock Issuance
fin_anomaly = anomaly.copy()
fin_anomaly["lag_shares"] = fin_anomaly.groupby(
    "ticker"
)["shares_outstanding"].shift(1)

fin_anomaly["nsi"] = np.log(
    fin_anomaly["shares_outstanding"] / fin_anomaly["lag_shares"]
)
fin_anomaly["nsi"] = winsorize(fin_anomaly["nsi"])

# Net debt issuance (change in total debt / assets)
fin_anomaly["ndi"] = (
    (fin_anomaly["total_debt"] -
     fin_anomaly.groupby("ticker")["total_debt"].shift(1)) /
    fin_anomaly["lag_assets"]
)
fin_anomaly["ndi"] = winsorize(fin_anomaly["ndi"])

# Portfolio sorts on NSI
fin_anomaly["nsi_quintile"] = fin_anomaly.groupby("year")[
    "nsi"
].transform(lambda x: pd.qcut(x, 5, labels=[1, 2, 3, 4, 5],
                                duplicates="drop"))

port_nsi = monthly_with_signal.merge(
    fin_anomaly[["ticker", "formation_year", "nsi_quintile"]],
    on=["ticker", "formation_year"],
    how="inner"
)

nsi_returns = (
    port_nsi.groupby(["date", "nsi_quintile"])
    .agg(port_ret=("ret", "mean"))
    .reset_index()
)

nsi_wide = nsi_returns.pivot(
    index="date", columns="nsi_quintile", values="port_ret"
)
nsi_wide["L-S"] = nsi_wide[1] - nsi_wide[5]
Bảng 43.17: Lợi nhuận danh mục theo nhóm ngũ phân vị phát hành cổ phiếu ròng
Hiện mã
nsi_summary = nsi_wide.describe().T[["mean", "std"]].copy()
nsi_summary["mean_ann"] = nsi_summary["mean"] * 12
nsi_summary["sharpe"] = (
    nsi_summary["mean_ann"] /
    (nsi_summary["std"] * np.sqrt(12))
)

for col in nsi_wide.columns:
    t_stat = nsi_wide[col].mean() / (
        nsi_wide[col].std() / np.sqrt(len(nsi_wide))
    )
    nsi_summary.loc[col, "t_stat"] = t_stat

nsi_summary = nsi_summary[["mean_ann", "sharpe", "t_stat"]].round(4)
nsi_summary.columns = ["Ann. Return", "Sharpe", "t-stat"]
nsi_summary

43.6.3 Hàm ý định giá: hồi quy nhân tố Fama-French

Chúng ta đánh giá xem các hiện tượng bất thường về đầu tư và tài trợ có đại diện cho phần bù đắp rủi ro hệ thống hay không bằng cách hồi quy các danh mục mua–bán khống (long–short) theo các mô hình nhân tố chuẩn:

\[ R_{p,t} - R_{f,t} = \alpha + \beta_{\text{MKT}} \text{MKT}_t + \beta_{\text{SMB}} \text{SMB}_t + \beta_{\text{HML}} \text{HML}_t + \varepsilon_t \tag{43.24}\]

\(\alpha\) dương có ý nghĩa sau khi kiểm soát các nhân tố rủi ro đã biết sẽ cho thấy hiện tượng bất thường không được giải thích bởi mức phơi nhiễm quy mô và giá trị.

Hiện mã
# Merge long-short returns with factor data
factor_data = factors.set_index("date")

# Asset growth anomaly alpha
ag_ls = ag_wide[["L-S"]].dropna().rename(columns={"L-S": "excess_ret"})
ag_merged = ag_ls.join(factor_data[["mkt_rf", "smb", "hml"]], how="inner")

model_ag_ff3 = sm.OLS(
    ag_merged["excess_ret"],
    sm.add_constant(ag_merged[["mkt_rf", "smb", "hml"]])
).fit(cov_type="HAC", cov_kwds={"maxlags": 6})

# NSI anomaly alpha
nsi_ls = nsi_wide[["L-S"]].dropna().rename(columns={"L-S": "excess_ret"})
nsi_merged = nsi_ls.join(factor_data[["mkt_rf", "smb", "hml"]], how="inner")

model_nsi_ff3 = sm.OLS(
    nsi_merged["excess_ret"],
    sm.add_constant(nsi_merged[["mkt_rf", "smb", "hml"]])
).fit(cov_type="HAC", cov_kwds={"maxlags": 6})
Bảng 43.18: Alpha ba nhân tố Fama-French cho các hiện tượng bất thường về quyết định doanh nghiệp
Hiện mã
alpha_table = pd.DataFrame({
    "Asset Growth L-S": {
        "Alpha (monthly)": f"{model_ag_ff3.params['const']:.4f}",
        "  t-stat": f"{model_ag_ff3.tvalues['const']:.3f}",
        "MKT": f"{model_ag_ff3.params['mkt_rf']:.4f}",
        "SMB": f"{model_ag_ff3.params['smb']:.4f}",
        "HML": f"{model_ag_ff3.params['hml']:.4f}",
        "R²": f"{model_ag_ff3.rsquared:.4f}"
    },
    "Net Issuance L-S": {
        "Alpha (monthly)": f"{model_nsi_ff3.params['const']:.4f}",
        "  t-stat": f"{model_nsi_ff3.tvalues['const']:.3f}",
        "MKT": f"{model_nsi_ff3.params['mkt_rf']:.4f}",
        "SMB": f"{model_nsi_ff3.params['smb']:.4f}",
        "HML": f"{model_nsi_ff3.params['hml']:.4f}",
        "R²": f"{model_nsi_ff3.rsquared:.4f}"
    }
})
alpha_table
Hiện mã
# Combine asset growth and NSI long-short for comparison
combined = pd.DataFrame({
    "Asset Growth": ag_wide["L-S"],
    "Net Issuance": nsi_wide["L-S"]
}).dropna()

combined_cum = (1 + combined).cumprod().reset_index()
combined_long = combined_cum.melt(
    id_vars="date",
    var_name="Anomaly",
    value_name="Cumulative Return"
)

(
    p9.ggplot(combined_long, p9.aes(
        x="date", y="Cumulative Return", color="Anomaly"
    ))
    + p9.geom_line(size=0.8)
    + p9.geom_hline(yintercept=1, linetype="dashed", color="gray")
    + p9.scale_color_manual(values=["#2E5090", "#C0392B"])
    + p9.labs(
        x="",
        y="Cumulative Return (Growth of $1)",
        title="Investment vs. Financing Anomalies: Long-Short Portfolios"
    )
    + p9.theme_minimal()
    + p9.theme(figure_size=(12, 5), legend_position="top")
)
Hình 43.5

43.7 Tóm tắt

Chương này đã cài đặt bộ công cụ kinh tế lượng cốt lõi của tài chính doanh nghiệp thực nghiệm cho các doanh nghiệp niêm yết Việt Nam. Các công cụ ước lượng trải trên bốn lĩnh vực liên kết với nhau: quyết định đầu tư (hồi quy đầu tư-\(Q\) và các biến thể đã hiệu chỉnh sai số đo lường), quyết định tài trợ (các yếu tố quyết định cấu trúc vốn, kiểm định trật tự phân hạng và các thước đo định thời điểm thị trường), chính sách chi trả (làm mượt Lintner, mô hình mua lại cổ phiếu và kiểm định tín hiệu cổ tức), và chi phí đại diện (quan hệ sở hữu-giá trị, các thước đo dòng tiền tự do và các biến quản trị).

Một số phát hiện đáng nhấn mạnh. Mối quan hệ đầu tư-\(Q\) ở Việt Nam bị suy giảm so với các chuẩn mực của thị trường phát triển, phản ánh cả mức độ nghiêm trọng của sai số đo lường trong \(Q\) (giao dịch mỏng, biên độ giá, lạm phát biến động) lẫn sự phổ biến của đầu tư không theo thị trường của các SOE. Dòng tiền vẫn là một biến dự báo đầu tư có ý nghĩa qua các phân loại ràng buộc, mặc dù tranh luận FHP-KZ về cách diễn giải vẫn áp dụng đầy đủ. Cấu trúc vốn được dự báo mạnh bởi khả năng sinh lời (theo chiều âm, phù hợp với trật tự phân hạng) và tính hữu hình (theo chiều dương, phù hợp với lý thuyết đánh đổi). Việc làm mượt cổ tức rất rõ rệt, nhưng tham số làm mượt khác nhau một cách hệ thống giữa SOE và doanh nghiệp tư nhân, phản ánh các lực lượng thể chế riêng chi phối chính sách chi trả của từng nhóm.

Chương này cũng liên kết các quyết định doanh nghiệp với lợi nhuận tài sản thông qua việc phân loại danh mục theo tăng trưởng tài sản và phát hành cổ phiếu ròng. Liệu các hiện tượng bất thường này có tồn tại sau khi điều chỉnh rủi ro và duy trì ngoài mẫu tại thị trường Việt Nam hay không là một câu hỏi mở quan trọng cho nghiên cứu tương lai.