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- thestock_closecolumn. - 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) rithe 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)