|
From: Aleksis A. R. <ale...@go...> - 2023-11-27 09:15:35
|
i think you’re just missing a ql.YieldTermStuctureHandle() call on ur constructed curve. you can add that but then u’ll need to alter the dt in dates call to refer to the unhandled curve, and also specify some parameters in the bondyield call. Then the error will go away.
your code should run fine even without it.
> On Nov 27, 2023, at 8:38 AM, Quant <qua...@gm...> wrote:
>
> Hi QuantLib Users,
>
> I have data containing Bond information and I managed to use this information to bootstrap the zero curve. To check if my zero curve is correct, I would like to reprice the Bonds using the bootstrapped curve (using the zero curve) to get back to the quoted prices of the Bonds. I am getting the following errors on the repricing part and if anyone can help I would appreciate;
>
> 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 &'
>
> Find below the code that I am running;
>
> # 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)
>
> Thanks & regards,
> _______________________________________________
> QuantLib-users mailing list
> Qua...@li...
> https://lists.sourceforge.net/lists/listinfo/quantlib-users
|