# Issue in Pricing Binary Options using Heaviside Function and QuantLib Python

I am trying to price binary option using MC Simulation and Python QuantLib Library. The price of the option matches with the Analytical Engine. However, I am not sure how to incorporate the Heaviside Function to calculate the payoff (1 if St > K; 0 otherwise). Here is the code for the same:

import QuantLib as ql
today = ql.Date().todaysDate()
initialValue = 40
riskFreeTS = ql.YieldTermStructureHandle(ql.FlatForward(today, 0.01, ql.Actual365Fixed()))
dividendTS = ql.YieldTermStructureHandle(ql.FlatForward(today, 0.02, ql.Actual365Fixed()))
volatility = ql.BlackVolTermStructureHandle(ql.BlackConstantVol(today, ql.NullCalendar(), 0.2, ql.Actual365Fixed()))

process = ql.BlackScholesMertonProcess(ql.QuoteHandle(ql.SimpleQuote(40)), riskFreeTS, dividendTS, volatility)
steps = 2
rng = "pseudorandom" # could use "lowdiscrepancy"
numPaths = 500000
option_type = ql.Option.Call
strike_price = 40

maturity_date = ql.Date(2, 4, 2021)
exercise = ql.EuropeanExercise(maturity_date)
payoff=ql.PlainVanillaPayoff(ql.Option.Call, strike_price)
binary_option = ql.VanillaOption(payoff, exercise)

engine = ql.MCEuropeanEngine(process, rng, steps, requiredSamples=numPaths)


# Run with Monte Carlo

binary_option.setPricingEngine(engine)
price = binary_option.NPV()
print("Monte Carlo Price: {}".format(price))


# Run with Analytic Engine

engine = ql.AnalyticEuropeanEngine(process)
binary_option.setPricingEngine(engine)
print("Analytic Price: {}".format(binary_option.NPV()))


The output is:

Monte Carlo Price: 2.5199444258975885

Analytic Price: 2.5135333959120034


You will need to change the payoff from:

payoff = ql.PlainVanillaPayoff(ql.Option.Call, strike_price)


to

payoff = ql.CashOrNothingPayoff(ql.Option.Call, strike_price, 1)

• It is showing the following error: runfile('C:/Users/nitin.kapai/Documents/Exam_v1/QuantLib Code/Binary_Options_MC_Simulation_QuantLib.py', wdir='C:/Users/nitin.kapai/Documents/Exam_v1/QuantLib Code') Traceback (most recent call last): File "C:\Users\nitin.kapai\Documents\Exam_v1\QuantLib Code\Binary_Options_MC_Simulation_QuantLib.py", line 34, in <module> price = binary_option.NPV() File "C:\Users\nitin.kapai\Anaconda3\lib\site-packages\QuantLib\QuantLib.py", line 9172, in NPV return _QuantLib.Instrument_NPV(self) RuntimeError: non-plain payoff given Sep 4, 2020 at 12:24
• I am adding my code to the "Answer Your Question" section Sep 4, 2020 at 12:26
import QuantLib as ql

today = ql.Date().todaysDate()

initialValue = 40

riskFreeTS = ql.YieldTermStructureHandle(ql.FlatForward(today, 0.01, ql.Actual365Fixed()))

dividendTS = ql.YieldTermStructureHandle(ql.FlatForward(today, 0.02, ql.Actual365Fixed()))

volatility = ql.BlackVolTermStructureHandle(ql.BlackConstantVol(today, ql.NullCalendar(), 0.2, ql.Actual365Fixed()))

process = ql.BlackScholesMertonProcess(ql.QuoteHandle(ql.SimpleQuote(40)), riskFreeTS, dividendTS, volatility)

steps = 2

rng = "pseudorandom" # could use "lowdiscrepancy"

numPaths = 500000

option_type = ql.Option.Call

strike_price = 40

maturity_date = ql.Date(2, 4, 2021)

exercise = ql.EuropeanExercise(maturity_date)

payoff = ql.CashOrNothingPayoff(ql.Option.Call, strike_price, 1)

binary_option = ql.VanillaOption(payoff, exercise)

engine = ql.MCEuropeanEngine(process, rng, steps, requiredSamples=numPaths)

#Run with Monte Carlo

binary_option.setPricingEngine(engine)

price = binary_option.NPV()

print("Monte Carlo Price: {}".format(price))

# Run with Analytic Engine

engine = ql.AnalyticEuropeanEngine(process)

binary_option.setPricingEngine(engine)

print("Analytic Price: {}".format(binary_option.NPV()))

• I initially started with this version of code where I used CashorNothingPayoff, but it was throwing an error. Then I used PlainVanillaPayoff which was getting compiled. Sep 4, 2020 at 12:38
• Hiya... so this is annoying. QL has an engine called ql.MCDigitalEngine which is what you need, but it's not available in the Python port yet. In the mean time, if you need a numerical pricer you could try the finite difference pricer again, which DOES work for digitals... try this (works for me and generates a price of 0.4793): #Run with FD tGrid, xGrid = 2000, 200 engine = ql.FdBlackScholesVanillaEngine(process, tGrid, xGrid) binary_option.setPricingEngine(engine) price = binary_option.NPV() print("FD Price: {}".format(price)) Sep 4, 2020 at 12:44
• Wow that code does not look good in comment format, but add some line breaks and it should work! Sep 4, 2020 at 12:44
• Yep that works! Thanks StackG!! Sep 4, 2020 at 12:50