Skip to content
All library documents

Black and Bachelier Caplet Pricing Use Different Volatility Inputs

Article Quant Q&A · Author: Add

Summary

The document compares an attempted Black 76 caplet valuation with a Bachelier, or normal-model, implementation for an interest rate caplet. The central modeling distinction in the replies is that Black volatility is quoted as a relative, lognormal change, while Bachelier volatility is an absolute change in the rate. Thus, using the same numerical volatility in both models does not generally represent the same market assumption.

A second reply identifies a parenthesization issue in the Black d-plus calculation. The supplied Bachelier code also appears to use a cumulative normal probability where the normal density is needed in the volatility term, so the volatility-units observation alone does not make that implementation correct. The discussion gives no validated normal-model price, volatility conversion, or practical SABR implementation. It is a limited coding discussion, and the example’s inputs should not be treated as a market calibration.

Key ideas

  • Black 76 treats the forward rate as lognormal and uses relative volatility.
  • Bachelier models absolute rate changes, so its volatility input has different units and scale.
  • The Black implementation’s d-plus expression is flagged for a parenthesization correction.
  • The displayed Bachelier formula should be checked carefully because its volatility term appears to require the normal density.

Tags

Full text
# Black and Normal Model for Caplet using Python


# Black and Normal Model for Caplet using Python












I am able to Price Caplet using Black 76 model in Python. However, I am unable to price the same with Normal Model. Can anyone suggest what is missing ?

I am valuing caplet that caps interest rate on 10000 loan at 8% p.a. quarterly compounding for three months starting in one year.

The zero curve is flat at 6.9394% p.a. one year volatility is 20% p.a.

Also, If you can suggest best place to see practical SABR model implementation using python that would be great.

Code for Black in Python:

```
from scipy.stats import norm
import math

def black(F_0,y,expiry,vol,rfr,expiry_1,isCall):
    option_value = 0
    if expiry * vol == 0.0:
        if isCall:
            option_value = max(F_0 - y, 0.0)
        else:
            option_value = max(y - F_0 , 0.0)
    else:
        d1 = dPlusBlack(F_0 = F_0 , y = y, expiry = expiry ,vol = vol)
        d2 = dMinusBlack(F_0 = F_0 , y = y, expiry = expiry ,vol = vol)
        if isCall:
             option_value = (math.exp((-rfr)*expiry_1))*(F_0 * norm.cdf(d1) - y *norm.cdf(d2))
        else:
             option_value = (math.exp((-rfr)*expiry_1))*(y * norm.cdf(-d2) - F_0 *norm.cdf(-d1))
    return option_value
def dPlusBlack(F_0 , y, expiry , vol):
    d_plus = ((math.log(F_0 / y) + 0.5 * vol * vol * expiry)/ vol / math.sqrt(expiry))
    return d_plus
def dMinusBlack(F_0 , y, expiry , vol):
    d_minus = (dPlusBlack(F_0 = F_0 , y = y, expiry = expiry ,vol = vol ) - vol * math.sqrt(expiry))
    return d_minus
a = black(0.07,0.08,1,0.20,0.069394,1.25,"isCall")
a = 0.0020646470930435683
```

Code for bachelier

```
from scipy.stats import norm
import math

def bachelier(F_0,y,expiry,vol,rfr,expiry_1,isCall):
    option_value = 0
    if expiry * vol == 0.0:
        if isCall:
            option_value = max(F_0 - y, 0.0)
        else:
            option_value = max(y - F_0 , 0.0)
    else:
        d1 = dPlusBachelier(F_0 = F_0 , y = y, expiry = expiry ,vol = vol)
        if isCall:
             option_value = (math.exp((-rfr)*expiry_1))*((F_0 - y)* norm.cdf(d1) + vol * math.sqrt(expiry) * norm.cdf(d1))
        else:
             option_value = (math.exp((-rfr)*expiry_1))*((y-F_0) * norm.cdf(-d1) + vol * math.sqrt(expiry) * norm.cdf(-d1))
    return option_value

def dPlusBachelier(F_0 , y, expiry , vol):
    d_plus = (F_0 - y)/ (vol * math.sqrt(expiry))
    return d_plus

a = bachelier(0.07,0.08,1,0.20,0.069394,1.25,"isCall")
```

## Answer by Kiann (score 5)

https://quant.stackexchange.com/a/44558

are you using the same volatility 20% for both black76 and Bachelier?

The black76 is a lognormal model, where volatilities are quoted as relative price changes. The bachelier/normal model quotes volatilities as absolute changes.

That might be what you're missing?

Kind regards

## Answer by Varun (score 0)

https://quant.stackexchange.com/a/46603

Sorry I am bit late to the party. Just saw your post while trying to write my own black model. I am going to the mistake is a typo in dplus

```
d_plus = ((math.log(F_0 / y) + 0.5 * vol * vol * expiry)/ vol / math.sqrt(expiry))
```

Should be:

```
d_plus = ((math.log(F_0 / y) + 0.5 * vol * vol * expiry)/( vol * math.sqrt(expiry)))
```

Warm Regards, Varun

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.