to spline or not to spline, that is the question

Hello.. a question for the math geeks out there:

I'm trying to create a few functions to derive OTC options data, so for instance I have the strike at 3.2 with delta 0.55, the strike at 3.3 with delta 0.43, then I want to know what would be the theoretical strike of an option with delta of exactly 0.5

How to do it?

Currently, I'm trying to use splines, so I create one spline series for the strikes, one spline series for the deltas, and I match the position on the delta spline at the same interval on the strike spline

Now my question is: would that Is be mathematically sound?? Or should I instead try to derive the value via BSM equations?
 
Delta is the p1 in BSM, so it should be easy to solve the formula for any of the below vars, incl. K, since you already have all the required params, except the strike K.

Ie. in your said example just set p1=0.5 and solve the following for K:
C = S * exp(-q * t) * p1 - K * exp(-r * t) * p2

Just guessing... :-)
 
Last edited:
Hello.. a question for the math geeks out there:

I'm trying to create a few functions to derive OTC options data, so for instance I have the strike at 3.2 with delta 0.55, the strike at 3.3 with delta 0.43, then I want to know what would be the theoretical strike of an option with delta of exactly 0.5

How to do it?

Currently, I'm trying to use splines, so I create one spline series for the strikes, one spline series for the deltas, and I match the position on the delta spline at the same interval on the strike spline

Now my question is: would that Is be mathematically sound?? Or should I instead try to derive the value via BSM equations?

using 2 splines is probably "close enough", especially for options near the money

in your example you expect 0.5 delta strike to ~equal the underlying price right?

I like the idea of just using the BS formula like earth_imperator suggested, it's just that you'd have to have a vol surface to find the 'in between' volatilities (to find theoretical option prices, then calculate your deltas to query), but I'm pretty sure for 0.5 delta you can just assume the strike price will be the underlying price
 
using 2 splines is probably "close enough", especially for options near the money

in your example you expect 0.5 delta strike to ~equal the underlying price right?

I like the idea of just using the BS formula like earth_imperator suggested, it's just that you'd have to have a vol surface to find the 'in between' volatilities (to find theoretical option prices, then calculate your deltas to query), but I'm pretty sure for 0.5 delta you can just assume the strike price will be the underlying price
oh, sorry for being a dick here, but this is an important detail: the 0.5 delta strike is never the underlying price.
It moves further upwards the higher volatility and the more expensive the forward is.
 
let me clarify, if I had all the other parts of the puzzle, calculating the value of the strike at 0.5 delta would be easy peasy, but I don't have anything else. I just have the data from the option chain and I'm trying to infer all the elements of a strike in between

I could calibrate my pricing model on the option chain and derive the elements from my model parameters, however, doing this adaptation needs a lot of tweaks in my code (plus calibrating every time the distribution takes a lot of computing time).

I was looking for something faster, hence the splines, for which more or less I already have 90% of the code ready.

@CactusWren now you bring out the issue of having a vol surface.. but wouldn't that be exactly the same problem? I.E. the need to use some sort of interpolation to find the IV value of a strike in between?

@earth_imperator can you please elaborate on the bsearch method used in this way?
 
let me clarify, if I had all the other parts of the puzzle, calculating the value of the strike at 0.5 delta would be easy peasy, but I don't have anything else. I just have the data from the option chain and I'm trying to infer all the elements of a strike in between

I could calibrate my pricing model on the option chain and derive the elements from my model parameters, however, doing this adaptation needs a lot of tweaks in my code (plus calibrating every time the distribution takes a lot of computing time).

I was looking for something faster, hence the splines, for which more or less I already have 90% of the code ready.

@earth_imperator can you please elaborate on the bsearch method used in this way?

First take a look at the following test data, Is it the data you look for?
This one does not use bsearch yet. It's first to go sure that we both mean the same data result or method.
It uses Spot S=100, DTE=365 days, IV=30, and Delta from 0.95 down to 0.05 in steps of 0.05, and finds matching Strikes (K). Pr is the Premium for this parameter set --> ie. calls BSM.
In this Q&D test pgm it finds some more than needed, but this shall not be a problem.
Btw, here DividendYield (q) and EarningsYield (r) are not used, ie. both set to 0.0, but it is possible to use real values for them, if available.
Code:
test6_find_k_for_p1_aka_delta(S=100.0000, DTE=365.0000, IV=30.0000, Delta=0.9500, accuracy=0.003000):
Found: K=63.5000 C_Pr=37.1734 P_Pr=0.6734 : p1=0.9519 : C_delta=p1=0.9519 P_Delta=C_Delta-1=-0.0481
Found: K=63.7500 C_Pr=36.9452 P_Pr=0.6952 : p1=0.9506 : C_delta=p1=0.9506 P_Delta=C_Delta-1=-0.0494
Found: K=64.0000 C_Pr=36.7176 P_Pr=0.7176 : p1=0.9492 : C_delta=p1=0.9492 P_Delta=C_Delta-1=-0.0508
Found: K=64.2500 C_Pr=36.4905 P_Pr=0.7405 : p1=0.9479 : C_delta=p1=0.9479 P_Delta=C_Delta-1=-0.0521

test6_find_k_for_p1_aka_delta(S=100.0000, DTE=365.0000, IV=30.0000, Delta=0.9000, accuracy=0.003000):
Found: K=71.0000 C_Pr=30.5847 P_Pr=1.5847 : p1=0.9018 : C_delta=p1=0.9018 P_Delta=C_Delta-1=-0.0982
Found: K=71.2500 C_Pr=30.3752 P_Pr=1.6252 : p1=0.8997 : C_delta=p1=0.8997 P_Delta=C_Delta-1=-0.1003
Found: K=71.5000 C_Pr=30.1664 P_Pr=1.6664 : p1=0.8976 : C_delta=p1=0.8976 P_Delta=C_Delta-1=-0.1024

test6_find_k_for_p1_aka_delta(S=100.0000, DTE=365.0000, IV=30.0000, Delta=0.8500, accuracy=0.003000):
Found: K=76.5000 C_Pr=26.1513 P_Pr=2.6513 : p1=0.8515 : C_delta=p1=0.8515 P_Delta=C_Delta-1=-0.1485
Found: K=76.7500 C_Pr=25.9589 P_Pr=2.7089 : p1=0.8490 : C_delta=p1=0.8490 P_Delta=C_Delta-1=-0.1510

test6_find_k_for_p1_aka_delta(S=100.0000, DTE=365.0000, IV=30.0000, Delta=0.8000, accuracy=0.003000):
Found: K=81.2500 C_Pr=22.6407 P_Pr=3.8907 : p1=0.8001 : C_delta=p1=0.8001 P_Delta=C_Delta-1=-0.1999
Found: K=81.5000 C_Pr=22.4646 P_Pr=3.9646 : p1=0.7973 : C_delta=p1=0.7973 P_Delta=C_Delta-1=-0.2027

test6_find_k_for_p1_aka_delta(S=100.0000, DTE=365.0000, IV=30.0000, Delta=0.7500, accuracy=0.003000):
Found: K=85.2500 C_Pr=19.9305 P_Pr=5.1805 : p1=0.7524 : C_delta=p1=0.7524 P_Delta=C_Delta-1=-0.2476
Found: K=85.5000 C_Pr=19.7687 P_Pr=5.2687 : p1=0.7493 : C_delta=p1=0.7493 P_Delta=C_Delta-1=-0.2507

test6_find_k_for_p1_aka_delta(S=100.0000, DTE=365.0000, IV=30.0000, Delta=0.7000, accuracy=0.003000):
Found: K=89.2500 C_Pr=17.4518 P_Pr=6.7018 : p1=0.7016 : C_delta=p1=0.7016 P_Delta=C_Delta-1=-0.2984
Found: K=89.5000 C_Pr=17.3046 P_Pr=6.8046 : p1=0.6984 : C_delta=p1=0.6984 P_Delta=C_Delta-1=-0.3016

test6_find_k_for_p1_aka_delta(S=100.0000, DTE=365.0000, IV=30.0000, Delta=0.6500, accuracy=0.003000):
Found: K=93.0000 C_Pr=15.3385 P_Pr=8.3385 : p1=0.6524 : C_delta=p1=0.6524 P_Delta=C_Delta-1=-0.3476
Found: K=93.2500 C_Pr=15.2048 P_Pr=8.4548 : p1=0.6491 : C_delta=p1=0.6491 P_Delta=C_Delta-1=-0.3509

test6_find_k_for_p1_aka_delta(S=100.0000, DTE=365.0000, IV=30.0000, Delta=0.6000, accuracy=0.003000):
Found: K=96.7500 C_Pr=13.4253 P_Pr=10.1753 : p1=0.6026 : C_delta=p1=0.6026 P_Delta=C_Delta-1=-0.3974
Found: K=97.0000 C_Pr=13.3047 P_Pr=10.3047 : p1=0.5993 : C_delta=p1=0.5993 P_Delta=C_Delta-1=-0.4007

test6_find_k_for_p1_aka_delta(S=100.0000, DTE=365.0000, IV=30.0000, Delta=0.5500, accuracy=0.003000):
Found: K=100.7500 C_Pr=11.5969 P_Pr=12.3469 : p1=0.5498 : C_delta=p1=0.5498 P_Delta=C_Delta-1=-0.4502

test6_find_k_for_p1_aka_delta(S=100.0000, DTE=365.0000, IV=30.0000, Delta=0.5000, accuracy=0.003000):
Found: K=104.5000 C_Pr=10.0718 P_Pr=14.5718 : p1=0.5013 : C_delta=p1=0.5013 P_Delta=C_Delta-1=-0.4987
Found: K=104.7500 C_Pr=9.9764 P_Pr=14.7264 : p1=0.4981 : C_delta=p1=0.4981 P_Delta=C_Delta-1=-0.5019

test6_find_k_for_p1_aka_delta(S=100.0000, DTE=365.0000, IV=30.0000, Delta=0.4500, accuracy=0.003000):
Found: K=108.5000 C_Pr=8.6333 P_Pr=17.1333 : p1=0.4515 : C_delta=p1=0.4515 P_Delta=C_Delta-1=-0.5485
Found: K=108.7500 C_Pr=8.5496 P_Pr=17.2996 : p1=0.4484 : C_delta=p1=0.4484 P_Delta=C_Delta-1=-0.5516

test6_find_k_for_p1_aka_delta(S=100.0000, DTE=365.0000, IV=30.0000, Delta=0.4000, accuracy=0.003000):
Found: K=112.7500 C_Pr=7.3011 P_Pr=20.0511 : p1=0.4013 : C_delta=p1=0.4013 P_Delta=C_Delta-1=-0.5987
Found: K=113.0000 C_Pr=7.2286 P_Pr=20.2286 : p1=0.3984 : C_delta=p1=0.3984 P_Delta=C_Delta-1=-0.6016

test6_find_k_for_p1_aka_delta(S=100.0000, DTE=365.0000, IV=30.0000, Delta=0.3500, accuracy=0.003000):
Found: K=117.2500 C_Pr=6.0897 P_Pr=23.3397 : p1=0.3518 : C_delta=p1=0.3518 P_Delta=C_Delta-1=-0.6482
Found: K=117.5000 C_Pr=6.0280 P_Pr=23.5280 : p1=0.3492 : C_delta=p1=0.3492 P_Delta=C_Delta-1=-0.6508

test6_find_k_for_p1_aka_delta(S=100.0000, DTE=365.0000, IV=30.0000, Delta=0.3000, accuracy=0.003000):
Found: K=122.2500 C_Pr=4.9565 P_Pr=27.2065 : p1=0.3017 : C_delta=p1=0.3017 P_Delta=C_Delta-1=-0.6983
Found: K=122.5000 C_Pr=4.9052 P_Pr=27.4052 : p1=0.2993 : C_delta=p1=0.2993 P_Delta=C_Delta-1=-0.7007

test6_find_k_for_p1_aka_delta(S=100.0000, DTE=365.0000, IV=30.0000, Delta=0.2500, accuracy=0.003000):
Found: K=127.7500 C_Pr=3.9335 P_Pr=31.6835 : p1=0.2526 : C_delta=p1=0.2526 P_Delta=C_Delta-1=-0.7474
Found: K=128.0000 C_Pr=3.8920 P_Pr=31.8920 : p1=0.2505 : C_delta=p1=0.2505 P_Delta=C_Delta-1=-0.7495
Found: K=128.2500 C_Pr=3.8508 P_Pr=32.1008 : p1=0.2485 : C_delta=p1=0.2485 P_Delta=C_Delta-1=-0.7515

test6_find_k_for_p1_aka_delta(S=100.0000, DTE=365.0000, IV=30.0000, Delta=0.2000, accuracy=0.003000):
Found: K=134.2500 C_Pr=2.9767 P_Pr=37.2267 : p1=0.2028 : C_delta=p1=0.2028 P_Delta=C_Delta-1=-0.7972
Found: K=134.5000 C_Pr=2.9447 P_Pr=37.4447 : p1=0.2010 : C_delta=p1=0.2010 P_Delta=C_Delta-1=-0.7990
Found: K=134.7500 C_Pr=2.9130 P_Pr=37.6630 : p1=0.1993 : C_delta=p1=0.1993 P_Delta=C_Delta-1=-0.8007
Found: K=135.0000 C_Pr=2.8815 P_Pr=37.8815 : p1=0.1976 : C_delta=p1=0.1976 P_Delta=C_Delta-1=-0.8024

test6_find_k_for_p1_aka_delta(S=100.0000, DTE=365.0000, IV=30.0000, Delta=0.1500, accuracy=0.003000):
Found: K=142.2500 C_Pr=2.0979 P_Pr=44.3479 : p1=0.1527 : C_delta=p1=0.1527 P_Delta=C_Delta-1=-0.8473
Found: K=142.5000 C_Pr=2.0748 P_Pr=44.5748 : p1=0.1514 : C_delta=p1=0.1514 P_Delta=C_Delta-1=-0.8486
Found: K=142.7500 C_Pr=2.0520 P_Pr=44.8020 : p1=0.1500 : C_delta=p1=0.1500 P_Delta=C_Delta-1=-0.8500
Found: K=143.0000 C_Pr=2.0295 P_Pr=45.0295 : p1=0.1486 : C_delta=p1=0.1486 P_Delta=C_Delta-1=-0.8514
Found: K=143.2500 C_Pr=2.0071 P_Pr=45.2571 : p1=0.1473 : C_delta=p1=0.1473 P_Delta=C_Delta-1=-0.8527

test6_find_k_for_p1_aka_delta(S=100.0000, DTE=365.0000, IV=30.0000, Delta=0.1000, accuracy=0.003000):
Found: K=153.0000 C_Pr=1.2985 P_Pr=54.2985 : p1=0.1025 : C_delta=p1=0.1025 P_Delta=C_Delta-1=-0.8975
Found: K=153.2500 C_Pr=1.2839 P_Pr=54.5339 : p1=0.1015 : C_delta=p1=0.1015 P_Delta=C_Delta-1=-0.8985
Found: K=153.5000 C_Pr=1.2696 P_Pr=54.7696 : p1=0.1005 : C_delta=p1=0.1005 P_Delta=C_Delta-1=-0.8995
Found: K=153.7500 C_Pr=1.2553 P_Pr=55.0053 : p1=0.0996 : C_delta=p1=0.0996 P_Delta=C_Delta-1=-0.9004
Found: K=154.0000 C_Pr=1.2413 P_Pr=55.2413 : p1=0.0987 : C_delta=p1=0.0987 P_Delta=C_Delta-1=-0.9013
Found: K=154.2500 C_Pr=1.2273 P_Pr=55.4773 : p1=0.0977 : C_delta=p1=0.0977 P_Delta=C_Delta-1=-0.9023

test6_find_k_for_p1_aka_delta(S=100.0000, DTE=365.0000, IV=30.0000, Delta=0.0500, accuracy=0.003000):
Found: K=170.0000 C_Pr=0.5987 P_Pr=70.5987 : p1=0.0527 : C_delta=p1=0.0527 P_Delta=C_Delta-1=-0.9473
Found: K=170.2500 C_Pr=0.5919 P_Pr=70.8419 : p1=0.0522 : C_delta=p1=0.0522 P_Delta=C_Delta-1=-0.9478
Found: K=170.5000 C_Pr=0.5851 P_Pr=71.0851 : p1=0.0517 : C_delta=p1=0.0517 P_Delta=C_Delta-1=-0.9483
Found: K=170.7500 C_Pr=0.5784 P_Pr=71.3284 : p1=0.0512 : C_delta=p1=0.0512 P_Delta=C_Delta-1=-0.9488
Found: K=171.0000 C_Pr=0.5718 P_Pr=71.5718 : p1=0.0507 : C_delta=p1=0.0507 P_Delta=C_Delta-1=-0.9493
Found: K=171.2500 C_Pr=0.5653 P_Pr=71.8153 : p1=0.0502 : C_delta=p1=0.0502 P_Delta=C_Delta-1=-0.9498
Found: K=171.5000 C_Pr=0.5588 P_Pr=72.0588 : p1=0.0497 : C_delta=p1=0.0497 P_Delta=C_Delta-1=-0.9503
Found: K=171.7500 C_Pr=0.5524 P_Pr=72.3024 : p1=0.0492 : C_delta=p1=0.0492 P_Delta=C_Delta-1=-0.9508
Found: K=172.0000 C_Pr=0.5461 P_Pr=72.5461 : p1=0.0487 : C_delta=p1=0.0487 P_Delta=C_Delta-1=-0.9513
Found: K=172.2500 C_Pr=0.5398 P_Pr=72.7898 : p1=0.0482 : C_delta=p1=0.0482 P_Delta=C_Delta-1=-0.9518
Found: K=172.5000 C_Pr=0.5337 P_Pr=73.0337 : p1=0.0477 : C_delta=p1=0.0477 P_Delta=C_Delta-1=-0.9523
Found: K=172.7500 C_Pr=0.5276 P_Pr=73.2776 : p1=0.0472 : C_delta=p1=0.0472 P_Delta=C_Delta-1=-0.9528
 
Last edited:
@CactusWren now you bring out the issue of having a vol surface.. but wouldn't that be exactly the same problem? I.E. the need to use some sort of interpolation to find the IV value of a strike in between?

Yeah, I was just trying to come up with a way to 're-use' the surface interpolation and just search for the value like earth_imperator was suggesting. Might be worth comparing the two strategies if you need to be efficient with CPU

oh, sorry for being a dick here, but this is an important detail: the 0.5 delta strike is never the underlying price.
It moves further upwards the higher volatility and the more expensive the forward is.

not a dick move at all, thanks
 
We used splines but found that other methods were better. There are some methods you can find that game developers use to estimate unknowns in their world.
The orange line in the graph below is our curve.
300c209e5e03a9fb79034c2c0e59faa2.png
 
Not going to pretend I know what’s going on here…hats off to the individual traders who get to this level. And thanks to ORATS for putting care into their data product
 
Back
Top