Reconciling QuantLib and Bloomberg Black Option Prices and Greeks
Summary
This discussion explains why a QuantLib Black calculation for a Treasury futures option can appear to disagree with Bloomberg on price and gamma. The accepted answer attributes the apparent mismatch to quote conventions and Greek settings: Bloomberg may show gamma for a one-percent underlying move, while QuantLib reports a different scaling. It also distinguishes the displayed option price from total contract value and from price expressed relative to the underlying.
The answer describes checking a listed option in Bloomberg’s OTC pricer, matching the gamma bump convention, and accounting for fractional days to expiry. It reports that after aligning inputs and quotation units, the calculated values are close. It also notes that the example uses a standard Black calculator rather than an American-option PDE engine, and that theta conventions can differ, especially near expiry. The comparison depends on the particular contract, screen settings, and market quotation; the figures and workflow are illustrative rather than a general guarantee that the two platforms will always match.
Key ideas
- Greek comparisons require matching the size and units of the underlying price bump used for gamma.
- An option’s displayed quote, total contract value, and value relative to the underlying are distinct quantities.
- Bloomberg’s listed-option pricing mode can help compare model values with exchange quotations.
- Fractional days to expiry and theta conventions can materially affect short-dated option comparisons.
- The example uses a standard Black calculator and does not establish a general pricing difference between platforms.
Tags
Full text
# 65822
# Quantlib Black Model for Commodity Options (Interest Rate Options) is extremely light on gamma and price vs BBG, is model incorrect?
I am using the QuantLib developers example to try and price a TY option. The Delta is pretty close but the price and gamma are way off (almost by a factor of 2).
Am I using the model wrong or is the model wrong?
Here is the code
```
import QuantLib as ql
import math
calendar = ql.UnitedStates()
bussiness_convention = ql.ModifiedFollowing
settlement_days = 0
day_count = ql.ActualActual()
interest_rate = 25/10000
calc_date = ql.Date(1,7,2021)
yield_curve = ql.FlatForward(calc_date,
interest_rate,
day_count,
ql.Compounded,
ql.Continuous)
ql.Settings.instance().evaluationDate = calc_date
option_maturity_date = ql.Date(23,7,2021)
strike = 133
spot = 132.40625 # futures price
volatility = 3.896/100
flavor = ql.Option.Call
discount = yield_curve.discount(option_maturity_date)
strikepayoff = ql.PlainVanillaPayoff(flavor, strike)
T = yield_curve.dayCounter().yearFraction(calc_date,
option_maturity_date)
stddev = volatility*math.sqrt(T)
black = ql.BlackCalculator(strikepayoff,
spot,
stddev,
discount)
print("Option Price: " + str(black.value() ))
print("Delta: " + str(black.delta(spot) ))
print("Gamma: " + str(black.gamma(spot) ))
print("Theta: "+ str(black.theta(spot, T) ))
print("Vega: "+ str(black.vega(T) ))
```
and the output
| Category | Value |
| Option Price | 0.2638741114188638 |
| Delta | 0.3216355274081426 |
| Gamma | 0.28294608317127584 |
| Theta | -3.7640249885989223 |
| Vega | 11.648484397370504 |
and here is the screenshot of BBG
## Answer by AKdemy (score 4, accepted)
https://quant.stackexchange.com/a/65827
Short answer:
- Gamma is computed differently;
- price is quoted by the exchange in a way QuantLib does not compute
Long answer: BBG's DES page computes Gamma as 1% chg in underlying - there is also no flexibility with the DES page and frequently this is not the best calc they offer.
However you can load any listed option in their OTC pricers to get `listed` mode. `TYQ1C 133.00 COMB Comdty OVME` loads the ticker (next to the underlying). You compute it the "wrong" way around. This ticker is quoted in price (see `OMON` or `HP)`- so IVOL is a result, not an input. Price (share) will be color coded as it uses listed price.
In terms of Gamma - click on Settings (in OVME) - User Settings - Pricing - Greeks section - Gamma - set to `1 unit underly chg` and you get ~27. On the same page, you may see `fraction of days` ticked. So expiry is in minutes not full days (and its only 21 left). I think the API fields (DES) do that too, but generally BBG is stronger with OV pricers and MARS than this `FLDS` API stuff (but is very close here, so should be fine).
I cannot comment on quantlib, but is this really a PDE solver? That is an American option. The code `ql.PlainVanillaPayoff` makes me wonder if that is not simply standard Black? I may be wrong and am too lazy to try on my end now. In any case, PDE solvers are not trivial and will impose some differences.
Edit
Thanks @mmencke. Actually did not see you referenced the qlib documentation anyways Danny. It shows it is standard Black. That said, with this contract - there is little to no difference theoretically. You could hack a BS American pricer (if you have one) by including an artificial dividend equal to r and using the future price as the underlying price.
I honestly did not look at this properly and just quickly responded as I knew the gamma setting and that price is a market quote. I tried in OVME now and it is essentially identical. While all of the above still applies, understanding the quotation of these is the tricky part and not something qlib cares about. It is just Black after all (and has no reference to what contract this is). Technically there is also the distinction between price and yield vol but BBG offers only price vol for TYA which coincides with Black. You can have a look at `EDA Cmdty` on `OVDV` and `OVME` to see yield vol, both in lognormal and normal space.
Quotation: Shares displayed in OVME are the value of 1 point. The price quote is in points and fractions of points with par on the basis of 100 points. In your screenshot, the price is `0'17` and Tick Value is USD 15.625. Hence, what you see on OVME for the quoted price on that day is
- Price (Share): 00'17 (what is quoted)
- Price (Total): Price (Share)*Tick Value = 281.25
- Price (%): Price (Total) per share / Underlying Price => $(281.25/1000)/132-13 =0.002124$
What qlib displays is actually neither of this. It is Price (Total) per share = $263.9/1000 = 0.2639$ in the screenshot below. I was manually overriding OVME to use your inputs. Hence price is no longer 00'17 but 00'16 7/8 (it now solves for price like in your example). The screenshot on the right uses a higher notional, so that you see the exact decimals - and how close the two are $236895.16/1000000=0.26389516$.
Now essentially everything matches.
For the rest, Vega is just scaling and Theta is most certainly not textbook theta in Bloomberg. It is customary to compute theta as true one-day theta (kind of bump and re-price by decreasing time to expiry , keeping all else equal) because textbook theta can exceed the actual market value of an option if the time to expiry is short, as shown in this answer.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.