0
$\begingroup$

I am trying to price Convertible bond with the following data:

  1. price = 5.11
  2. coupon = 0.0575
  3. frequency = semi-annual
  4. risk free rate = 0.02347
  5. conversion Ratio = 3.8095
  6. Conversion Price = 26.25
  7. volatility = 0.64
  8. principal = 100
  9. dividend yield = 0.0 10 time = 2.5 yrs
  10. credit spread = 0.9183
  11. value = 0.0
  12. N=5 #Number of time steps
  13. rates = [0.0107, 0.0136, 0.0145, 0.0202, 0.02347] #term structure
  14. call schedule = [103, 101.9, 101.9, 100.85, 100.85, 100]

The problem I am currently facing is to build callability schedule and term structure as I don't have the respective dates. I have taken some sample dates to finish the code and come up with a working solution. However, it will be great if I can have a working python code which doesn't use QuantLib library. Below is the code I have developed so far:

import QuantLib as ql

calculation_date = ql.Date(9,1,2004)
ql.Settings.instance().evaluationDate = calculation_date

redemption = 100.00
face_amount = 100.0
spot_price = 5.11
conversion_price = 26.25
conversion_ratio = 3.8095  # BBG quotes 38.4615; had to scale by a factor of 10

issue_date = ql.Date(15,3,2002)        
maturity_date = ql.Date(15,9,2004)

settlement_days = 2
calendar = ql.UnitedStates(ql.UnitedStates.GovernmentBond)
coupon = 0.0575
frequency = ql.Semiannual
tenor = ql.Period(frequency)

day_count = ql.Thirty360()
accrual_convention = ql.Unadjusted
payment_convention = ql.Unadjusted

call_dates = [ql.Date(15,9,2002)]
call_price = 103
put_dates = [ql.Date(15,3,2003), ql.Date(15,9,2003), ql.Date(15,3,2004)]
put_price = 100.0

# assumptions
dividend_yield = 0.0
credit_spread_rate = 0.9183
risk_free_rate = 0.02347
volatility = 0.64

callability_schedule = ql.CallabilitySchedule()


for call_date in call_dates:
   # callability_price  = ql.CallabilityPrice(call_price, 
   #                                          ql.CallabilityPrice.Clean)
   # call_price = [103, 101.9, 101.9, 100.85, 100.85, 100]
   callability_price  = ql.CallabilityPrice(call_price, 
                                          ql.CallabilityPrice.Clean)
   callability_schedule.append(ql.Callability(callability_price, 
                                       ql.Callability.Call,
                                       call_date)
                        )
    
for put_date in put_dates:
    puttability_price = ql.CallabilityPrice(put_price, 
                                            ql.CallabilityPrice.Clean)
    callability_schedule.append(ql.Callability(puttability_price,
                                               ql.Callability.Put,
                                               put_date))
    
dividend_schedule = ql.DividendSchedule() # No dividends
dividend_amount = dividend_yield*spot_price
next_dividend_date = ql.Date(15,9,2002)
dividend_amount = spot_price*dividend_yield
for i in range(5):
    date = calendar.advance(next_dividend_date, 1, ql.Years)
    dividend_schedule.append(
        ql.FixedDividend(dividend_amount, date)
    )

schedule = ql.Schedule(issue_date, maturity_date, tenor,
                       calendar, accrual_convention, accrual_convention,
                       ql.DateGeneration.Backward, False)

credit_spread_handle = ql.QuoteHandle(ql.SimpleQuote(credit_spread_rate))
exercise = ql.AmericanExercise(calculation_date, maturity_date)

convertible_bond = ql.ConvertibleFixedCouponBond(exercise,
                                                 conversion_ratio,
                                                 dividend_schedule,
                                                 callability_schedule, 
                                                 credit_spread_handle,
                                                 issue_date,
                                                 settlement_days,
                                                 [coupon],
                                                 day_count,
                                                 schedule,
                                                 redemption)

spot_price_handle = ql.QuoteHandle(ql.SimpleQuote(spot_price))
yield_ts_handle = ql.YieldTermStructureHandle(
    ql.FlatForward(calculation_date, risk_free_rate, day_count)
)

#Create the Yield Curve
dates = [ql.Date(15,3,2002),ql.Date(15,9,2002),ql.Date(15,3,2003),ql.Date(15,9,2003),ql.Date(15,3,2004), ql.Date(15,9,2004)]

rates = [0.0107,0.0136,0.0145,0.0202,0.02347, 0.0245]

ts = ql.ForwardCurve(dates, rates, day_count)
ts_handle = ql.YieldTermStructureHandle(ts)


dividend_ts_handle = ql.YieldTermStructureHandle(
    ql.FlatForward(calculation_date, dividend_yield, day_count)
)
volatility_ts_handle = ql.BlackVolTermStructureHandle(
    ql.BlackConstantVol(calculation_date, calendar,volatility, day_count)
)

bsm_process = ql.BlackScholesMertonProcess(spot_price_handle, 
                                           dividend_ts_handle,
                                           ts_handle,
                                           volatility_ts_handle)

time_steps = 5
engine = ql.BinomialConvertibleEngine(bsm_process, "crr", time_steps)

convertible_bond.setPricingEngine(engine)
print ("NPV ", convertible_bond.NPV())

$\endgroup$
1
$\begingroup$

I have recently released a Python financial library called FinancePy. It has a convertible bond model implementation. It is still in beta so may have some bugs but you are welcome to try it out. It also uses Numba so it is fast and you can look through to the actual Python code. The github is at

https://github.com/domokane/FinancePy

Here is an example notebook that prices a convertible bond.

https://github.com/domokane/FinancePy-Examples/blob/master/notebooks/BOND_CONVERTIBLE_ComparisonWithQLExample.ipynb

I am happy to be contacted directly if you find any issues. See my email at the github repository readme.

$\endgroup$
5
  • $\begingroup$ I have ran the code from FinancePy and it is working on my system. However, you have used the dates to create the term structure and that's the issue. I don't have the dates and need a work around to price the bond without dates. $\endgroup$ – Desi_Quant Sep 25 '20 at 10:38
  • $\begingroup$ If you don't have the dates, what term structure information do you have ? What are the terms of the rates you have provided above. And is it a 5 year bond ? $\endgroup$ – Dom Sep 25 '20 at 11:11
  • $\begingroup$ It is a 2.5 year bond. I have mentioned the inputs in the query above. $\endgroup$ – Desi_Quant Sep 25 '20 at 12:51
  • $\begingroup$ Thank you very much, Prof. O'kane, for sharing your very interesting-looking library! $\endgroup$ – Dimitri Vulis Sep 27 '20 at 13:02
  • $\begingroup$ OK. I deleted my post because of your rejection of the question. I am not familiar with the other libraries apart from QL and asking a question that made my library one of the answers might be seen as biased. Better if someone else does it. $\endgroup$ – Dom Sep 27 '20 at 13:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.