定期存单价格 · ISDA(国际通用)
返回 CD 净价与应计利息
CD(定期存单)到期一次性还本付息,按单利计息。
格式 yyyy-mm-dd
格式 yyyy-mm-dd
格式 yyyy-mm-dd
计算结果
点击「计算」查看输出
code
计算逻辑代码
以下为「ISDA国际通用」QuantLib 代码示例。
# 依赖版本:
# python==3.9
# QuantLib==1.43
# -*- coding: utf-8 -*-
from datetime import datetime
import traceback
import QuantLib as ql
# ============================================================
# 工具函数(原 util 模块内联)
# ============================================================
def _parse_date(s: str) -> ql.Date:
"""解析 'yyyy-mm-dd' 字符串为 ql.Date"""
d = datetime.strptime(s.strip(), "%Y-%m-%d")
return ql.Date(d.day, d.month, d.year)
def _map_period(period: int):
"""年付息次数 -> (ql.Period, ql.Frequency)"""
mapping = {
0: (None, ql.NoFrequency),
1: (ql.Period(ql.Annual), ql.Annual),
2: (ql.Period(ql.Semiannual), ql.Semiannual),
3: (ql.Period(4, ql.Months), ql.EveryFourthMonth),
4: (ql.Period(ql.Quarterly), ql.Quarterly),
6: (ql.Period(ql.Bimonthly), ql.Bimonthly),
12: (ql.Period(ql.Monthly), ql.Monthly),
}
if period not in mapping:
raise ValueError(f"不支持的 Period: {period}")
return mapping[period]
def _map_basis(basis: int):
"""日计数基准编号 -> ql.DayCounter"""
mapping = {
0: ql.ActualActual(ql.ActualActual.ISDA),
1: ql.Thirty360(ql.Thirty360.USA),
2: ql.Actual360(),
3: ql.Actual365Fixed(),
4: ql.Thirty360(ql.Thirty360.BondBasis),
5: ql.Thirty360(ql.Thirty360.ISDA),
6: ql.Thirty360(ql.Thirty360.European),
7: ql.Actual365Fixed(),
8: ql.ActualActual(ql.ActualActual.ISMA),
9: ql.Actual360(),
10: ql.Actual365Fixed(),
11: ql.Thirty360(ql.Thirty360.EurobondBasis),
12: ql.Actual365Fixed(),
13: ql.Business252(),
}
if basis not in mapping:
raise ValueError(f"暂不支持的 Basis: {basis}")
return mapping[basis]
# ============================================================
# 核心计算函数
# ============================================================
def qjquant_calu_cdprice(
yield_var: float,
coupon_rate_var: float,
settle_var: str,
maturity_var: str,
issue_date_var: str,
basis_var: int = 2,
):
try:
# ---------- 参数校验 ----------
if yield_var < 0:
return {"ok": False, "msg": "到期收益率不能为负"}
if coupon_rate_var < 0:
return {"ok": False, "msg": "息票率不能为负"}
settle_date = _parse_date(settle_var)
maturity_date = _parse_date(maturity_var)
issue_date = _parse_date(issue_date_var)
if issue_date > settle_date:
return {"ok": False, "msg": "签发日必须早于或等于结算日"}
if settle_date >= maturity_date:
return {"ok": False, "msg": "结算日必须早于到期日"}
dc = _map_basis(basis_var)
# 两个关键年分数
T_issue_to_mat = dc.yearFraction(issue_date, maturity_date)
T_issue_to_set = dc.yearFraction(issue_date, settle_date)
T_set_to_mat = dc.yearFraction(settle_date, maturity_date)
if T_set_to_mat <= 0:
return {"ok": False, "msg": "结算日至到期日的年分数必须为正"}
# 到期支付金额 = 本金 + 单利票息
redemption = 100.0 * (1.0 + coupon_rate_var * T_issue_to_mat)
# 全价 = 到期支付 / (1 + Yield * T_settle_to_maturity)
dirty_price = redemption / (1.0 + yield_var * T_set_to_mat)
# 应计利息 = 本金 × 票息率 × 已计息年分数
accrued = 100.0 * coupon_rate_var * T_issue_to_set
clean_price = dirty_price - accrued
return {
"ok": True,
"price": round(clean_price, 4),
"accrued": round(accrued, 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("示例 1:实际/360(basis=2,美国 CD 常用)")
print("=" * 60)
r1 = qjquant_calu_cdprice(
yield_var=0.0525,
coupon_rate_var=0.05,
settle_var="2002-01-02",
maturity_var="2002-03-31",
issue_date_var="2001-10-01",
basis_var=2,
)
print(r1)
print()
print("=" * 60)
print("示例 2:实际/365(basis=3)")
print("=" * 60)
r2 = qjquant_calu_cdprice(
yield_var=0.05,
coupon_rate_var=0.04,
settle_var="2024-03-15",
maturity_var="2024-09-15",
issue_date_var="2024-01-01",
basis_var=3,
)
print(r2)
print()
print("=" * 60)
print("示例 3:实际/实际 ISDA(basis=0)")
print("=" * 60)
r3 = qjquant_calu_cdprice(
yield_var=0.05,
coupon_rate_var=0.04,
settle_var="2024-03-15",
maturity_var="2024-09-15",
issue_date_var="2024-01-01",
basis_var=0,
)
print(r3)
print()
print("=" * 60)
print("示例 4:30/360 USA(basis=1)")
print("=" * 60)
r4 = qjquant_calu_cdprice(
yield_var=0.05,
coupon_rate_var=0.04,
settle_var="2024-03-15",
maturity_var="2024-09-15",
issue_date_var="2024-01-01",
basis_var=1,
)
print(r4)