Saturday, April 05, 2014

Quantlib and Python - Putting Fingers to Keyboard

[Read the previous part in this series here]

You want to be an ueber powerful super hero capable of all sorts of impossible feats; then again don't you want to lead a simple life away from all the complexities of having rubbery hands and being able to become invisible?

No wonder super heroes resort to having those Clarke Kent and Bruce Wayne alter egos.

[As an aside, that reminds me of the age old question - would you rather be able to fly or turn invisible?]

Every designer has to ask himself this.  Not whether he wants to fly or not but do we want to do a few things well or be a super duper Swiss Army knife?

Quantlib (most of the time) comes down on the Swiss Army side of the argument; which means it's hard to learn; but also, once mastered, you will have those financial super powers at the touch of your finger tips. That's the hope!

Dates are a good starting point.  Almost everything non trivial in finance involves specific future payoffs.  Actually when I say non trivial I mean in some way tractable; the really hard stuff doesn't have specific future payments is left untouched.

In any case let's drop into Python's interactive interpreter


and create a few date objects

>>> from QuantLib import *
>>> valuationDate = Date(13,1,2014) 
>>> expiryDate = Date(13,1,2015)

Now tell the system what the valuation date is

>>> Settings.instance().evaluationDate = 

Finance is obsessed by time.  And of course money.  The cost of money over time is naturally represented by discount factors and on a day to day basis these prices are quoted as interest rates.

The following code sets an interest rate of 1% and tells the system that the price of money is constant over time.  The actual actual day count convention makes sure every calendar is accounted for when accruing payment IOUs (i.e. no short cut conventions are made in assuming 30 days in a month and 360 days a year).

>>> interestRate = 0.01
>>> riskFreeRate = FlatForward(valuationDate, interestRate, ActualActual() )

We can do the same for dividends.

>>> dividendRate = 0.02
>>> dividendYield = FlatForward(valuationDate, dividendRate, ActualActual() )

By the way if you want decent dividend predictions, check out

Any financial asset with non-linear payoffs (it turns out almost everything) needs to account for volatility.  We will setup our volatility data in a very similar manner.

>>> calendar = UnitedStates()
>>> volRate = 0.03 
>>> volatility = BlackConstantVol(valuationDate, calendar, volRate, ActualActual())

As an aside, QuantLib's calendars are very useful (at the risk of being monotonous - finance is obsessed by time! : )).

I am unsure why volatility requires calendar information whereas flat forwards does not.  Let me know in the comments if you can enlighten me.

The last piece of data to setup is an underlying equity price of 123

>>> underlying = SimpleQuote(123)

As you can see, pretty much everything needed to be an object in QuantLib.  Every.  Single.  Thing.

Hardcore abstraction may well give you super powers, but also means there's a high barrier to entry.

No prizes for what we are going to model next.  We need to specify the payoff conditions for our European equity call option with a strike of 100

>>> exercise = EuropeanExercise(expiryDate)  
>>> strikePrice = 100
>>> payoff = PlainVanillaPayoff(Option.Call, strikePrice)

and roll those terms together into an option object

>>> option = VanillaOption(payoff,  exercise)

Now bundle the market data together

>>> u = QuoteHandle(underlying) 
>>> d = YieldTermStructureHandle(dividendYield)
>>> r = YieldTermStructureHandle(riskFreeRate)
>>> v = BlackVolTermStructureHandle(volatility)  
>>> process = BlackScholesMertonProcess( u,d,r,v)

Things are getting a little convoluted now with the handle objects, eh?

Finally we set the pricing engine.

>>> engine = AnalyticEuropeanEngine(process)
>>> option.setPricingEngine(engine)

Let's price and see a result

>>> option.NPV()

Now we start to tangibly benefit from the object oriented-ness.  We can swap pricing engines in and out to our heart's content.  For example, why stick with bog standard Black Scholes when we could use something which sounds much fancier?

In any case, we will wrap up by calculating some Greeks

>>> option.gamma()
>>> option.vega()
>>> option.theta() 
>>> option.rho()

If you missed it, QuantLib is a pretty verbose convoluted affair.

Rest assured as with intelligent design or creationism everything is done for a reason and after overcoming all of these obstacles you will become a finance quant prophet amongst men.

[Next part is here]

1 comment:

John Orford said...

Luigi on the QuantLib mailing list suggested that requiring calendar information for the volatility curve might be redundant and due a clean up