def test_heston_pricer(self): trade_date = date(2011, 1, 24) spot = 1290.58 # option definition options = ds.option_quotes_template().reindex(index=range(2)) options[nm.OPTION_TYPE] = ['C', 'P'] options[nm.STRIKE] = [1290, 1290] options[nm.EXPIRY_DATE] = [date(2015, 1, 1), date(2015, 1, 1)] options[nm.SPOT] = [spot] * 2 # interest rate and dividend yield rates = ds.riskfree_dividend_template().reindex( index=[date(2011, 3, 16), date(2013, 3, 16), date(2015, 3, 16)]) rates[nm.DIVIDEND_YIELD] = [.021, .023, .024] rates[nm.INTEREST_RATE] = [.010, .015, .019] # heston model heston_params = dict(v0=0.051965, kappa=0.977314, theta=0.102573, sigma=0.987796, rho=-0.747033 ) results = heston_pricer(trade_date, options, heston_params, rates, spot=1290.58) price_call = results[nm.PRICE][0] price_put = results[nm.PRICE][1] self.assertAlmostEqual(price_call, 194.6, 1) self.assertAlmostEqual(price_put, 218.9, 1)
def options_to_rates(options, t_min=1. / 12., n_min=6): """ Extract implied risk-free rates and dividend yield from standard European option quote file. ignore data: - with time to maturity < tMin (in fraction of years) - with fewer than nMin quotes per maturity date Parameters ---------- t_min: float (default: 1 month) Minimum time to maturity in fraction of years n_min: int (default: 6) minimum number of quotes per maturity date """ grouped = options.groupby(nm.EXPIRY_DATE) expiry_dates = [] implied_interest_rates = [] implied_dividend_yields = [] for spec, group in grouped: # implied vol for this type/expiry group index = group.index trade_date = group[nm.TRADE_DATE][index[0]] expiry_date = group[nm.EXPIRY_DATE][index[0]] spot = group[nm.SPOT][index[0]] days_to_expiry = (expiry_date - trade_date).days time_to_maturity = days_to_expiry / 365.0 # exclude groups with too short time to maturity if time_to_maturity < t_min: continue # extract the put and call quotes calls = group[group[nm.OPTION_TYPE] == nm.CALL_OPTION] puts = group[group[nm.OPTION_TYPE] == nm.PUT_OPTION] # exclude groups with too few data points if (len(calls) < n_min) | (len(puts) < n_min): continue # calculate forward, implied interest rate and implied div. yield call_premium = DataFrame( (calls[nm.PRICE_BID] + calls[nm.PRICE_ASK]) / 2., columns=[CALL_PREMIUM]) call_premium.index = np.array(calls[nm.STRIKE]) put_premium = DataFrame((puts[nm.PRICE_BID] + puts[nm.PRICE_ASK]) / 2., columns=[PUT_PREMIUM]) put_premium.index = np.array(puts[nm.STRIKE]) # use 'inner' join because some strikes are not quoted for C and P all_quotes = call_premium.join(put_premium, how='inner') all_quotes[nm.STRIKE] = all_quotes.index all_quotes['C-P'] = all_quotes[CALL_PREMIUM] - all_quotes[PUT_PREMIUM] y = np.array(all_quotes['C-P']) x = np.array(all_quotes[nm.STRIKE]) A = np.vstack([x, np.ones(len(x))]).T a_1, a_0 = np.linalg.lstsq(A, y)[0] # intercept is last coef interest_rate = -np.log(-a_1) / time_to_maturity dividend_yield = np.log(spot / a_0) / time_to_maturity implied_interest_rates.append(interest_rate) implied_dividend_yields.append(dividend_yield) expiry_dates.append(expiry_date) rates = ds.riskfree_dividend_template().reindex(index=expiry_dates) rates[nm.INTEREST_RATE] = implied_interest_rates rates[nm.DIVIDEND_YIELD] = implied_dividend_yields return rates
def test_riskfree_dividend(self): x = df.riskfree_dividend_template().reindex( index=[date(2000, 1, 1) + timedelta(days=k) for k in range(10)]) x[nm.DIVIDEND_YIELD] = np.linspace(.01, .03, 10) x[nm.INTEREST_RATE] = np.linspace(.02, .04, 10) self.assertTrue(True)
def test_riskfree_dividend(self): x = df.riskfree_dividend_template().reindex( index=[date(2000,1,1)+timedelta(days=k) for k in range(10)]) x[nm.DIVIDEND_YIELD] = np.linspace(.01, .03, 10) x[nm.INTEREST_RATE] = np.linspace(.02, .04, 10) self.assertTrue(True)
def options_to_rates(options, t_min=1./12., n_min=6): """ Extract implied risk-free rates and dividend yield from standard European option quote file. ignore data: - with time to maturity < tMin (in fraction of years) - with fewer than nMin quotes per maturity date Parameters ---------- t_min: float (default: 1 month) Minimum time to maturity in fraction of years n_min: int (default: 6) minimum number of quotes per maturity date """ grouped = options.groupby(nm.EXPIRY_DATE) expiry_dates = [] implied_interest_rates = [] implied_dividend_yields = [] for spec, group in grouped: # implied vol for this type/expiry group index = group.index trade_date = group[nm.TRADE_DATE][index[0]] expiry_date = group[nm.EXPIRY_DATE][index[0]] spot = group[nm.SPOT][index[0]] days_to_expiry = (expiry_date-trade_date).days time_to_maturity = days_to_expiry/365.0 # exclude groups with too short time to maturity if time_to_maturity < t_min: continue # extract the put and call quotes calls = group[group[nm.OPTION_TYPE] == nm.CALL_OPTION] puts = group[group[nm.OPTION_TYPE] == nm.PUT_OPTION] # exclude groups with too few data points if (len(calls) < n_min) | (len(puts) < n_min): continue # calculate forward, implied interest rate and implied div. yield call_premium = DataFrame( (calls[nm.PRICE_BID] + calls[nm.PRICE_ASK]) / 2., columns=[CALL_PREMIUM]) call_premium.index = np.array(calls[nm.STRIKE]) put_premium = DataFrame( (puts[nm.PRICE_BID] + puts[nm.PRICE_ASK]) / 2., columns=[PUT_PREMIUM]) put_premium.index = np.array(puts[nm.STRIKE]) # use 'inner' join because some strikes are not quoted for C and P all_quotes = call_premium.join(put_premium, how='inner') all_quotes[nm.STRIKE] = all_quotes.index all_quotes['C-P'] = all_quotes[CALL_PREMIUM] - all_quotes[PUT_PREMIUM] y = np.array(all_quotes['C-P']) x = np.array(all_quotes[nm.STRIKE]) A = np.vstack([x, np.ones(len(x))]).T a_1, a_0 = np.linalg.lstsq(A, y)[0] # intercept is last coef interest_rate = -np.log(-a_1)/time_to_maturity dividend_yield = np.log(spot/a_0)/time_to_maturity implied_interest_rates.append(interest_rate) implied_dividend_yields.append(dividend_yield) expiry_dates.append(expiry_date) rates = ds.riskfree_dividend_template().reindex(index=expiry_dates) rates[nm.INTEREST_RATE] = implied_interest_rates rates[nm.DIVIDEND_YIELD] = implied_dividend_yields return rates