国库券收益率

国库券收益率 根据价格计算三种口径收益率
根据每 100 元面值的国库券价格、结算日与到期日,计算货币市场收益率(MMYield)、债券等价收益率(BEYield)和贴现率(Discount)。
格式 yyyy-mm-dd
格式 yyyy-mm-dd
计算结果
点击「计算」查看输出
code 计算逻辑代码
以下为「国库券收益率」QuantLib 代码示例。

# 依赖版本:
# python==3.9
# QuantLib==1.43
import traceback
from datetime import datetime,date as py_date
import QuantLib as ql
from fastapi import Query


# ============================================================
# 工具函数
# ============================================================
def _parse_date(s: str) -> ql.Date:
    d = datetime.strptime(s.strip(), "%Y-%m-%d")
    return ql.Date(d.day, d.month, d.year)

# ============================================================
# 核心计算函数
# ============================================================
def qjquant_calu_tbillyield(
    price: float = Query(...),
    settle_date: str = Query(...),
    maturity_date: str = Query(...),
):
    try:
        # ---------- 参数校验 ----------
        if price <= 0 or price > 100:
            return {"ok": False, "msg": "价格必须大于 0 且不超过 100"}

        settle_qd   = _parse_date(settle_date)
        maturity_qd = _parse_date(maturity_date)

        if settle_qd >= maturity_qd:
            return {"ok": False, "msg": "结算日必须早于到期日"}

        # ---------- 实际天数 ----------
        # 结算日至到期日的实际天数(Actual/360 与 Actual/365 的天数部分相同)
        days = ql.Actual360().dayCount(settle_qd, maturity_qd)
        if days <= 0:
            return {"ok": False, "msg": "到期天数异常"}

        FACE = 100.0

        # ---------- 1) 货币市场收益率 MMYield(Actual/360) ----------
        # 价格关系:Price = FACE / (1 + MMYield * days/360)
        mm_yield = (FACE / price - 1.0) * 360.0 / days

        # ---------- 3) 贴现率 Discount(Actual/360) ----------
        # 价格关系:Price = FACE * (1 - Discount * days/360)
        discount = (1.0 - price / FACE) * 360.0 / days

        # ---------- 2) 债券等价收益率 BEYield ----------
        # MATLAB tbillyield 口径:
        #   期限 <= 182 天:BEY = (FACE/Price - 1) * 365/days
        #   期限 >  182 天:BEY 由二次方程求解(长期国库券口径)
        if days <= 182:
            be_yield = (FACE / price - 1.0) * 365.0 / days
        else:
            # 长期 T-Bill BEY 定价公式:
            #   Price = FACE / (1 + BEY * days/365)  的精确反向需解二次方程
            # 采用市场标准的二次公式:
            #   BEY = [-2*days/365 + sqrt((2*days/365)^2 + 4*(FACE/Price - 1))] / 2
            # 即求解: (days/365)*BEY^2/2 + BEY - (FACE/Price - 1) = 0
            # 但更常见的长期公式为:
            #   Price = FACE / (1 + BEY * days/365) 仅在 <=182 天有效;
            # 长期使用:
            #   BEY = (2 * (FACE/Price - 1)) / (days/365 + sqrt((days/365)^2 + 4*(FACE/Price - 1)))
            # 下面采用与 MATLAB 一致的二次公式:
            t = days / 365.0
            r = FACE / price - 1.0
            # 解方程: t * BEY^2 / 2 + BEY - r = 0  =>  BEY = [-1 + sqrt(1 + 2*t*r)] / t
            # 注意:MATLAB 文档对长期 T-Bill 的 BEY 使用如下公式:
            #   BEY = (2*(FACE/Price - 1)) / (t + sqrt(t^2 + 4*(FACE/Price - 1)))
            # 等价于解 t*BEY^2/2 + BEY - r = 0 的正根。
            discriminant = 1.0 + 2.0 * t * r
            if discriminant < 0:
                return {"ok": False, "msg": "长期国库券 BEY 计算判别式异常"}
            be_yield = (-1.0 + (discriminant ** 0.5)) / t

        # ---------- 结果 ----------
        return {
            "ok": True,
            "mm_yield": round(mm_yield, 4),
            "be_yield": round(be_yield, 4),
            "discount": round(discount, 4),
        }

    except ValueError as ve:
        traceback.print_exc()
        return {"ok": False, "msg": f"参数错误: {ve}"}
    except Exception as e:
        traceback.print_exc()
        return {"ok": False, "msg": f"未知错误: {e}"}


# ============================================================
# 可复制运行的示例
# ============================================================
if __name__ == "__main__":
    print("=" * 60)
    print("国库券收益率 tbillyield 示例")
    print("=" * 60)

    # 示例 1:期限 <= 182 天(短期,BEY 用简单公式)
    r1 = qjquant_calu_tbillyield(
        price=97.8172,
        settle_date="2024-01-02",
        maturity_date="2024-07-01",
    )
    print("\n[示例1] 短期 180 天,价格 97.8172")
    print("  结果:", r1)

    # 示例 2:期限 > 182 天(长期,BEY 用二次公式)
    r2 = qjquant_calu_tbillyield(
        price=95.5000,
        settle_date="2024-01-02",
        maturity_date="2024-12-31",
    )
    print("\n[示例2] 长期 364 天,价格 95.5000")
    print("  结果:", r2)

    # 示例 3:价格 = 100(边界,收益率为 0)
    r3 = qjquant_calu_tbillyield(
        price=100.0,
        settle_date="2024-01-02",
        maturity_date="2024-07-01",
    )
    print("\n[示例3] 价格 100.0(边界)")
    print("  结果:", r3)