0

I'm trying to use extrapolation to get data for some missing numbers and am really struggling.

Below is some options data with the strike price as the index and the volatility as MidVol. What I'm trying to do is find the MidVol for various strikes that aren't listed, such as the 2000.0, 3000.0 or the 30000.0 or 40000.0.

         MidVol    CallDelta PutDelta
4000.0   0.757832  0.910918 -0.089082
5000.0   0.739650  0.844523 -0.155477
6000.0   0.742915  0.766228 -0.233772
7000.0   0.733530  0.685637 -0.314363
8000.0   0.753219  0.610900 -0.389100
9000.0   0.750366  0.539006 -0.460994
10000.0  0.756793  0.476428 -0.523572
11000.0  0.774761  0.426470 -0.573530
12000.0  0.781004  0.379058 -0.620942
14000.0  0.795634  0.303317 -0.696683
16000.0  0.812305  0.247911 -0.752089
18000.0  0.831367  0.207874 -0.792126
20000.0  0.852848  0.179159 -0.820841

I have used both poly1d and interp1d to draw a curve for the current data, and as interp1d is the only one that seems to have an extrapolation feature you'd think that would be a good one to use. The code I have for that curve is:

curve = interp1d(df.index, df['MidVol'], kind='cubic', fill_value='extrapolate')

And then would use the following code to calculate the missing strikes:

missing = [20000, 22000,24000,26000,28000,30000]
extrap = [f(x).item() for x in sample]

However, when I then try to extrapolate out and get data for point that aren't in the df I get this joke of a response:

enter image description here

Firstly, does anyone know why the extrapolation is failing miserably? The 30000.0 strike should have a MidVol of around 0.95.

I have since stumbled across scipy.splev which actually fits the data even better than interp1d in my opinion. And the code I use for that is:

ipo = spi.splrep(df.index, df['MidVol'], k=5, s=6)
iy = spi.splev(df.index, ipo)

I also noticed that there was a ext variable in the documentation which says if ext=0, return the extrapolated value.. Does this mean I can use this to extrapolate out? If so can any one explain how I do that in a similar manner to how I do it above with missing = [20000, 22000,24000,26000,28000,30000] and then calculate the MidVol for each missing strike?

If anyone can shed light on either of my problems (why interp1d doesn't extrapolate properly or how to extrapolate with splev) I'd really appreciate it.

top bantz
  • 585
  • 1
  • 12
  • 29
  • 1
    *"Firstly, does anyone know why the extrapolation is failing miserably?"* You used the argument `kind='quadratic'`, and those extrapolated curves look like parabolas, as you requested! – Warren Weckesser Dec 30 '19 at 12:42
  • Oh sorry fair enough, it was from an answer I got from here and the resulting graph looked exactly what I wanted. I changed to 'cubic' and the graph is even worse. Is there another 'kind' I should be using? – top bantz Dec 30 '19 at 13:43

1 Answers1

0

You can somewhat control the extrapolation mode with make_interp_spline or CubicSpline bc_type parameter. E.g. you can force a linear extrapolation with bc_type="natural".

ev-br
  • 24,968
  • 9
  • 65
  • 78