5  Xây dựng lãi suất phi rủi ro tại Việt Nam

Ghi chú

Trong chương này, chúng ta giải quyết một vấn đề tuy đơn giản nhưng có hệ quả lớn: làm thế nào để xây dựng chuỗi lãi suất phi rủi ro cho các nghiên cứu tài chính thực nghiệm tại Việt Nam. Chúng ta đánh giá các biến đại diện sẵn có, như lợi suất trái phiếu chính phủ, lãi suất liên ngân hàng qua đêm và các mức lãi suất điều hành của Ngân hàng Nhà nước Việt Nam (NHNN), xây dựng các quy trình nội suy và căn chỉnh tần suất, đồng thời lượng hóa mức độ nhạy của các kết quả định giá tài sản chủ chốt đối với việc lựa chọn biến đại diện cho lãi suất phi rủi ro.

Lãi suất phi rủi ro là con số đơn lẻ quan trọng nhất trong tài chính. Nó là điểm neo cho lợi nhuận vượt mức, tỷ lệ chiết khấu, phần bù nhân tố, chi phí vốn chủ sở hữu, đánh giá hiệu quả đầu tư và định giá phái sinh. Dù giữ vai trò nền tảng, lãi suất phi rủi ro thường bị coi là một dữ liệu cho sẵn: một con số tải từ cơ sở dữ liệu rồi đưa vào các công thức mà không suy xét thêm. Ở các thị trường phát triển, nơi thị trường chứng khoán chính phủ sâu và thanh khoản cao, cách làm tùy tiện này thường không gây hại. Ở Việt Nam thì không như vậy.

Thị trường thu nhập cố định của Việt Nam mỏng, phân mảnh, và có đặc điểm là việc phát hành chứng khoán chính phủ ngắn hạn diễn ra không đều đặn. Không có một mức lãi suất phi rủi ro duy nhất được chấp nhận rộng rãi, tương tự lãi suất tín phiếu kho bạc kỳ hạn 1 tháng vốn là điểm neo của hầu như mọi nghiên cứu định giá tài sản ở các thị trường trưởng thành. Thay vào đó, các nhà nghiên cứu phải lựa chọn giữa những biến đại diện không hoàn hảo, mỗi biến có ưu điểm và hạn chế riêng. Lựa chọn này không phải vô hại: các biến đại diện khác nhau có thể tạo ra lợi nhuận vượt mức, phần bù nhân tố và ước lượng định giá khác biệt đáng kể.

Chương này xây dựng một cách tiếp cận có hệ thống để xây dựng lãi suất phi rủi ro. Chúng ta bắt đầu với các yêu cầu lý thuyết đối với một tài sản phi rủi ro, sau đó đánh giá các biến đại diện sẵn có của Việt Nam theo những yêu cầu này. Chúng ta xây dựng các chuỗi lãi suất phi rủi ro theo tháng với nhiều cách xác định khác nhau, trình bày các kỹ thuật căn chỉnh tần suất và nội suy, rồi tiến hành phân tích độ nhạy để lượng hóa việc lựa chọn biến đại diện ảnh hưởng thế nào đến các kết quả phía sau.

5.1 Vai trò của lãi suất phi rủi ro trong tài chính

5.1.1 Lợi nhuận vượt mức

Công dụng cơ bản nhất của lãi suất phi rủi ro là tính lợi nhuận vượt mức. Lợi nhuận vượt mức của tài sản \(i\) trong kỳ \(t\) là:

\[ r_{i,t}^{e} = r_{i,t} - r_{f,t} \tag{5.1}\]

trong đó \(r_{i,t}\) là lợi nhuận thô và \(r_{f,t}\) là lãi suất phi rủi ro trong cùng kỳ, cùng đơn vị tiền tệ và cùng quy ước ghép lãi. Lợi nhuận vượt mức tách riêng phần bù đắp cho việc chịu rủi ro, loại bỏ phần lợi nhuận có thể kiếm được mà không phải chịu rủi ro.

Việc đo lường sai \(r_{f,t}\) làm nhiễm trực tiếp mọi quan sát lợi nhuận vượt mức và, suy rộng ra, mọi đại lượng được tính từ lợi nhuận vượt mức. Nếu \(r_{f,t}\) bị chệch lên một cách có hệ thống, lợi nhuận vượt mức sẽ bị đánh giá thấp một cách có hệ thống, phần bù nhân tố bị nén lại, và chi phí vốn chủ sở hữu bị đánh giá quá cao.

5.1.2 Phần bù nhân tố

Trong mô hình ba nhân tố của Fama và French (1993), phần bù rủi ro thị trường là:

\[ \text{MKTRF}_t = r_{m,t} - r_{f,t} \tag{5.2}\]

trong đó \(r_{m,t}\) là lợi nhuận thị trường theo trọng số vốn hóa. Các phần bù quy mô (SMB) và giá trị (HML) được định nghĩa là lợi nhuận của các danh mục mua–bán khống và không phụ thuộc trực tiếp vào \(r_{f,t}\). Tuy nhiên, hệ số chặn (alpha) từ hồi quy chuỗi thời gian của lợi nhuận vượt mức của bất kỳ danh mục nào theo các nhân tố lại phụ thuộc vào \(r_{f,t}\) thông qua biến phụ thuộc. Một lãi suất phi rủi ro bị chệch sẽ làm dịch chuyển mọi alpha một cách đồng đều.

5.1.3 Tỷ lệ chiết khấu và định giá

Mô hình chiết khấu dòng tiền định giá một doanh nghiệp như sau:

\[ V_0 = \sum_{t=1}^{\infty} \frac{E[CF_t]}{(1 + r_{WACC})^t} \tag{5.3}\]

trong đó chi phí vốn bình quân gia quyền (WACC) phụ thuộc vào chi phí vốn chủ sở hữu, và chi phí này lại phụ thuộc vào lãi suất phi rủi ro thông qua mô hình định giá tài sản vốn (CAPM):

\[ r_{e} = r_f + \beta_i (\bar{r}_m - r_f) \tag{5.4}\]

Sai số 100 điểm cơ bản trong \(r_f\) lan truyền sang chi phí vốn chủ sở hữu và có thể làm thay đổi hiện giá của một chuỗi dòng tiền có duration dài từ 10-20%, tùy theo cấu trúc duration của dòng tiền.

5.1.4 Đánh giá hiệu quả đầu tư

Các thước đo hiệu quả điều chỉnh theo rủi ro như tỷ số Sharpe:

\[ \text{SR} = \frac{\bar{r}_p - \bar{r}_f}{\sigma(r_p - r_f)} \tag{5.5}\]

và alpha của Jensen:

\[ \alpha = \bar{r}_p - r_f - \hat{\beta}_p (\bar{r}_m - r_f) \tag{5.6}\]

đều phụ thuộc trực tiếp vào \(r_f\). Tỷ số Sharpe đặc biệt nhạy vì mẫu số (độ biến động của lợi nhuận vượt mức) cũng chịu ảnh hưởng bởi mức và sự biến thiên của \(r_f\).

5.2 “Phi rủi ro” có nghĩa là gì trong thực tế?

Một tài sản phi rủi ro thực sự phải đồng thời thỏa mãn bốn điều kiện (Bảng 5.1).

Bảng 5.1: Các yêu cầu đối với một tài sản phi rủi ro
Điều kiện Định nghĩa Thách thức thực tế
Không có rủi ro vỡ nợ Tổ chức phát hành không thể không thanh toán Chỉ nợ chính phủ bằng đồng nội tệ mới đủ điều kiện
Dòng tiền đã biết Khoản thanh toán chắc chắn ngay từ đầu Loại trừ các công cụ có lãi suất thả nổi
Không có rủi ro tái đầu tư Kỳ hạn khớp với kỳ đầu tư Đòi hỏi chứng khoán zero-coupon (không trả lãi định kỳ) có kỳ hạn chính xác
Thanh khoản cao Có thể giao dịch với chi phí thấp Thị trường trái phiếu chính phủ mỏng không đạt yêu cầu này

Không có tài sản nào trong thực tế thỏa mãn hoàn hảo cả bốn điều kiện. Ngay cả ở những thị trường trái phiếu chính phủ sâu nhất, vẫn có phần bù thanh khoản ở các chứng khoán đã phát hành trước đó (off-the-run) và lợi suất tiện ích ở các đợt phát hành mới (on-the-run) (Krishnamurthy và Vissing-Jorgensen 2012). Câu hỏi thực tiễn là: công cụ sẵn có nào gần nhất với lý tưởng?

5.2.1 Biến đại diện lý tưởng

Biến đại diện lý tưởng cho lãi suất phi rủi ro trong nghiên cứu định giá tài sản thực nghiệm có các đặc tính sau:

  1. Kỳ hạn ngắn: Giảm thiểu rủi ro tái đầu tư và việc bị lẫn phần bù kỳ hạn. Lựa chọn thông thường là kỳ hạn 1 tháng.
  2. Do chính phủ phát hành hoặc bảo đảm: Loại bỏ rủi ro tín dụng (đối với đồng nội tệ).
  3. Được giao dịch tích cực: Bảo đảm lợi suất quan sát được phản ánh điều kiện thị trường hiện tại.
  4. Phát hành đều đặn: Cung cấp chuỗi thời gian liên tục, không có khoảng trống.
  5. Phương pháp nhất quán: Cách tính lợi suất rõ ràng và có thể so sánh theo thời gian.

5.3 Các biến đại diện sẵn có tại Việt Nam

Hạ tầng tài chính của Việt Nam cung cấp một số công cụ ứng viên, không công cụ nào thỏa mãn hoàn hảo mọi tiêu chí. Chúng ta lần lượt đánh giá từng công cụ.

5.3.1 Lợi suất trái phiếu chính phủ

Chính phủ Việt Nam phát hành trái phiếu với nhiều kỳ hạn thông qua Kho bạc Nhà nước và thị trường trái phiếu Việt Nam (VBM). Các đặc điểm chính:

Bảng 5.2: Đặc điểm của trái phiếu chính phủ Việt Nam
Đặc điểm Mô tả
Tổ chức phát hành Kho bạc Nhà nước Việt Nam
Thị trường sơ cấp Đấu thầu qua HNX
Các kỳ hạn sẵn có 1, 2, 3, 5, 7, 10, 15, 20, 30 năm
Chuẩn ngắn nhất 1 năm (đôi khi có kỳ hạn ngắn hơn qua tín phiếu)
Cơ cấu lãi coupon Cố định, trả nửa năm một lần
Tần suất phát hành Đấu thầu đều đặn hằng tuần/hai tuần một lần
Thanh khoản thị trường thứ cấp Tập trung ở nhóm kỳ hạn 3-5 năm; đầu ngắn hạn mỏng
Khả năng tiếp cận dữ liệu Có sẵn qua DataCore.vn

Hạn chế chính của lợi suất trái phiếu chính phủ khi làm biến đại diện cho lãi suất phi rủi ro là sự khan hiếm các chứng khoán có kỳ hạn ngắn. Trái phiếu kỳ hạn một năm là chuẩn ngắn nhất được phát hành đều đặn, và lợi suất của chúng bao gồm một phần bù kỳ hạn mà lãi suất phi rủi ro thực sự không có. Tín phiếu kho bạc (kỳ hạn < 1 năm) được phát hành không đều và với khối lượng nhỏ, khiến chúng không phù hợp làm một chuỗi liên tục.

5.3.2 Lãi suất liên ngân hàng qua đêm

Thị trường liên ngân hàng Việt Nam hình thành lãi suất cho vay qua đêm giữa các ngân hàng thương mại. Lãi suất qua đêm được NHNN công bố.

Ưu điểm: Kỳ hạn rất ngắn (qua đêm), tần suất cao (hằng ngày), phản ánh chi phí đi vay thực tế trong hệ thống tài chính.

Hạn chế: Phản ánh rủi ro tín dụng của khu vực ngân hàng (rủi ro vỡ nợ liên ngân hàng, dù nhỏ), có thể biến động mạnh khi thanh khoản bị thắt chặt, và không tương ứng với một công cụ zero-coupon (không trả lãi định kỳ) có thể giao dịch được.

5.3.3 Lãi suất điều hành của NHNN

Ngân hàng Nhà nước Việt Nam ấn định một số mức lãi suất điều hành (Bảng 5.3).

Bảng 5.3: Các mức lãi suất điều hành của NHNN
Lãi suất Vai trò Tần suất thay đổi
Lãi suất tái cấp vốn Mức lãi suất NHNN cho các ngân hàng vay Hiếm khi (theo các cuộc họp chính sách)
Lãi suất tái chiết khấu Lãi suất tái chiết khấu giấy tờ có giá đủ điều kiện Hiếm khi
Lãi suất cho vay qua đêm Mức trần của lãi suất liên ngân hàng qua đêm Hiếm khi
Trần lãi suất tiền gửi Mức lãi suất tối đa các ngân hàng được trả cho tiền gửi Hiếm khi

Ưu điểm: Ổn định (ít thay đổi), phản ánh lập trường chính sách tiền tệ, có sẵn cho toàn bộ giai đoạn mẫu.

Hạn chế: Không phải là lợi nhuận có thể giao dịch (tức là không nhà đầu tư nào thực sự kiếm được lãi suất điều hành). Đây là một mục tiêu hành chính, không phải mức giá cân bằng của thị trường. Phản ứng có độ trễ với các điều kiện kinh tế vĩ mô.

5.3.4 Lãi suất tiền gửi tiết kiệm

Các ngân hàng thương mại cung cấp tiền gửi có kỳ hạn với mức lãi suất chịu giới hạn trần của NHNN. Lãi suất tiền gửi ngắn hạn (1 tháng hoặc 3 tháng) đôi khi được dùng như biến đại diện phi chính thức cho lãi suất phi rủi ro trong bối cảnh thực hành.

Ưu điểm: Là khoản lợi nhuận có thể đầu tư được đối với nhà đầu tư nhỏ, phổ biến rộng rãi.

Hạn chế: Chịu rủi ro tín dụng của ngân hàng, khác nhau giữa các ngân hàng, mức trần tạo ra một giới hạn trên có thể không phản ánh lãi suất cân bằng thực sự, không được chuẩn hóa cho mục đích nghiên cứu.

5.3.5 So sánh tổng hợp

Bảng 5.4: So sánh các biến đại diện cho lãi suất phi rủi ro tại Việt Nam
Biến đại diện Rủi ro vỡ nợ Khớp kỳ hạn Tính liên tục Thanh khoản Mục đích sử dụng khuyến nghị
Trái phiếu chính phủ 1 năm Tối thiểu (chính phủ) Kém (1 năm so với 1 tháng) Tốt Trung bình Phân tích theo năm/quý
Tín phiếu kho bạc (< 1 năm) Tối thiểu (chính phủ) Tốt (khi có sẵn) Kém (phát hành không đều) Thấp Ưu tiên khi có sẵn
Lãi suất liên ngân hàng qua đêm Thấp (liên ngân hàng) Rất ngắn (qua đêm) Xuất sắc Cao (liên ngân hàng) Phân tích theo ngày/tháng
Lãi suất tái cấp vốn của NHNN Không có (lãi suất điều hành) Không áp dụng (không giao dịch) Xuất sắc Không áp dụng Chỉ dùng cho so sánh dài hạn
Lãi suất tiền gửi ngân hàng 1 tháng Thấp đến trung bình (ngân hàng) Tốt (1 tháng) Tốt Không áp dụng DCF trong thực hành

5.4 Xây dựng chuỗi lãi suất phi rủi ro

Bây giờ chúng ta xây dựng các chuỗi lãi suất phi rủi ro theo tháng thay thế và khảo sát các đặc tính của chúng.

5.4.1 Tải và làm sạch dữ liệu lãi suất

Hiện mã
import pandas as pd
import numpy as np

# Assume rf_data contains: date, rate_type, rate_annual (annualized, in %)
rf_raw = pd.read_parquet("data/risk_free_rates.parquet")

# Preview available rate types
print("Available rate types:")
print(rf_raw["rate_type"].value_counts())
Hiện mã
import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(8, 4.5))

colors = {
    "govt_bond_1y": "#2C73D2",
    "interbank_overnight": "#FF6B6B",
    "sbv_refinancing": "#5DCEAF",
    "tbill_3m": "#FFB347",
    "deposit_1m": "#B19CD9"
}

for rate_type, color in colors.items():
    subset = rf_raw[rf_raw["rate_type"] == rate_type].sort_values("date")
    if len(subset) > 0:
        ax.plot(
            subset["date"], subset["rate_annual"],
            label=rate_type.replace("_", " ").title(),
            color=color, linewidth=1.2, alpha=0.85
        )

ax.set_ylabel("Annualized Rate (%)")
ax.set_xlabel("")
ax.legend(frameon=False, fontsize=9, loc="upper right")
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
plt.tight_layout()
plt.show()
Hình 5.1

5.4.2 Căn chỉnh tần suất

Các kiểm định định giá tài sản đòi hỏi lãi suất phi rủi ro theo tháng. Dữ liệu thô có thể đến theo tần suất hằng ngày, hằng tuần hoặc không đều. Chúng ta dùng logic chuyển đổi sau:

Từ ngày sang tháng: Lấy trung bình các mức lãi suất hằng ngày trong mỗi tháng, sau đó chuyển từ lãi suất quy năm sang lãi suất tháng.

Từ không đều sang tháng: Với các chuỗi có khoảng trống (ví dụ tín phiếu kho bạc), điền tiếp (forward-fill) quan sát gần nhất, sau đó lấy trung bình trong mỗi tháng.

Từ quy năm sang tháng: Với lãi đơn, \(r_f^{monthly} = r_f^{annual} / 12\). Với lãi ghép liên tục, \(r_f^{monthly} = r_f^{annual} / 12\) (vì lãi suất liên tục có tính cộng). Chúng ta dùng lãi đơn để nhất quán với quy ước rằng lợi nhuận cổ phiếu được tính dưới dạng lợi nhuận số học.

Hiện mã
# Construct monthly risk-free rates from each proxy

def construct_monthly_rf(rf_raw, rate_type, method="mean"):
    """
    Convert raw rate data to monthly frequency.

    Parameters
    ----------
    rf_raw : pd.DataFrame
        Raw rate data with columns: date, rate_type, rate_annual
    rate_type : str
        Which rate proxy to use
    method : str
        Aggregation method: 'mean', 'last', or 'first'

    Returns
    -------
    pd.DataFrame
        Monthly risk-free rate with columns: date, rf_monthly
    """
    subset = (
        rf_raw[rf_raw["rate_type"] == rate_type]
        .sort_values("date")
        .set_index("date")
    )

    # Forward-fill gaps (for irregular series)
    subset = subset.resample("D").ffill()

    # Aggregate to monthly
    if method == "mean":
        monthly = subset.resample("ME")["rate_annual"].mean()
    elif method == "last":
        monthly = subset.resample("ME")["rate_annual"].last()
    else:
        monthly = subset.resample("ME")["rate_annual"].first()

    monthly = monthly.reset_index()
    monthly.columns = ["date", "rf_annual"]

    # Convert annualized rate (%) to monthly decimal
    monthly["rf_monthly"] = monthly["rf_annual"] / 100 / 12

    return monthly[["date", "rf_monthly", "rf_annual"]]

# Construct series for each proxy
rf_proxies = {}
for proxy in ["govt_bond_1y", "interbank_overnight", "sbv_refinancing"]:
    rf_proxies[proxy] = construct_monthly_rf(rf_raw, proxy)
    rf_proxies[proxy]["proxy"] = proxy

rf_all = pd.concat(rf_proxies.values(), ignore_index=True)

5.4.3 Xử lý dữ liệu thiếu và các điểm gãy cấu trúc

Dữ liệu lãi suất của Việt Nam có thể có khoảng trống do thị trường đóng cửa, thay đổi cách báo cáo, hoặc việc đưa ra các công cụ mới. Chúng ta xử lý các trường hợp này một cách có hệ thống:

Hiện mã
# Check coverage for each proxy
coverage = (
    rf_all
    .groupby("proxy")
    .agg(
        start_date=("date", "min"),
        end_date=("date", "max"),
        n_months=("rf_monthly", "count"),
        n_missing=("rf_monthly", lambda x: x.isna().sum()),
        avg_rate_pct=("rf_annual", "mean")
    )
    .round(2)
)

print(coverage)

Với các giai đoạn mà biến đại diện chính không có sẵn, chúng ta xây dựng một chuỗi kết hợp theo thứ tự ưu tiên:

Hiện mã
def construct_blended_rf(rf_proxies, priority=None):
    """
    Construct a blended monthly risk-free rate using proxy priority.

    Priority order (default):
    1. Treasury bills (shortest maturity, sovereign)
    2. Interbank overnight (short maturity, high frequency)
    3. 1-year government bond (sovereign, regular)
    4. SBV refinancing rate (fallback)
    """
    if priority is None:
        priority = [
            "tbill_3m",
            "interbank_overnight",
            "govt_bond_1y",
            "sbv_refinancing"
        ]

    # Create full date range
    all_dates = pd.date_range(
        start=min(df["date"].min() for df in rf_proxies.values()),
        end=max(df["date"].max() for df in rf_proxies.values()),
        freq="ME"
    )

    blended = pd.DataFrame({"date": all_dates})
    blended["rf_monthly"] = np.nan
    blended["source"] = ""

    for proxy in priority:
        if proxy in rf_proxies:
            proxy_df = rf_proxies[proxy][["date", "rf_monthly"]].rename(
                columns={"rf_monthly": f"rf_{proxy}"}
            )
            blended = blended.merge(proxy_df, on="date", how="left")

            # Fill missing values from this proxy
            mask = blended["rf_monthly"].isna() & blended[f"rf_{proxy}"].notna()
            blended.loc[mask, "rf_monthly"] = blended.loc[mask, f"rf_{proxy}"]
            blended.loc[mask, "source"] = proxy

            blended = blended.drop(columns=[f"rf_{proxy}"])

    return blended

rf_blended = construct_blended_rf(rf_proxies)
Bảng 5.5: Cơ cấu nguồn dữ liệu của chuỗi lãi suất phi rủi ro kết hợp
Hiện mã
source_comp = (
    rf_blended
    .groupby("source")
    .agg(
        n_months=("date", "count"),
        pct=("date", lambda x: len(x) / len(rf_blended) * 100)
    )
    .round(1)
    .sort_values("n_months", ascending=False)
)

source_comp

5.4.4 Các đặc tính của chuỗi đã xây dựng

Bảng 5.6: Thống kê mô tả của các biến đại diện cho lãi suất phi rủi ro theo tháng
Hiện mã
rf_wide = rf_all.pivot_table(
    index="date", columns="proxy", values="rf_monthly"
)

summary = rf_wide.describe(percentiles=[0.10, 0.25, 0.50, 0.75, 0.90]).T
summary = summary[["mean", "std", "min", "10%", "50%", "90%", "max"]]
summary.columns = [
    "Mean", "Std", "Min", "P10", "Median", "P90", "Max"
]

# Convert to annualized percentage for interpretability
(summary * 12 * 100).round(2)
Hiện mã
fig, axes = plt.subplots(2, 1, figsize=(8, 6), sharex=True)

# Level
for proxy, color in [
    ("govt_bond_1y", "#2C73D2"),
    ("interbank_overnight", "#FF6B6B"),
    ("sbv_refinancing", "#5DCEAF")
]:
    subset = rf_proxies[proxy].sort_values("date")
    axes[0].plot(
        subset["date"], subset["rf_monthly"] * 100,
        label=proxy.replace("_", " ").title(),
        color=color, linewidth=1
    )
axes[0].set_ylabel("Monthly Rate (%)")
axes[0].legend(frameon=False, fontsize=9)
axes[0].spines["top"].set_visible(False)
axes[0].spines["right"].set_visible(False)

# Pairwise spread: govt bond - interbank
merged = rf_proxies["govt_bond_1y"][["date", "rf_monthly"]].merge(
    rf_proxies["interbank_overnight"][["date", "rf_monthly"]],
    on="date", suffixes=("_bond", "_interbank")
)
merged["spread"] = (merged["rf_monthly_bond"] - merged["rf_monthly_interbank"]) * 100

axes[1].fill_between(
    merged["date"], merged["spread"], 0,
    where=merged["spread"] > 0, alpha=0.4, color="#2C73D2", label="Bond > Interbank"
)
axes[1].fill_between(
    merged["date"], merged["spread"], 0,
    where=merged["spread"] <= 0, alpha=0.4, color="#FF6B6B", label="Bond < Interbank"
)
axes[1].axhline(0, color="black", linewidth=0.5)
axes[1].set_ylabel("Spread (% monthly)")
axes[1].set_xlabel("")
axes[1].legend(frameon=False, fontsize=9)
axes[1].spines["top"].set_visible(False)
axes[1].spines["right"].set_visible(False)

plt.tight_layout()
plt.show()
Hình 5.2

Chênh lệch giữa các biến đại diện mang nhiều thông tin. Chênh lệch dương liên tục (lợi suất trái phiếu > lãi suất liên ngân hàng) phản ánh phần bù kỳ hạn nằm trong trái phiếu 1 năm. Các giai đoạn lãi suất liên ngân hàng vọt lên trên lợi suất trái phiếu thường tương ứng với tình trạng thắt chặt thanh khoản trong hệ thống ngân hàng.

5.4.5 Tương quan giữa các biến đại diện

Bảng 5.7: Tương quan cặp của các biến đại diện cho lãi suất phi rủi ro theo tháng
Hiện mã
rf_corr = rf_wide.corr().round(3)
rf_corr.index = [x.replace("_", " ").title() for x in rf_corr.index]
rf_corr.columns = [x.replace("_", " ").title() for x in rf_corr.columns]
rf_corr

Tương quan cao (> 0.8) giữa các biến đại diện cho thấy mức độ và chiều hướng biến động của lãi suất được tất cả các biến đại diện nắm bắt tương tự nhau. Tương quan thấp sẽ cho thấy việc lựa chọn biến đại diện đưa vào lợi nhuận vượt mức một lượng biến thiên riêng biệt đáng kể.

5.5 Xây dựng lợi nhuận vượt mức

Với chuỗi lãi suất phi rủi ro trong tay, bây giờ chúng ta xây dựng lợi nhuận vượt mức cho từng cổ phiếu và cho danh mục thị trường.

5.5.1 Khớp các quy ước

Việc xây dựng lợi nhuận vượt mức đòi hỏi sự nhất quán nghiêm ngặt theo ba chiều (Bảng 5.8).

Bảng 5.8: Các yêu cầu nhất quán đối với lợi nhuận vượt mức
Chiều Yêu cầu Lỗi thường gặp
Tiền tệ Cùng đơn vị tiền tệ cho \(r_i\) và \(r_f\) Dùng lãi suất USD cho lợi nhuận tính bằng VND
Tần suất Cùng kỳ nắm giữ Dùng \(r_f\) quy năm với \(r_i\) theo tháng
Ghép lãi Cùng quy ước Trộn lẫn lợi nhuận logarit và lợi nhuận số học
Hiện mã
# Load monthly stock returns
stock_returns = pd.read_parquet("data/monthly_returns.parquet")
# Assume columns: symbol, date (month-end), ret

# Merge with risk-free rate
# Use the blended series as the baseline
rf_for_merge = rf_blended[["date", "rf_monthly"]].rename(
    columns={"rf_monthly": "rf"}
)

stock_returns = stock_returns.merge(rf_for_merge, on="date", how="left")

# Compute excess returns
stock_returns["ret_excess"] = stock_returns["ret"] - stock_returns["rf"]

5.5.2 Lợi nhuận vượt mức của thị trường

Hiện mã
# Value-weighted market return
market_monthly = (
    stock_returns
    .groupby("date")
    .apply(
        lambda g: np.average(
            g["ret"].dropna(),
            weights=g["mktcap"].loc[g["ret"].dropna().index]
        ) if g["ret"].dropna().shape[0] > 0 else np.nan,
        include_groups=False
    )
    .reset_index(name="rm")
)

market_monthly = market_monthly.merge(rf_for_merge, on="date", how="left")
market_monthly["mktrf"] = market_monthly["rm"] - market_monthly["rf"]
Hiện mã
fig, ax = plt.subplots(figsize=(8, 3.5))

ax.bar(
    market_monthly["date"], market_monthly["mktrf"] * 100,
    color=np.where(market_monthly["mktrf"] >= 0, "#2C73D2", "#FF6B6B"),
    width=25, alpha=0.8
)
ax.axhline(0, color="black", linewidth=0.5)
ax.set_ylabel("Market Excess Return (%)")
ax.set_xlabel("")
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
plt.tight_layout()
plt.show()
Hình 5.3

5.6 Phân tích độ nhạy: việc chọn biến đại diện quan trọng đến mức nào?

Đây là câu hỏi thực nghiệm trọng tâm của chương. Nếu các biến đại diện khác nhau cho lãi suất phi rủi ro tạo ra các kết quả phía sau về cơ bản giống nhau, thì lựa chọn đó không có hệ quả. Nếu chúng tạo ra các kết quả khác nhau, nhà nghiên cứu phải biện minh cho lựa chọn của mình và báo cáo độ vững.

5.6.1 Tác động lên phần bù cổ phiếu

Bảng 5.9: Phần bù cổ phiếu quy năm theo các biến đại diện thay thế cho lãi suất phi rủi ro
Hiện mã
results = []
for proxy_name, proxy_df in rf_proxies.items():
    rf_merge = proxy_df[["date", "rf_monthly"]].rename(
        columns={"rf_monthly": "rf_proxy"}
    )
    merged = market_monthly[["date", "rm"]].merge(rf_merge, on="date", how="inner")
    merged["mktrf_proxy"] = merged["rm"] - merged["rf_proxy"]

    n_months = merged["mktrf_proxy"].count()
    mean_monthly = merged["mktrf_proxy"].mean()
    std_monthly = merged["mktrf_proxy"].std()
    sharpe = mean_monthly / std_monthly if std_monthly > 0 else np.nan
    t_stat = mean_monthly / (std_monthly / np.sqrt(n_months))

    results.append({
        "Proxy": proxy_name.replace("_", " ").title(),
        "N Months": n_months,
        "Mean (% ann.)": round(mean_monthly * 12 * 100, 2),
        "Std (% ann.)": round(std_monthly * np.sqrt(12) * 100, 2),
        "Sharpe (ann.)": round(sharpe * np.sqrt(12), 3),
        "t-stat": round(t_stat, 2)
    })

pd.DataFrame(results).style.hide(axis="index")

5.6.2 Tác động lên phần bù nhân tố

Bảng 5.10: Độ nhạy của phần bù nhân tố đối với biến đại diện cho lãi suất phi rủi ro (quy năm, %)
Hiện mã
# Load or construct factor returns
# Assume factors_monthly has: date, smb, hml (these are long-short, rf-independent)
# Only MKTRF changes with the proxy

factors_monthly = pd.read_parquet("data/factors_monthly.parquet")

for proxy_name, proxy_df in rf_proxies.items():
    rf_merge = proxy_df[["date", "rf_monthly"]].rename(
        columns={"rf_monthly": "rf_proxy"}
    )
    factors_merged = factors_monthly.merge(rf_merge, on="date", how="inner")
    factors_merged = factors_merged.merge(
        market_monthly[["date", "rm"]], on="date", how="inner"
    )
    factors_merged[f"mktrf_{proxy_name}"] = (
        factors_merged["rm"] - factors_merged["rf_proxy"]
    )

    mean_mktrf = factors_merged[f"mktrf_{proxy_name}"].mean() * 12 * 100
    mean_smb = factors_merged["smb"].mean() * 12 * 100
    mean_hml = factors_merged["hml"].mean() * 12 * 100

    print(
        f"{proxy_name:>25s}: MKTRF = {mean_mktrf:6.2f}%, "
        f"SMB = {mean_smb:6.2f}%, HML = {mean_hml:6.2f}%"
    )

Lưu ý rằng SMB và HML được xây dựng như lợi nhuận của danh mục mua–bán khống và phải giống hệt nhau bất kể biến đại diện cho lãi suất phi rủi ro. Chỉ có MKTRF khác nhau. Tuy nhiên, nếu nhà nghiên cứu dùng lãi suất phi rủi ro để tính lợi nhuận vượt mức của từng cổ phiếu trước khi phân loại vào các danh mục nhân tố, có thể xuất hiện những khác biệt nhỏ trong việc phân loại.

5.6.3 Tác động lên các ước lượng alpha

Việc chọn biến đại diện cho lãi suất phi rủi ro ảnh hưởng đến ước lượng alpha của bất kỳ danh mục nào được đánh giá theo một mô hình nhân tố. Chúng ta minh họa điều này bằng cách ước lượng alpha của một danh mục động lượng theo từng biến đại diện.

Bảng 5.11: Độ nhạy của alpha danh mục động lượng đối với biến đại diện cho lãi suất phi rủi ro
Hiện mã
import statsmodels.api as sm

# Assume momentum_ret contains: date, mom_ret (raw return of WML portfolio)
momentum_ret = pd.read_parquet("data/momentum_returns.parquet")

alpha_results = []
for proxy_name, proxy_df in rf_proxies.items():
    rf_merge = proxy_df[["date", "rf_monthly"]].rename(
        columns={"rf_monthly": "rf_proxy"}
    )

    merged = (
        momentum_ret
        .merge(rf_merge, on="date", how="inner")
        .merge(market_monthly[["date", "rm"]], on="date", how="inner")
        .merge(factors_monthly[["date", "smb", "hml"]], on="date", how="inner")
    )

    merged["mom_excess"] = merged["mom_ret"] - merged["rf_proxy"]
    merged["mktrf"] = merged["rm"] - merged["rf_proxy"]

    X = sm.add_constant(merged[["mktrf", "smb", "hml"]])
    y = merged["mom_excess"]
    model = sm.OLS(y, X).fit(cov_type="HAC", cov_kwds={"maxlags": 6})

    alpha_results.append({
        "Proxy": proxy_name.replace("_", " ").title(),
        "Alpha (% monthly)": round(model.params["const"] * 100, 3),
        "t-stat": round(model.tvalues["const"], 2),
        "R²": round(model.rsquared, 3)
    })

pd.DataFrame(alpha_results).style.hide(axis="index")

5.6.4 Tác động lên định giá

Để minh họa tác động lên định giá, hãy xét một bài tập DCF đơn giản trong đó chi phí vốn chủ sở hữu được ước lượng bằng CAPM.

Bảng 5.12: Độ nhạy của chi phí vốn chủ sở hữu và giá trị cuối kỳ đối với biến đại diện cho lãi suất phi rủi ro
Hiện mã
# Example: firm with beta = 1.0, expected CF = 1 billion VND, growth = 3%
beta_example = 1.0
cf = 1e9  # VND
growth = 0.03

valuation_results = []
for proxy_name, proxy_df in rf_proxies.items():
    rf_ann = proxy_df["rf_annual"].dropna().iloc[-12:].mean() / 100  # Latest year avg

    rf_merge = proxy_df[["date", "rf_monthly"]].rename(
        columns={"rf_monthly": "rf_proxy"}
    )
    mkt_merged = market_monthly[["date", "rm"]].merge(
        rf_merge, on="date", how="inner"
    )
    mkt_merged["mktrf"] = mkt_merged["rm"] - mkt_merged["rf_proxy"]
    erp = mkt_merged["mktrf"].mean() * 12  # Annualized equity premium

    cost_equity = rf_ann + beta_example * erp
    terminal_value = cf / (cost_equity - growth) if cost_equity > growth else np.nan

    valuation_results.append({
        "Proxy": proxy_name.replace("_", " ").title(),
        "Rf (% ann.)": round(rf_ann * 100, 2),
        "ERP (% ann.)": round(erp * 100, 2),
        "Cost of Equity (%)": round(cost_equity * 100, 2),
        "Terminal Value (B VND)": round(terminal_value / 1e9, 1) if terminal_value else "N/A"
    })

pd.DataFrame(valuation_results).style.hide(axis="index")
Phát hiện chính

Ngay cả những chênh lệch khiêm tốn về lãi suất phi rủi ro (50-150 điểm cơ bản giữa các biến đại diện) cũng có thể tạo ra chênh lệch giá trị cuối kỳ từ 10-30%. Các nhà nghiên cứu và nhà thực hành phải ghi chép rõ ràng lựa chọn lãi suất phi rủi ro của mình và báo cáo độ nhạy đối với các phương án thay thế.

5.7 Các cân nhắc về cấu trúc kỳ hạn

Khi cần các tỷ lệ chiết khấu cho chân trời dài hơn (ví dụ cho DCF nhiều năm hoặc ước lượng chi phí vốn), lãi suất phi rủi ro cần được khớp kỳ hạn. Điều này đòi hỏi phải xây dựng một đường cong lợi suất từ dữ liệu trái phiếu chính phủ sẵn có.

5.7.1 Ước lượng đường cong lợi suất

Gürkaynak, Sack, và Wright (2007) phát triển một cách tiếp cận tham số để ước lượng đường cong lợi suất bằng các mô hình của Nelson và Siegel (1987) và Svensson (1994). Mô hình Nelson-Siegel tham số hóa lãi suất kỳ hạn tức thời như sau:

\[ f(\tau) = \beta_0 + \beta_1 \exp\left(-\frac{\tau}{\lambda}\right) + \beta_2 \frac{\tau}{\lambda} \exp\left(-\frac{\tau}{\lambda}\right) \tag{5.7}\]

trong đó \(\tau\) là kỳ hạn, \(\beta_0\) là mức dài hạn, \(\beta_1\) quyết định độ dốc, \(\beta_2\) quyết định độ cong, và \(\lambda\) kiểm soát vị trí của đỉnh lồi.

Lợi suất tương ứng là:

\[ y(\tau) = \beta_0 + \beta_1 \frac{1 - \exp(-\tau/\lambda)}{\tau/\lambda} + \beta_2 \left[\frac{1 - \exp(-\tau/\lambda)}{\tau/\lambda} - \exp(-\tau/\lambda)\right] \tag{5.8}\]

Hiện mã
from scipy.optimize import minimize

def nelson_siegel_yield(tau, beta0, beta1, beta2, lam):
    """Nelson-Siegel yield curve model."""
    tau_lam = tau / lam
    factor1 = (1 - np.exp(-tau_lam)) / tau_lam
    factor2 = factor1 - np.exp(-tau_lam)
    return beta0 + beta1 * factor1 + beta2 * factor2

def fit_nelson_siegel(maturities, yields):
    """Fit Nelson-Siegel model to observed yields."""
    def objective(params):
        beta0, beta1, beta2, lam = params
        if lam <= 0:
            return 1e10
        fitted = nelson_siegel_yield(maturities, beta0, beta1, beta2, lam)
        return np.sum((yields - fitted) ** 2)

    result = minimize(
        objective,
        x0=[yields[-1], yields[0] - yields[-1], 0, 2.0],
        method="Nelder-Mead",
        options={"maxiter": 10000}
    )
    return result.x

# Example: fit to latest available government bond yields
# Assume govt_yields contains: date, maturity_years, yield_pct
govt_yields = pd.read_parquet("data/govt_bond_yields.parquet")

latest_date = govt_yields["date"].max()
latest_yields = govt_yields[govt_yields["date"] == latest_date].sort_values("maturity_years")

maturities = latest_yields["maturity_years"].values
yields = latest_yields["yield_pct"].values

params = fit_nelson_siegel(maturities, yields)
beta0, beta1, beta2, lam = params
Hiện mã
tau_fine = np.linspace(0.25, 30, 200)
fitted_yields = nelson_siegel_yield(tau_fine, *params)

fig, ax = plt.subplots(figsize=(7, 4))
ax.scatter(
    maturities, yields, color="#FF6B6B", s=60, zorder=5,
    label="Observed yields", edgecolors="white"
)
ax.plot(
    tau_fine, fitted_yields, color="#2C73D2", linewidth=2,
    label="Nelson-Siegel fit"
)
ax.set_xlabel("Maturity (Years)")
ax.set_ylabel("Yield (%)")
ax.legend(frameon=False)
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
plt.tight_layout()
plt.show()

print(f"Nelson-Siegel parameters:")
print(f"  β₀ (level)     = {beta0:.4f}")
print(f"  β₁ (slope)     = {beta1:.4f}")
print(f"  β₂ (curvature) = {beta2:.4f}")
print(f"  λ (decay)      = {lam:.4f}")
Hình 5.4
Mẹo

Đường cong lợi suất Nelson-Siegel cho phép trích xuất lãi suất phi rủi ro ở bất kỳ kỳ hạn nào. Với định giá tài sản theo tháng, hãy tính giá trị của đường cong tại \(\tau = 1/12\) (một tháng). Với định giá DCF có chân trời 10 năm, hãy tính tại \(\tau = 10\). Cách khớp kỳ hạn này vượt trội so với việc dùng một biến đại diện duy nhất cho mọi mục đích.

5.7.2 Trích xuất lãi suất ngắn hạn từ đường cong lợi suất

Hiện mã
# Extract 1-month rate from Nelson-Siegel curve at each date
def extract_ns_short_rate(govt_yields, target_maturity=1/12):
    """
    For each date, fit Nelson-Siegel and extract the yield
    at the target maturity.
    """
    dates = govt_yields["date"].unique()
    short_rates = []

    for d in dates:
        obs = govt_yields[govt_yields["date"] == d].sort_values("maturity_years")
        if len(obs) < 3:  # Need at least 3 points to fit
            short_rates.append({"date": d, "rf_ns": np.nan})
            continue

        try:
            params = fit_nelson_siegel(
                obs["maturity_years"].values,
                obs["yield_pct"].values
            )
            rf_ns = nelson_siegel_yield(target_maturity, *params)
            short_rates.append({"date": d, "rf_ns": rf_ns})
        except Exception:
            short_rates.append({"date": d, "rf_ns": np.nan})

    return pd.DataFrame(short_rates)

ns_short_rates = extract_ns_short_rate(govt_yields)

5.7.3 Lợi nhuận vượt mức khớp duration

Đường cong lợi suất cũng là đầu vào cho một đề xuất triệt để hơn về việc “lợi nhuận vượt mức” nên có nghĩa là gì. Quy ước dùng xuyên suốt cuốn sách này, trừ lãi suất ngắn hạn khỏi lợi nhuận cổ phiếu theo tháng, khớp kỳ hạn của chuẩn so sánh với tần suất đo lường lợi nhuận thay vì với kỳ hạn của các dòng tiền được định giá. Cổ phiếu là các quyền đòi có duration dài; tín phiếu một tháng thì không. Binsbergen, Ma, và Schwert (2026) lập luận rằng một phản thực tế sạch hơn là thay quyền đòi của mỗi danh mục đối với dòng tiền tại chân trời \(h\) bằng một trái phiếu chính phủ zero-coupon (không trả lãi định kỳ) kỳ hạn \(h\), từng phần một (strip by strip), và định nghĩa lợi nhuận vượt mức là lợi nhuận thô trừ đi lợi nhuận của danh mục trái phiếu khớp duration đó. Phần còn lại là khoản bù đắp cho việc chịu rủi ro của các dòng tiền rủi ro, với phần bù kỳ hạn được loại bỏ và dành cho các nghiên cứu về thu nhập cố định.

Hệ quả lớn hơn nhiều so với những gì bản chất cơ học của việc điều chỉnh này gợi ý. Với dữ liệu Hoa Kỳ giai đoạn 1962 đến 2020, lợi nhuận vượt mức thị trường thông thường trung bình 0.53% mỗi tháng, trong khi phiên bản điều chỉnh duration trung bình \(-0.20\%\) mỗi tháng với độ biến động gấp khoảng hai lần, và hai chuỗi có tương quan dưới 0.5. Theo mặt cắt ngang, phần bù giá trị và đầu tư tăng lên theo định nghĩa điều chỉnh duration, phần bù quy mô giảm đi, còn động lượng hầu như không đổi vì các danh mục thắng và thua có duration tương tự nhau. Trong 153 hiện tượng bất thường đã công bố, 20 hiện tượng thay đổi trạng thái về ý nghĩa thống kê khi chỉ thay đổi định nghĩa lợi nhuận vượt mức (Binsbergen, Ma, và Schwert 2026), một điểm mà chúng ta sẽ quay lại ở Mục 21.1.

Với Việt Nam, logic tương tự cũng áp dụng, nhưng trên một lộ trình lãi suất ngắn hơn và dốc hơn. Đường cong Nelson-Siegel đã khớp ở trên là nguyên liệu cho một chuẩn so sánh khớp duration, nhưng có hai trở ngại thực tế. Thứ nhất, thanh khoản thị trường thứ cấp tập trung ở nhóm kỳ hạn 3-5 năm (Bảng 5.2), nên đường cong khớp vừa là ngoại suy vừa là ước lượng ở cả đầu rất ngắn lẫn đầu rất dài, đúng những kỳ hạn mà việc khớp từng phần đòi hỏi. Thứ hai, các trọng số từng phần cần tỷ suất cổ tức và tốc độ tăng trưởng kỳ vọng cho mỗi danh mục, điều này mong manh đối với các doanh nghiệp có lịch sử chi trả không đều, mà chính sách chi trả của Việt Nam lại không đều so với chuẩn của các thị trường phát triển. Một giải pháp dung hòa khả thi là báo cáo các phần bù nhân tố so với cả lãi suất ngắn hạn lẫn một trái phiếu chính phủ kỳ hạn dài cố định, và công bố chênh lệch tỷ suất cổ tức giữa vế dài và vế ngắn để người đọc có thể đánh giá bao nhiêu phần của một khoản phần bù có thể chỉ là một canh bạc về duration.

5.8 Lãi suất phi rủi ro thực và danh nghĩa

Đối với một số ứng dụng, đặc biệt là định giá dài hạn và phân tích lợi nhuận thực, lãi suất phi rủi ro thực (đã điều chỉnh lạm phát) phù hợp hơn lãi suất danh nghĩa. Phương trình Fisher liên hệ hai loại lãi suất này:

\[ r_f^{real} \approx r_f^{nominal} - \pi^{e} \tag{5.9}\]

trong đó \(\pi^e\) là lạm phát kỳ vọng. Trong thực tế, chúng ta có thể dùng lạm phát CPI thực hiện làm biến đại diện cho lạm phát kỳ vọng (với giả định kỳ vọng hợp lý, hoặc như một điều chỉnh sau sự kiện).

Hiện mã
# Load CPI data
# Assume cpi_data contains: date, cpi_index (or inflation_mom for month-over-month)
cpi_data = pd.read_parquet("data/cpi_monthly.parquet")
cpi_data = cpi_data.sort_values("date")
cpi_data["inflation_monthly"] = cpi_data["cpi_index"].pct_change()

rf_real = rf_blended[["date", "rf_monthly"]].merge(
    cpi_data[["date", "inflation_monthly"]], on="date", how="inner"
)
rf_real["rf_real"] = rf_real["rf_monthly"] - rf_real["inflation_monthly"]
Hiện mã
fig, ax = plt.subplots(figsize=(8, 4))
ax.plot(
    rf_real["date"], rf_real["rf_monthly"] * 100,
    color="#2C73D2", label="Nominal", linewidth=1
)
ax.plot(
    rf_real["date"], rf_real["rf_real"] * 100,
    color="#FF6B6B", label="Real", linewidth=1
)
ax.axhline(0, color="black", linewidth=0.5, linestyle="--")
ax.set_ylabel("Monthly Rate (%)")
ax.set_xlabel("")
ax.legend(frameon=False)
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
plt.tight_layout()
plt.show()
Hình 5.5
Ghi chú

Trong các giai đoạn lạm phát cao, lãi suất phi rủi ro thực có thể âm đáng kể. Điều này có hệ quả đối với việc tính lợi nhuận vượt mức thực và đối với việc diễn giải phần bù cổ phiếu theo giá trị thực. Lãi suất phi rủi ro thực âm hàm ý rằng các chứng khoán chính phủ danh nghĩa không bảo toàn sức mua, điều này củng cố lập luận ủng hộ đầu tư cổ phiếu từ góc nhìn lợi nhuận thực.

5.9 So sánh quốc tế

Việc so sánh môi trường lãi suất phi rủi ro của Việt Nam với các thị trường mới nổi và phát triển khác là hữu ích để đặt các độ lớn vào bối cảnh (Bảng 5.13).

Bảng 5.13: Các biến đại diện cho lãi suất phi rủi ro: so sánh quốc tế
Quốc gia Biến đại diện điển hình Kỳ hạn ngắn hạn sẵn có Mức điển hình (%, 2020-2024)
Việt Nam Liên ngân hàng qua đêm / trái phiếu chính phủ 1 năm Hạn chế (kỳ hạn <1 năm thưa thớt) 2.5-6.0
Thái Lan Lãi suất mua lại song phương 1 ngày Có (repo 1 ngày) 0.5-2.5
Indonesia Lãi suất repo ngược 7 ngày của Bank Indonesia Có (7 ngày, 1 tháng) 3.5-6.0
Philippines Tín phiếu 91 ngày Có (tín phiếu 91 ngày) 1.5-6.0
Ấn Độ Tín phiếu 91 ngày Có (tín phiếu 91 ngày) 3.5-7.0
Hàn Quốc Lãi suất chứng chỉ tiền gửi (CD) 91 ngày Có (CD 91 ngày) 1.0-3.5
Nhật Bản Lãi suất call qua đêm không có tài sản bảo đảm Có (qua đêm) -0.1-0.1
Hiện mã
# get the risk-free rate of Asian markets

Môi trường lãi suất phi rủi ro của Việt Nam có đặc điểm là lãi suất danh nghĩa tương đối cao (phản ánh lạm phát và động lực tăng trưởng), việc sẵn có các công cụ chính phủ kỳ hạn rất ngắn còn hạn chế, và sự phụ thuộc nhiều hơn vào lãi suất liên ngân hàng làm biến đại diện trên thực tế. Điều này nhìn chung tương tự các thị trường cận biên khác của ASEAN nhưng đối lập rõ rệt với các thị trường châu Á phát triển, nơi thị trường chứng khoán chính phủ sâu cung cấp các chuẩn ngắn hạn sạch.

5.10 Danh sách kiểm tra các thực hành tốt nhất

Dựa trên phân tích trong chương này, chúng ta tóm tắt các thực hành được khuyến nghị để xây dựng lãi suất phi rủi ro trong nghiên cứu tài chính tại Việt Nam (Bảng 5.14).

Bảng 5.14: Các thực hành tốt nhất để xây dựng lãi suất phi rủi ro
Thực hành Lý do
Dùng kỳ hạn ngắn nhất sẵn có Giảm thiểu sự nhiễm phần bù kỳ hạn
Khớp tần suất với dữ liệu lợi nhuận Tránh sai lệch ghép lãi giữa rf và lợi nhuận cổ phiếu
Dùng cùng quy ước ghép lãi Lợi nhuận số học đòi hỏi chuyển đổi rf theo số học
Ghi chép rõ ràng biến đại diện và nguồn Cho phép tái lập; các biến đại diện khác nhau cho kết quả khác nhau
Báo cáo độ nhạy đối với các biến đại diện thay thế Chứng tỏ độ vững của kết luận
Tránh các mức lãi suất điều hành mang tính định hướng tương lai Lãi suất điều hành không phải là lợi nhuận có thể đầu tư
Xử lý khoảng trống bằng nội suy có ghi chép Điền tiếp, sau đó lấy trung bình trong tháng; ghi chép quy trình
Dùng Nelson-Siegel để khớp kỳ hạn Cho phép trích xuất lãi suất ở bất kỳ kỳ hạn nào từ dữ liệu thưa
Cân nhắc lãi suất thực cho phân tích dài hạn Lãi suất danh nghĩa phóng đại khoản bù đắp thực trong các giai đoạn lạm phát cao
Duy trì một chuỗi nhất quán duy nhất cho mỗi nghiên cứu Trộn lẫn các biến đại diện giữa các giai đoạn sẽ đưa vào các điểm gãy cấu trúc

5.11 Lưu lãi suất phi rủi ro để sử dụng ở các bước sau

Bước cuối cùng là lưu chuỗi lãi suất phi rủi ro đã xây dựng để dùng trong các chương tiếp theo.

Hiện mã
# Save all variants for flexibility
rf_output = rf_blended[["date", "rf_monthly", "source"]].copy()
rf_output["rf_annual_pct"] = rf_output["rf_monthly"] * 12 * 100

# Also save individual proxies
for proxy_name, proxy_df in rf_proxies.items():
    col_name = f"rf_{proxy_name}"
    rf_output = rf_output.merge(
        proxy_df[["date", "rf_monthly"]].rename(
            columns={"rf_monthly": col_name}
        ),
        on="date",
        how="left"
    )

# Save to parquet for use in later chapters
rf_output.to_parquet("data/risk_free_rate.parquet", index=False)

print(f"Risk-free rate series saved: {len(rf_output)} months")
print(f"Date range: {rf_output['date'].min()} to {rf_output['date'].max()}")
print(f"\nColumns: {list(rf_output.columns)}")
Mẹo

Bằng cách lưu lãi suất phi rủi ro thành một tệp riêng, được ghi chép đầy đủ, mọi chương phía sau có thể kết hợp nó một cách nhất quán. Điều này tránh được cái bẫy thường gặp là xây dựng lại lãi suất phi rủi ro theo cách khác nhau trong các phân tích khác nhau của cùng một nghiên cứu.

5.12 Tóm tắt

Chương này đã xác lập rằng việc xây dựng lãi suất phi rủi ro là một quyết định mô hình hóa bậc nhất trong nghiên cứu tài chính tại Việt Nam, không phải một chi tiết kỹ thuật thứ yếu. Các điểm rút ra chính là:

  1. Không có biến đại diện hoàn hảo tại Việt Nam. Lãi suất liên ngân hàng qua đêm, lợi suất trái phiếu chính phủ 1 năm và lãi suất điều hành của NHNN đều có điểm mạnh và hạn chế riêng. Một chuỗi kết hợp theo thứ tự ưu tiên được ghi chép rõ ràng cung cấp phương án cơ sở vững chắc nhất.

  2. Việc chọn biến đại diện quan trọng về mặt định lượng. Các biến đại diện khác nhau có thể làm dịch chuyển phần bù cổ phiếu ước lượng 50-200 điểm cơ bản mỗi năm, thay đổi alpha của danh mục, và thay đổi giá trị cuối kỳ của DCF 10-30%.

  3. Căn chỉnh tần suất và quy ước ghép lãi phải được xử lý cẩn thận. Chuyển lãi suất quy năm sang tháng đòi hỏi phải chỉ rõ quy ước ghép lãi. Các khoảng trống trong dữ liệu đòi hỏi nội suy có ghi chép.

  4. Mô hình đường cong lợi suất Nelson-Siegel cho phép trích xuất lãi suất phi rủi ro ở bất kỳ kỳ hạn nào từ dữ liệu trái phiếu chính phủ thưa, điều đặc biệt có giá trị cho việc ước lượng tỷ lệ chiết khấu khớp kỳ hạn.

  5. Phân tích độ nhạy là bắt buộc. Bất kỳ nghiên cứu nào báo cáo kết quả theo một biến đại diện duy nhất cho lãi suất phi rủi ro mà không báo cáo độ vững đối với các phương án thay thế đều có một nguồn bất định về cách xác định mô hình chưa được lượng hóa.