# 不同day count下計算債券價格
:::info
Calculate the dirty and the clean price for a bond under actual/actual and 30/360 day count conversion.
Input: Bond maturity date, settlement date, bond yield, and the coupon rate.
The bond is assumed to pay coupons
:::
### 目標
計算actual/actual和30/360的day count計算方法下,債券的淨價和全價。
輸入: 債券到期日、結算日、債券收益率YTM和票面利率coupon rate。
假設債券半年付息一次。
## 程式碼 (by python)
### 輸入資料
將 settlement date 、 maturity date 、 coupon rate 以及 bond yield (YTM) 輸入,並且透過 flag 輸入 1 或 2 來判斷 day count 的種類。
並且
```pyhton=
import math
import datetime
settlement_date = input("Please input settlement date. \n")
settlement_date = datetime.datetime.strptime(settlement_date,'%Y%m%d').date()
maturity_date = input("Please input maturity date.\n")
maturity_date = datetime.datetime.strptime(maturity_date,'%Y%m%d').date()
coupon_rate = float(input("Please input coupon_rate. \n"))
bond_yield = float(input("Please input bond yield(YTM). \n"))
flag = input("Please select day count. Input \"1\" ==> actual/actual, input \"2\" ==> 30/360. ")
face_value = 100
m_date = datetime.date(settlement_date.year, maturity_date.month, maturity_date.day) #將到期日的月分和日期移到交割日的那一年來比較
#為了找出在settlement date前後的coupon date來算出 coupon periods 和 days in periods
```
### 使用actual/actual
```python=
if flag == "1": #actual/actual
if m_date < settlement_date: # m_date 比 settlement_date 早
if settlement_date.month - m_date.month > 6: # m_date 比 settlement_date早了超過6個月的話
if maturity_date.month <= 6:
m_date = datetime.date(settlement_date.year, m_date.month+6, m_date.day)
else:
n = maturity_date.month - 6
m_date = datetime.date(settlement_date.year+1, m_date.month+n, m_date.day)
interval = settlement_date - m_date
time_before_settlement = interval.days #算出settlement_date和上一個coupon_date距離有幾天
if maturity_date.month <= 6:
coupon_date = datetime.date(settlement_date.year, m_date.month+6, m_date.day)
else:
n = maturity_date.month - 6
coupon_date = datetime.date(settlement_date.year+1, m_date.month+n, m_date.day)
previous_coupon_date = datetime.date(m_date.year, m_date.month, m_date.day)
periods = coupon_date - settlement_date
time_after_settlement = periods.days #算出settlement_date和下一個coupon_date距離有幾天
w = time_after_settlement/(time_before_settlement + time_after_settlement)
elif m_date > settlement_date: # settlement_date 比 m_date 早
if m_date - settlement_date > 6: # settlement_date 比 m_date 早了超過6個月
if maturity_date.month <= 6:
m_date = datetime.date(settlement_date.year-1, m_date.month+6, m_date.day)
else:
m_date = datetime.date(settlement_date.year, m_date.month-6, m_date.day)
interval = m_date - settlement_date
time_after_settlement = interval.days #算出settlement_date和下一個coupon_date距離有幾天
coupon_date = datetime.date(m_date.year, m_date.month, m_date.day)
if maturity_date.month <= 6:
previous_coupon_date = datetime.date(settlement_date.year-1, m_date.month+6, m_date.day)
else:
previous_coupon_date = datetime.date(settlement_date.year, m_date.month-6, m_date.day)
periods = settlement_date - previous_coupon_date
time_before_settlement = periods.days #算出settlement_date和上一個coupon_date距離有幾天
w = time_after_settlement/(time_before_settlement + time_after_settlement)
else:
w = 1 #交割日的和coupon date 一樣
```
### 使用30/360
```python=
elif flag == "2": # 30/360
if m_date < settlement_date: # m_date 比 settlement_date 早
if settlement_date.month - m_date.month > 6: # m_date 比 settlement_date早了超過6個月的話
if maturity_date.month <= 6:
m_date = datetime.date(settlement_date.year, m_date.month+6, m_date.day)
else:
n = maturity_date.month - 6
m_date = datetime.date(settlement_date.year+1, m_date.month+n, m_date.day)
time_before_settlement = (settlement_date.year - m_date.year) * 360 + \
(settlement_date.month - m_date.month) * 30 + \
(settlement_date.day - m_date.day) #算出settlement_date和上一個coupon_date距離有幾天
if maturity_date.month <= 6:
coupon_date = datetime.date(settlement_date.year, m_date.month+6, m_date.day)
else:
n = maturity_date.month - 6
coupon_date = datetime.date(settlement_date.year+1, m_date.month+n, m_date.day)
previous_coupon_date = datetime.date(m_date.year, m_date.month, m_date.day)
time_after_settlement = (coupon_date.year - settlement_date.year) * 360 + \
(coupon_date.month - settlement_date.month) * 30 + \
(coupon_date.day - settlement_date.day)
w = time_after_settlement/(time_before_settlement + time_after_settlement)
elif m_date > settlement_date: # settlement_date 比 m_date 早
if m_date - settlement_date > 6: # settlement_date 比 m_date 早了超過6個月
if maturity_date.month <= 6:
m_date = datetime.date(settlement_date.year-1, m_date.month+6, m_date.day)
else:
m_date = datetime.date(settlement_date.year, m_date.month-6, m_date.day)
time_after_settlement = (m_date.year - settlement_date.year) * 360 + \
(m_date.month - settlement_date.month) * 30 + \
(m_date.day - settlement_date.day) #算出settlement_date和下一個coupon_date距離有幾天
coupon_date = datetime.date(m_date.year, m_date.month, m_date.day)
if maturity_date.month <= 6:
previous_coupon_date = datetime.date(settlement_date.year-1, m_date.month+6, m_date.day)
else:
previous_coupon_date = datetime.date(settlement_date.year, m_date.month-6, m_date.day)
periods = settlement_date - previous_coupon_date
time_before_settlement = (settlement_date.year - previous_coupon_date.year) * 360 + \
(settlement_date.month - previous_coupon_date.month) * 30 + \
(settlement_date.day - previous_coupon_date.day)
#算出settlement_date和上一個coupon_date距離有幾天
w = time_after_settlement/(time_before_settlement + time_after_settlement)
else:
w = 1 #解決日期相等時的狀況
else:
print("Please input 1 or 2 to select day count") #防呆,要求輸入必須為1or2
```
### 計算期數(完整經過的期數)
```python=
years = maturity_date.year - settlement_date.year
if maturity_date.month > 6:
times = years * 2 -1
else:
times = years * 2 #半年配息一次
coupon = (face_value * coupon_rate)/2
dirty_price = 0
clean_price = 0
for i in range(times):
dirty_price += coupon * math.pow(1+bond_yield/2,-w-i)
dirty_price += 100 * math.pow(1+bond_yield/2,-w-i)
accured_interest = coupon * (1-w)
clean_price = dirty_price - accured_interest
print("dirty_price = ",dirty_price)
print("clean_price = ",clean_price)
print("accured_interest = ",accured_interest)
```
### 執行畫面

###### 以actual/actual為例
首先會輸入 settlement date,日期中間不需要空格,接著輸入 maturity date,還有 coupon rate 和 bond yield,最後選擇 day count 的種類,輸入 1代表使用 actual/actual,輸入 2 代表使用 30/360,就能得到 dirty price 和clean price,還有 accrued interest 的值。
---
###### tags: `財務工程`、`期貨與選擇權`、`債券`、`Python`