0

I have a Class object which calculates implied volatility, I have a csv for a company I am interested in with multiple strikes, contract lengths etc. But I cant work out how to get my df to interact with the object.

Ive added the code for the calculation as well as the df with the desired result which is the IV column.

df["IV"] = df.apply(implied_vol('p', df["Premium"], df["Stock Price"], df["Strike"], 0.001, df["Length / 365"], df["Div Yield"]))

from math import log, sqrt, pi, exp
from scipy.stats import norm


def d1(S,K,T,r,q,sigma):

    return(log(S/K)+(r - q +sigma**2/2.)*T)/sigma*sqrt(T)

def d2(S,K,T,r,q,sigma):

    return d1(S,K,T,r,q,sigma)-sigma*sqrt(T)


## define the call options price function

def bs_call(S,K,T,r,q,sigma):

    return S*exp(-q*T)*norm.cdf(d1(S,K,T,r,q,sigma))-K*exp(-r*T)*norm.cdf(d2(S,K,T,r,q,sigma))
 
def bs_put(S,K,T,r,q,sigma):

    return K*exp(-r*T)-S*exp(-q*T)+bs_call(S,K,T,r,q,sigma)

def implied_vol(option_type, option_price, S, K, r, T, q):
    precision = 0.0000001

    upper_vol = 99.0

    max_vol = 99.0

    min_vol = 0.0001

    lower_vol = 0.0001

    iteration = 0

    while 1:

        iteration +=1

        mid_vol = (upper_vol + lower_vol)/2.0

        if option_type == 'c':

            price = bs_call(S,K,T,r,q,mid_vol)

            lower_price = bs_call(S,K,T,r,q,lower_vol)

            if (lower_price - option_price) * (price - option_price) > 0:

                lower_vol = mid_vol
            else:
                upper_vol = mid_vol

            if abs(price - option_price) < precision: break

            if mid_vol > max_vol - 5 :

                mid_vol = 0.0001
                break

        elif option_type == 'p':

            price = bs_put(S,K,T,r,q,mid_vol)

            upper_price = bs_put(S,K,T,r,q,upper_vol)


            if (upper_price - option_price) * (price - option_price) > 0:

                upper_vol = mid_vol

            else:

                lower_vol = mid_vol
            if abs(price - option_price) < precision: break
            if iteration > 1000: break
    return mid_vol


Strike  Stock Price Premium Length  Div Yield   Length / 365    IV
480 490.649994  13.35   17  0   0.046575342                0.451331908
485 490.649994  15.025  17  0   0.046575342                0.427791225
490 490.649994  17.35   17  0   0.046575342                0.419756262
JPWilson
  • 691
  • 4
  • 14

1 Answers1

0

current code

df["IV"] = df.apply(implied_vol('p', df["Premium"], df["Stock Price"], df["Strike"], 0.001, df["Length / 365"], df["Div Yield"]))

is wrong since you call the implied_vol function your self and pandas try to convert the float that is returned into series.

you need to let pandas call the function with the required extra args.

See https://www.journaldev.com/33478/pandas-dataframe-apply-examples for examples.

balderman
  • 22,927
  • 7
  • 34
  • 52
  • I tried this df["IV"] = df.apply(implied_vol, axis = 0, args = ('p', df["Premium"], df["Stock Price"], df["Strike"], 0.001, df["Length / 365"], df["Div Yield"])). – JPWilson Sep 29 '20 at 13:55
  • But it says this error TypeError: implied_vol() takes 7 positional arguments but 8 were given Im struggling to see how there are 8 positional arguments – JPWilson Sep 29 '20 at 13:56