Discount vs forward estimation curve
The YieldTermStructureHandle
passed to BlackCapFloorEngine
corresponds to the discount curve, while the one passed to IborIndex
corresponds to the forward estimation curve
In the example you are referring two, it turns out both are identical, but you could very well define two different handles on two different curves, as follows:
disc_term_structure = ql.ZeroCurve(disc_dates, disc_zero_rates, ...)
disc_ts_handle = ql.YieldTermStructureHandle(disc_term_structure)
engine = ql.BlackCapFloorEngine(disc_ts_handle, vols)
Bachelier pricing engine
As for your second question, there is a BachelierCapFloorEngine
class in QuantLib, see here:
https://github.com/lballabio/QuantLib/blob/master/ql/pricingengines/capfloor/bacheliercapfloorengine.hpp
and it is exposed in Python (I am using QuantLib 1.16). You could for example, replace the Black engine instanciation with this line in Goutham's example:
engine = ql.BachelierCapFloorEngine(disc_ts_handle, ql.QuoteHandle(ql.SimpleQuote(0.03))