Quantlib: Bond with both callable and puttable options - quantlib

I am trying to use quantlib to price a bond with both callable and puttable options. I have seen examples for pricing callable bonds using ql.CallabilitySchedule(). I would like to ask how to include dates and strike prices for both put and call options in ql.CallabilitySchedule().
Thanks.

As a disclaimer, I haven't tried this myself but if you look at example, where I am reposting below the relevant part:
putCallSchedule.append(
ql.Callability(callability_price, ql.Callability.Call, ql.Date(15,6,2021))
)
The 2nd argument to the ql.Callability is the Type which can be either Call or Put. Therefore, try adding your Put days using ql.Callability.Put instead of ql.Callability.Call.

Related

Matched-maturity vanilla swap in Quantlib

Firstly apologies if this has been answered elsewhere.
I am using QuantLib (via Excel) to build a "standard" bond pricing sheet: prices, yields, spline AND matched-maturity ASW.
I can price the bonds, and have successfully built a forecast (Euribor) and discount (EONIA) curve. I can use qlMakeVanillaSwap() to define a spot-start swap by tenor (eg "1y","2Y" etc) and it works fine. However I am struggling to define a "broken date" swap, ie one which starts T+2 and ends on a given date (and so usually has a short stub on the first payment), to match the bond maturity. All the examples I can find have integer year tenors.
I would be grateful if someone could point me to the right method (can be in python, C++ or Excel). Or do I have to go down the route of creating explicit fixed and floating rate schedules for the swaps?
The answer seems to be: Yes, I do have to create explicit fixed and floating rate schedules, using qlSchedule(), but it turns out to be not too onerous. NB. I am pricing a vanilla EUR ABB vs 6m Euribor swap.
As for pricing, it seems the qlMakeVanillaSwap() is doing a few helpful things in one call, but only IF your swap has a whole-period tenor (eg "1y"). I found the answer for what I wanted to do in the example sheet that came with the QuantLibXL download package.
The other thing that qlMakeVanillaSwap() is doing (in addition to creating the schedules) is setting the Pricing Engine (which is used to discount the cashflows). In the longer version you have to (a) set it yourself using qlInstrumentSetPricingEngine() and (b) pass the result of that call to the Trigger parameter of qlVanillaSwapFairRate(), to establish the calculation order.

What are hp.Discrete and hp.Realinterval? Can I include more values in hp.realinterval instead of just 2?

I am using Hyperparameter using HParams Dashboard in Tensorflow 2.0-beta0 as suggested here https://www.tensorflow.org/tensorboard/r2/hyperparameter_tuning_with_hparams
I am confused in step 1, I could not find any better explanation. My questions are related to following lines:
HP_NUM_UNITS = hp.HParam('num_units', hp.Discrete([16, 32]))
HP_DROPOUT = hp.HParam('dropout', hp.RealInterval(0.1, 0.2))
HP_OPTIMIZER = hp.HParam('optimizer', hp.Discrete(['adam', 'sgd']))
My question:
I want to try more dropout values instead of just two (0.1 and 0.2). If I write more values in it then it throws an error- 'maximum 2 arguments can be given'. I tried to look for documentation but could not find anything like from where these hp.Discrete and hp.RealInterval functions came.
Any help would be appreciated. Thank you!
Good question. They notebook tutorial lacks in many aspects. At any rate, here is how you do it at a certain resolution res
for dropout_rate in tf.linspace(
HP_DROPOUT.domain.min_value,
HP_DROPOUT.domain.max_value,
res,):
By looking at the implementation to me it really doesn't seem to be GridSearch but MonteCarlo/Random search (note: this is not 100% correct, please see my edit below)
So on every iteration a random float of that real interval is chosen
If you want GridSearch behavior just use "Discrete". That way you can even mix and match GridSearch with Random search, pretty cool!
Edit: 27th of July '22: (based on the comment of #dpoiesz)
Just to make it a little more clear, as it is sampled from the intervals, concrete values are returned. Therefore, those are added to the grid dimension and grid search is performed using those
RealInterval is a min, max tuple in which the hparam will pick a number up.
Here a link to the implementation for better understanding.
The thing is that as it is currently implemented it does not seems to have any difference in between the two except if you call the sample_uniform method.
Note that tf.linspace breaks the mentioned sample code when saving current value.
See https://github.com/tensorflow/tensorboard/issues/2348
In particular OscarVanL's comment about his quick&dirty workaround.

clean or dirty price for FixedRateBondHelper

I would like to construct a spot curve from supplied bond prices. I know that the curve has to be constructed from dirty prices (i.e. the ones that include accrued interest). However, from FittedBondCurve.cpp example posted on quantlib.org, it appears that FixedRateBondHelper class is initialized with clean prices.
So, my question is: does it mean that FixedRateBondHelper takes care of computing accrued interest and converting clean price to dirty price? Or is it something that a user should do? I believe it's the former but wanted to make sure.
The helper doesn't, but the fitting algorithm does. If you look at the FittedBondDiscountCurve::FittingMethod::FittingCost::value method, you'll cringe a bit at the nested inner classes, but then you'll see that the model price is calculated by adding the discounted future cash flows and subtracting the accrued amount.
A further note: in recent releases, the bond helpers have been given the possibility to work with quoted dirty prices when bootstrapping a curve (see the last parameter of their constructors, useCleanPrice, which defaults to true but can be set to false to use dirty prices. However, the FittedBondDiscountCurve class is not yet aware of this change, and thus setting useCleanPrice to false would break the algorithm. I'll try to fix this in a future release.

Google Spreadsheets - IF with more that three arguments

I'm currently working an a very simple project management template.
The Idea is that after entering a start and end-date columns will show up as a very simplistic gantt chart (conditional formating).
Everything works fine, until "year" comes into consideration. Since it is a several years lasting project and we work with calenderweeks it is essential that the work package is only visualized in its specific year.
So I came up with the following (rough'n'dirty) formular (example from cell K3):
=and(if(K$2>=$F3;1;0);if(K$2<=$H3;1;0);if(or(right($E3;4)=K$1;1);(right(G3;4)=K1;1;0)))
This is the document: https://docs.google.com/spreadsheets/d/15F1uBnoHMuJqc_w0X04U5-ZCQ_6mgO_HJqvN5U28cog/edit?usp=sharing
Problem: GoogleSpreadsheets only alows three arguments with IF. But I do not know how to structure it otherwise...
Thankful for any suggestion!
Cheers,
Matt
This might be what you are looking for, ties the start week/ end week and year together for comparison.
=IF(AND(
(K$1&TEXT(K$2;"00")) >=(RIGHT($E$3;4)&TEXT($F$3;"00"));
(K$1&TEXT(K$2;"00")) <=(RIGHT($G$3;4)&TEXT($H$3;"00")))
;1;0)

Swaption pricing in QuantLib

I posted this on Wilmott too, wasn't sure which would get more of a response.
I'm relatively new to the world of Quantlib (and C++ . . .), so perhaps this is quite obvious. I'm trying to figure out if Quantlib can price forward premium vanilla swaptions (OIS discounting, 3mL curve for estimation). All I can see in Quantlib in the Swaption files are inputs for one term structure for discounting. Does it use this also for estimation? Or is there a way to override it, such that I can enter two curves.
Any help, examples etc would be much appreciated (and would save me a lot of time staring at the same files hoping something jumps out at me...)!
Thanks a lot
It depends. If you want to price Bermudan swaptions, you're out of luck; QuantLib can only price them on a tree and there's no way to use the two curves.
If you want to price European swaptions, you can use the two curves in the Black formula, although I agree that it's not obvious to find that out by looking at the code. As you've probably seen already, you'll have to instantiate both an instrument (the Swaption class) and a corresponding engine (the BlackSwaptionEngine class). The constructor of the BlackSwaptionEngine takes a discount curve besides the other args, so you'll pass the OIS curve here. The constructor of the Swaption, on the other hand, takes the swap underlying the option as a VanillaSwap instance. In turn, the VanillaSwap constructor takes an IborIndex instance representing the floating-rate index to be paid; and finally, the IborIndex constructor takes the curve to be used to forecast its fixings, so that's the place where you can pass the 3mL curve. To summarize:
shared_ptr<IborIndex> libor(new GBPLibor(3*Months, forecastCurve));
shared_ptr<VanillaSwap> swap(new VanillaSwap(..., libor, ...));
shared_ptr<Instrument> swaption(new Swaption(swap, ...));
shared_ptr<PricingEngine> engine(new BlackSwaptionEngine(discountCurve, ...));
swaption->setPricingEngine(engine);
double price = swaption->NPV();
Also, note that the current released version (QuantLib 1.1) has a bug that makes it use the wrong curve at some point during the calculations. You'll want to use version 1.2, which is not yet released but can be checked out from the Subversion repository at https://quantlib.svn.sourceforge.net/svnroot/quantlib/branches/R01020x-branch/QuantLib.