QuantLib Call Options Pricing over rows in a data frame

31 views Asked by At

I have some data which looks like:

date    call_open   call_high   call_low    call_close  put_open    put_high    put_low put_close   stock_open  stock_high  stock_low   stock_close stock_volume
0   2024-01-31 15:30:00 1.03    1.82    0.88    0.95    11.72   12.78   11.34   12.55   488.62  489.09  487.52  487.76  61890.0
1   2024-01-31 15:30:00 1.03    1.82    0.88    0.95    11.72   12.78   11.34   12.55   488.62  489.09  487.52  487.76  61890.0
2   2024-01-31 16:00:00 0.95    0.96    0.79    0.84    12.55   13.80   12.47   13.48   487.73  487.83  486.39  486.75  81468.0
3   2024-01-31 16:00:00 0.95    0.96    0.79    0.84    12.55   13.80   12.47   13.48   487.73  487.83  486.39  486.75  81468.0
4   2024-01-31 17:00:00 0.84    0.92    0.81    0.86    13.48   13.88   12.76   13.39   486.74  487.48  486.34  486.84  53420.0

I am trying to compute for each row the options price as if I was trying to price the option on that day.

This is the options chain data with a strike of 500 for the S&P500.

I pass it the following:

  • Todays stock S - the stock_close column.
  • Strike price K
  • volatility v (I know using the volatility of the whole dataset is not useful since its using future stock prices but this is just to assign a realistic value here)
  • ri the risk pree rate
  • The expiry is the last observed date in the options chain (I downloaded it just before close expiry = pd.to_datetime("2024-02-14")

What I don't understand is why is my call_option_pricing so different to that of the call_close - i.e. I am getting values of 0.013527 when the actual price was 0.95

date    call_open   call_high   call_low    call_close  put_open    put_high    put_low put_close   stock_open  stock_high  stock_low   stock_close stock_volume    option_pricing
0   2024-01-31 15:30:00 1.03    1.82    0.88    0.95    11.72   12.78   11.34   12.55   488.62  489.09  487.52  487.76  61890.0 0.013527
1   2024-01-31 15:30:00 1.03    1.82    0.88    0.95    11.72   12.78   11.34   12.55   488.62  489.09  487.52  487.76  61890.0 0.013527
2   2024-01-31 16:00:00 0.95    0.96    0.79    0.84    12.55   13.80   12.47   13.48   487.73  487.83  486.39  486.75  81468.0 0.006911
3   2024-01-31 16:00:00 0.95    0.96    0.79    0.84    12.55   13.80   12.47   13.48   487.73  487.83  486.39  486.75  81468.0 0.006911
4   2024-01-31 17:00:00 0.84    0.92    0.81    0.86    13.48   13.88   12.76   13.39   486.74  487.48  486.34  486.84  53420.0 0.007350

import pandas as pd
file_path = "path/expiry_20240214_strike_500.csv"
data = pd.read_csv(file_path)
data = data.dropna(subset=['stock_close'])
data


def compute_option_pricing(row):
    S = row['stock_close']  
    K = 500  
    v = data['stock_close'].std() / 100 
    ri = 0.0528 # taken from: https://home.treasury.gov/resource-center/data-chart-center/interest-rates/TextView?type=daily_treasury_bill_rates&field_tdr_date_value_month=202402
    

    date = pd.to_datetime(row['date'])
    today = ql.Date(date.day, date.month, date.year)
    expiry = pd.to_datetime("2024-02-14")
    expiry = ql.Date(expiry.day, expiry.month, expiry.year) 
    
    # Set the evaluation date
    ql.Settings.instance().evaluationDate = today
    
    # The Instrument
    option = ql.EuropeanOption(ql.PlainVanillaPayoff(ql.Option.Call, K),
                               ql.EuropeanExercise(expiry))
    
    # The Market
    u = ql.SimpleQuote(S)
    r = ql.SimpleQuote(ri)
    sigma = ql.SimpleQuote(v)
    riskFreeCurve = ql.FlatForward(0, ql.TARGET(), ql.QuoteHandle(r), ql.Actual365Fixed())
    volatility = ql.BlackConstantVol(0, ql.TARGET(), ql.QuoteHandle(sigma), ql.Actual365Fixed())
    
    # The Model
    process = ql.BlackScholesProcess(ql.QuoteHandle(u), 
                                     ql.YieldTermStructureHandle(riskFreeCurve),
                                     ql.BlackVolTermStructureHandle(volatility))
    
    # The Pricing Engine
    engine = ql.AnalyticEuropeanEngine(process)
    option.setPricingEngine(engine)
    
    return option.NPV()

# Apply the function to each row and store the results in a new column
data['call_option_pricing'] = data.apply(compute_option_pricing, axis=1)
0

There are 0 answers