在 QuantLib-Python 中用于 Bootstrapping 的债券重新定价

问题描述 投票:0回答:1

我有包含债券信息的数据,我设法使用这些信息来引导零曲线。为了检查我的零曲线是否正确,我想使用引导曲线(使用零曲线)对债券重新定价,以返回债券的报价。我在重新定价部分遇到以下错误,如果有人可以提供帮助,我将不胜感激;

Traceback (most recent call last):
  File "/Users/Library/CloudStorage/OneDrive-Personal/QuantLib Software/Valuations/IRS using Bond Bootstrapping/IRS using Bond Bootstrapping 2.py", line 369, in <module>
    bondEngine = ql.DiscountingBondEngine(curve)
  File "/usr/local/lib/python3.9/site-packages/QuantLib/QuantLib.py", line 25290, in __init__
    _QuantLib.DiscountingBondEngine_swiginit(self, _QuantLib.new_DiscountingBondEngine(discountCurve))
TypeError: in method 'new_DiscountingBondEngine', argument 1 of type 'Handle< YieldTermStructure > const &'

在下面找到我正在运行的代码;

# Importing Libraries:
# The code imports necessary libraries:
# pandas for data manipulation, matplotlib.pyplot for plotting, and QuantLib (ql) for quantitative finance calculations.
import pandas as pd
import matplotlib.pyplot as plt
# Use the QuantLib or ORE Libraries
import QuantLib as ql

# Setting Evaluation Date:
# Sets the evaluation date
today = ql.Date(21, ql.November, 2023)
ql.Settings.instance().evaluationDate = today

# Calendar and Day Count:
# Creates a calendar object and specifies the day-count convention (Actual/365 Fixed)
calendar = ql.NullCalendar()
day_count = ql.Actual365Fixed()

# Settlement Days:
zero_coupon_settlement_days = 4
coupon_bond_settlement_days = 3

# Face Value
faceAmount = 100

data = [
    ('11-09-2023', '11-12-2023', 0, 99.524, zero_coupon_settlement_days),
    ('11-09-2023', '11-03-2024', 0, 96.539, zero_coupon_settlement_days),
    ('11-09-2023', '10-06-2024', 0, 93.552, zero_coupon_settlement_days),
    ('11-09-2023', '09-09-2024', 0, 89.510, zero_coupon_settlement_days),
    ('22-08-2022', '22-08-2024', 9.0, 96.406933, coupon_bond_settlement_days),
    ('27-06-2022', '27-06-2025', 10.0, 88.567570, coupon_bond_settlement_days),
    ('27-06-2022', '27-06-2027', 11.0, 71.363073, coupon_bond_settlement_days),
    ('22-08-2022', '22-08-2029', 12.0, 62.911623, coupon_bond_settlement_days),
    ('27-06-2022', '27-06-2032', 13.0, 55.976845, coupon_bond_settlement_days),
    ('22-08-2022', '22-08-2037', 14.0, 52.656596, coupon_bond_settlement_days)]

helpers = []

for issue_date, maturity, coupon, price, settlement_days in data:
    price = ql.QuoteHandle(ql.SimpleQuote(price))
    issue_date = ql.Date(issue_date, '%d-%m-%Y')
    maturity = ql.Date(maturity, '%d-%m-%Y')
    schedule = ql.MakeSchedule(issue_date, maturity, ql.Period(ql.Semiannual))
    helper = ql.FixedRateBondHelper(price, settlement_days, faceAmount, schedule, [coupon / 100], day_count,
                                    False)
    helpers.append(helper)

curve = ql.PiecewiseCubicZero(today, helpers, day_count)

# Enable Extrapolation:
# This line enables extrapolation for the yield curve.
# Extrapolation allows the curve to provide interest rates or rates beyond the observed data points,
# which can be useful for pricing or risk management purposes.
curve.enableExtrapolation()

# Zero Rate and Discount Rate Calculation:
# Calculates and prints the zero rate and discount rate at a specific
# future date (May 28, 2048) using the constructed yield curve.
date = ql.Date(28, ql.May, 2024)
zero_rate = curve.zeroRate(date, day_count, ql.Annual).rate()
forward_rate = curve.forwardRate(date, date + ql.Period(1, ql.Years), day_count, ql.Annual).rate()
discount_rate = curve.discount(date)
print("Zero rate as at 28.05.2048: " + str(round(zero_rate*100, 4)) + str("%"))
print("Forward rate as at 28.05.2048: " + str(round(forward_rate*100, 4)) + str("%"))
print("Discount factor as at 28.05.2048: " + str(round(discount_rate, 4)))

# Print the Zero Rates, Forward Rates and Discount Factors at node dates
# print(pd.DataFrame(curve.nodes()))
node_data = {'Date': [],
             'Zero Rates': [],
             'Forward Rates': [],
             'Discount Factors': []}

for dt in curve.dates():
    node_data['Date'].append(dt)
    node_data['Zero Rates'].append(curve.zeroRate(dt, day_count, ql.Annual).rate())
    node_data['Forward Rates'].append(curve.forwardRate(dt, dt + ql.Period(1, ql.Years), day_count, ql.Annual).rate())
    node_data['Discount Factors'].append(curve.discount(dt))

node_dataframe = pd.DataFrame(node_data)

print(node_dataframe)

node_dataframe.to_excel('NodeRates.xlsx')

# Printing Daily Zero Rates:
# Prints the daily zero rates
# It calculates and prints the zero rates for each year using the constructed yield curve.
maturity_date = calendar.advance(today, ql.Period(1, ql.Years))
current_date = today
while current_date <= maturity_date:
    zero_rate = curve.zeroRate(current_date, day_count, ql.Annual).rate()
    print(f"Date: {current_date}, Zero Rate: {zero_rate}")
    current_date = calendar.advance(current_date, ql.Period(1, ql.Years))

# Creating Curve Data for Plotting:
# Creates lists of curve dates, zero rates, and forward rates for plotting.
# It calculates both zero rates and forward rates for each year up to 15 years from the current date.
curve_dates = [today + ql.Period(i, ql.Years)
               for i in range(15)]
curve_zero_rates = [curve.zeroRate(date, day_count, ql.Annual).rate()
                    for date in curve_dates]

# Converting ql.Date to Numerical Values: (years from today)
# Converts the curve dates (ql.Date objects) to numerical values representing years from the current
# date. This is done to prepare the data for plotting on the x-axis.
numeric_dates = [(date - today) / 365 for date in curve_dates]

# Plotting:
# Creates a plot showing the zero rates and forward rates over time.
# The x-axis represents the years from the current date, and the y-axis represents the interest rates.
# The plot displays two lines: one for zero rates (blue) and another for forward rates (red).
# The plot is labeled, grid lines are added, and the visualization is displayed using
plt.figure(figsize=(10, 6))
plt.plot(numeric_dates, curve_zero_rates, marker='', linestyle='-', color='b', label='Zero Rates')
plt.title('Zero Rates')
plt.xlabel('Years from Today')
plt.ylabel('Rate')
plt.legend()
plt.grid(True)
plt.xticks(rotation=0)
plt.tight_layout()

plt.show()

tenors = ['3M', '6M', '9M', '1Y', '2Y', '3Y', '5Y', '7Y', '10Y', '15Y']

# Print the Zero Rates, Forward Rates, and Discount Factors at Instrument maturity dates
node_data = {'Maturity Date': [],
             'Tenors': [],
             'Zero Rates': [],
             'Forward Rates': [],
             'Discount Factors': []}

for tenor in tenors:
    maturity_date = calendar.advance(today, ql.Period(tenor), ql.ModifiedFollowing)  # Calculate the maturity date
    node_data['Maturity Date'].append(maturity_date)
    node_data['Tenors'].append(tenor)
    node_data['Zero Rates'].append(curve.zeroRate(maturity_date, day_count, ql.Annual).rate())
    node_data['Forward Rates'].append(curve.forwardRate(maturity_date, maturity_date + ql.Period(0, ql.Years), day_count, ql.Annual).rate())
    node_data['Discount Factors'].append(curve.discount(maturity_date))

node_dataframe = pd.DataFrame(node_data)

print(node_dataframe)

node_dataframe.to_excel('NodeRates.xlsx')

# Create a DataFrame to store bond results
bond_results = {'Issue Date': [],
                'Maturity Date': [],
                'Coupon Rate': [],
                'Price': [],
                'Settlement Days': [],
                'Yield': [],
                'Clean Price': [],
                'Dirty Price': []}

# Calculate bond prices and yields
for issue_date, maturity, coupon, price, settlement_days in data:
    price = ql.QuoteHandle(ql.SimpleQuote(price))
    issue_date = ql.Date(issue_date, '%d-%m-%Y')
    maturity = ql.Date(maturity, '%d-%m-%Y')
    schedule = ql.MakeSchedule(issue_date, maturity, ql.Period(ql.Semiannual))
    bondEngine = ql.DiscountingBondEngine(curve)
    bond = ql.FixedRateBond(settlement_days, faceAmount, schedule, [coupon / 100], day_count)
    bond.setPricingEngine(bondEngine)

    # Calculate bond yield, clean price, and dirty price
    bondYield = bond.bondYield()
    bondCleanPrice = bond.cleanPrice()
    bondDirtyPrice = bond.dirtyPrice()

    # Append the results to the DataFrame
    bond_results['Issue Date'].append(issue_date)
    bond_results['Maturity Date'].append(maturity)
    bond_results['Coupon Rate'].append(coupon)
    bond_results['Price'].append(price.value())
    bond_results['Settlement Days'].append(settlement_days)
    bond_results['Yield'].append(bondYield)
    bond_results['Clean Price'].append(bondCleanPrice)
    bond_results['Dirty Price'].append(bondDirtyPrice)

# Create a DataFrame from the bond results
bond_results_df = pd.DataFrame(bond_results)

# Print the results
print(bond_results_df)
python finance quantitative-finance quantlib
1个回答
0
投票

您忘记为要传递的曲线创建一个 YieldTermStructureHandle DisoutningBondEngine。就像在某处添加以下行一样简单 在 for 循环之前

curveHandle = ql.YieldTermStructureHandle(curve)

然后像这样调用DiscountingEngine:

bondEngine = ql.DiscountingBondEngine(curveHandle)

你还缺少bondYield的相关参数,你 可能想要

bondYield = bond.bondYield(day_count, ql.Compounded, ql.Annual)
之类的东西,或者通过外部获得的干净价格。 哟

© www.soinside.com 2019 - 2024. All rights reserved.