Skip to content
All library documents

Fixing Negative Probabilities in QuantLib Option Pricing

Article Quant Q&A · Author: Suraj Sareen

Summary

The document describes a QuantLib American option pricing error that occurs for a deep out-of-the-money call. The accepted answer identifies a likely input-unit problem: the volatility appears to have been supplied as 57.829 rather than as a decimal representing 57.829 percent. Since pricing libraries generally expect volatility in decimal form, the misplaced scale can produce invalid intermediate values, including a negative probability error.

The answer also offers small date-handling conveniences for QuantLib, such as obtaining the current date from the library and parsing a date from a formatted string. The diagnosis is based on the sample input shown in the question, so it is not a general explanation of every negative-probability error. The key practical lesson is to check units and input conventions before changing the pricing engine or its numerical settings. The document does not provide a broader comparison of American option engines or independent validation of the proposed diagnosis.

Key ideas

  • QuantLib volatility inputs should be checked for the expected decimal convention.
  • A percentage entered as a whole number can cause invalid calculations in an option pricer.
  • An error appearing during net present value calculation can originate from an earlier input-unit mismatch.
  • QuantLib includes utilities for obtaining the current date and parsing formatted date strings.
  • The diagnosis applies to the displayed example and does not explain every negative-probability error.

Tags

Full text
# QuantLib Error "=negative probability"


# QuantLib Error "=negative probability"












I am trying to calculate the price of an american option. The code works fine for some options but for an deep out of the money call, I get the above error. Below is my code that I am trying to run.

I am new to QuantLib so any pointers to resolve the issue, will be of great help. I see the error comes at the very last statement when calculating the NPV, but not sure how to resolve, if I need to tweak anything in my code?

```
def calc_scn_price(p_und_price,p_strike,p_imp_vol,p_op_type,p_exp_date,p_und_bbg_tckr,p_div_yield):
```

t_date = dt.datetime.today() day_count = ql.Actual365Fixed() calendar = ql.UnitedStates() calculation_date = ql.Date(t_date.day,t_date.month,t_date.year)

```
    #print("Input to pricer :::",800,' Strike: ',1600.0,' Implied Vol: ',57.82902561325027,' Option Type: ','Call'," Exp Date: ","2021-09-17 00:00:00"," Underlier Ticker: ","TSLA US Equity")

    # Settings for evaluation
    ql.Settings.instance().evaluationDate = calculation_date
    # Risk free rate
    v_rfr = 0.0169
    v_matur_dt = ql.Date(p_exp_date.day, p_exp_date.month, p_exp_date.year)
    # Option Type
    if p_op_type == 'Call':
        v_op_type = ql.Option.Call
    elif p_op_type == 'Put':
        v_op_type = ql.Option.Put
    else:
        raise ValueError("Option Type must be only Call or Put")

    # Setup the option
    payoff = ql.PlainVanillaPayoff(v_op_type, float(p_strike))
    settlement = calculation_date  # Assume the transaction happens today since it is an American option
    am_excercise = ql.AmericanExercise(settlement, v_matur_dt)
    american_option = ql.VanillaOption(payoff, am_excercise)

    # ***********Setup Black Scholes Process*********#
    S = ql.QuoteHandle(ql.SimpleQuote(p_und_price))  # Underlier Spot Price
    r = ql.YieldTermStructureHandle(ql.FlatForward(calculation_date, v_rfr, day_count))  # Risk free rate
    v_div_yield = p_div_yield
    #v_bbg = blp.bdp(tickers=p_und_bbg_tckr, flds=['PX_LAST','EQY_DVD_YLD_IND'])

    #print("Here \n",v_bbg,p_und_bbg_tckr,v_bbg['px_last'].tolist()[0])

    # dividend yield - fetch from bbg
    #print(v_div_yield)

    dividend_yield = ql.YieldTermStructureHandle(ql.FlatForward(calculation_date, float(v_div_yield), day_count))

    sigma = ql.BlackVolTermStructureHandle(
        ql.BlackConstantVol(calculation_date, calendar, p_imp_vol, day_count))
    bsm_process = ql.BlackScholesMertonProcess(S, dividend_yield, r, sigma)

    # Use derived implied vol to calculate scenario Option price
    am_steps = 800

    # Run the engine
    binomial_engine = ql.BinomialVanillaEngine(bsm_process, "crr", am_steps)

    american_option.setPricingEngine(binomial_engine)
    v_op_price = american_option.NPV()

    #print(v_op_price)

    return v_op_price
```

## Answer by David Duarte (score 2, accepted)

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

Assuming you are using the inputs from this line:

```
#print("Input to pricer :::",800,' Strike: ',1600.0,' Implied Vol: ',57.82902561325027,' Option Type: ','Call'," Exp Date: ","2021-09-17 00:00:00"," Underlier Ticker: ","TSLA US Equity")
```

it seems you are using the volatility wrong, because your input should be 0.578290, which is 57.8290%, and not 57.829025613.

Additionally, as tips, QuantLib can:

- Get today's date: `ql.Date().todaysDate()`

- Parse dates from strings (ex: BBG dates): `ql.Date('27-02-2020', '%d-%m-%Y')`

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.