Exemple #1
0
 def test_prices(self):
     while self.tdi.has_next():
         row = self.tdi.next_row()
         S, K, t, r, sigma = row['S'], row['K'], row['t'], row['R'], row[
             'v']
         self.assertAlmostEqual(black_scholes_merton(
             'c', S, K, t, r, sigma, q),
                                row['bs_call'],
                                delta=0.000001)
         self.assertAlmostEqual(black_scholes_merton(
             'p', S, K, t, r, sigma, q),
                                row['bs_put'],
                                delta=0.000001)
Exemple #2
0
    def price_black_scholes_merton(self,
                                   option_type: str,
                                   spot: float,
                                   strike: float,
                                   years_to_maturity: float,
                                   risk_free_rate: float,
                                   dividend: float = 0) -> float:
        """
        Finds the no-arbitrage price of a European Vanilla option. The price is computed using the Black-Scholes-Merton
        framework, but the variance of the underlying is extracted from this model.

        :param option_type: the type of the option (c for call, p for put)
        :param spot: the spot price of the underlying
        :param strike: the option strike price
        :param years_to_maturity: the years remaining before maturity - as a decimal number
        :param risk_free_rate: the risk-free interest rate
        :param dividend: the dividend paid by the underlying - as a decimal number
        :return: the no-arbitrage price of the option
        """
        volatility = self.volatility(years_to_maturity)
        check_option_type(option_type)
        price = black_scholes_merton(option_type, spot, strike,
                                     years_to_maturity, risk_free_rate,
                                     volatility, dividend)
        return price
Exemple #3
0
 def test_implied_volatility(self):
     while self.tdi.has_next():
         row = self.tdi.next_row()
         S, K, t, r, sigma = row['S'], row['K'], row['t'], row['R'], row[
             'v']
         C, P = black_scholes_merton('c', S, K, t, r, sigma,
                                     q), black_scholes_merton(
                                         'p', S, K, t, r, sigma, q)
         try:
             iv = implied_volatility(C, S, K, t, r, q, 'c')
             self.assertAlmostEqual(sigma, iv, delta=0.0001)
         except:
             print('could not calculate iv for ', C, S, K, t, r, 'c')
         iv = implied_volatility(P, S, K, t, r, q, 'p')
         self.assertTrue(
             iv == 0.0) if iv == 0.0 else self.assertAlmostEqual(
                 sigma, iv, delta=0.001)
Exemple #4
0
 def theo(self, S, vol, t0=None):
     if t0 is None:
         if self.exp not in option.time_exp:
             option.time_exp[self.exp] = self.timetoexp()
         te = option.time_exp[self.exp]
     else:
         te = self.timetoexp(t0)
         if te <= 0: te = 0
         option.time_exp[self.exp] = te
     if te < 0:
         self.tv = np.nan
     else:
         self.tv = bs.black_scholes_merton(self.flag, S, self.K, te,
                                           self.rate, vol, 0.)
     return self.tv
def get_malliavin_greeks_bs_flat(s0: float, t: float, no_steps: int,
                                 no_paths: int, r: float, q: float,
                                 sigma: float, payoff: Callable[[ndarray],
                                                                ndarray],
                                 euler_scheme: EULER_SCHEME_TYPE):
    shift_delta = 0.01
    shift_vega = 0.01

    z = np.random.standard_normal(size=(no_paths, no_steps - 1))
    drift_t = partial(bs_drift_flat, rate_t=r, dividend_t=q)
    sigma_t = partial(bs_sigma_flat, sigma_t=sigma)
    sigma_t_shift = partial(bs_sigma_flat, sigma_t=sigma + shift_vega)

    s_t = sde_euler_simulation(0.0, t, s0, no_steps, no_paths, z, drift_t,
                               sigma_t, euler_scheme)

    s_t_shift_delta = sde_euler_simulation(0.0, t, s0 + shift_delta, no_steps,
                                           no_paths, z, drift_t, sigma_t,
                                           euler_scheme)

    s_t_shift_vega = sde_euler_simulation(0.0, t, s0, no_steps, no_paths, z,
                                          drift_t, sigma_t_shift, euler_scheme)

    phi_t = payoff(s_t[:, -1])
    mc_price = np.average(phi_t) * np.exp(-r * t)
    mc_price_delta = np.average(payoff(s_t_shift_delta[:, -1])) * np.exp(
        -r * t)
    mc_price_vega = np.average(payoff(s_t_shift_vega[:, -1])) * np.exp(-r * t)

    delta = analytical.delta('c', s0, 90, t, r, sigma, q)
    price = black_scholes_merton('c', s0, 90, t, r, sigma, q)
    vega = analytical.vega('c', s0, 90, t, r, sigma, q) * 100

    mc_delta = (mc_price_delta - mc_price) / shift_delta
    malliavin_delta = get_malliavin_delta_bs_flat(phi_t, s_t[:, -1], s0, sigma,
                                                  r, q, t)

    mc_vega = (mc_price_vega - mc_price) / shift_vega
    malliavin_vega = get_malliavin_vega_bs_flat(phi_t, s_t[:, -1], s0, sigma,
                                                r, q, t)

    return mc_delta, malliavin_delta
Exemple #6
0
    def btnClicked2(self):

        price = float(self.ui.StPrice.toPlainText())
        strike = float(self.ui.Strike.toPlainText())
        dayst = float(self.ui.Days.toPlainText())
        days = dayst / 365.0
        rate = float(self.ui.intrate.toPlainText())
        divd = float(self.ui.dividend.toPlainText())
        cp = self.ui.corp.toPlainText()

        vol = float(self.ui.volatility.toPlainText())
        price1 = BSprice.black_scholes_merton(cp, price, strike, days, rate,
                                              vol, divd)
        #price2 = binAm(price,strike,days,rate,vol,1000)
        delt = BSgreeksN.delta(cp, price, strike, days, rate, vol, divd)
        vega = BSgreeksN.vega(cp, price, strike, days, rate, vol, divd)
        gamma = BSgreeksN.gamma(cp, price, strike, days, rate, vol, divd)
        theta = BSgreeksN.theta(cp, price, strike, days, rate, vol, divd)
        self.ui.optprice.setText(str(price1))
        self.ui.Delta1.setText(str(delt))
        self.ui.Theta1.setText(str(theta))
        self.ui.Gamma1.setText(str(gamma))
        self.ui.Vega1.setText(str(vega))
Exemple #7
0
T = 4.0
mesh_t = Mesh(uniform_mesh, 50, 0.0, T)

r = 0.03
q = 0.01
sigma = 0.3

S0 = 100.0
K = np.exp((r - q) * T) * S0 + 10
log_K = np.log(K)

f = np.exp((r - q) * T) * S0
df = np.exp(-r * T)

start_time = time.time()
analytic_price = df * black_scholes_merton('c', f, K, T, 0.0, sigma, 0.0)
end_time = time.time()
print(end_time - start_time)
print(analytic_price)

mesh_x = LnUnderlyingMesh(r, q, sigma, S0, T, 0.999, uniform_mesh, 100)

bs_pde = PDE.from_ipde_terms(LN_BS_PDE(r, q, sigma))
bc = Zero_Laplacian_BC()

operator_exp = PDEOperators.LinearPDEOperator(mesh_x, bs_pde, bc)
operator_impl = PDEOperators.LinearPDEOperator(mesh_x, bs_pde, bc)
operators = [operator_exp, operator_impl]


def f_ln_payoff(mesh: Mesh) -> np_ndarray:
Exemple #8
0
from py_vollib.black_scholes_merton import black_scholes_merton
from py_vollib.helpers.numerical_greeks import delta as numerical_delta
from py_vollib.helpers.numerical_greeks import vega as numerical_vega
from py_vollib.helpers.numerical_greeks import theta as numerical_theta
from py_vollib.helpers.numerical_greeks import rho as numerical_rho
from py_vollib.helpers.numerical_greeks import gamma as numerical_gamma
from py_vollib.black_scholes_merton.greeks.analytical import gamma as agamma
from py_vollib.black_scholes_merton.greeks.analytical import delta as adelta
from py_vollib.black_scholes_merton.greeks.analytical import vega as avega
from py_vollib.black_scholes_merton.greeks.analytical import rho as arho
from py_vollib.black_scholes_merton.greeks.analytical import theta as atheta

# -----------------------------------------------------------------------------
# FUNCTIONS - NUMERICAL GREEK CALCULATION

f = lambda flag, S, K, t, r, sigma, b: black_scholes_merton(
    flag, S, K, t, r, sigma, r - b)


def delta(flag, S, K, t, r, sigma, q):
    """Returns the Black-Scholes-Merton delta of an option.
    
    :param flag: 'c' or 'p' for call or put.
    :type flag: str
    :param S: underlying asset price
    :type S: float
    :param K: strike price
    :type K: float
    :param t: time to expiration in years
    :type t: float
    :param r: annual risk-free interest rate
    :type r: float
Exemple #9
0
no_dt = len(dt)

for i in range(0, no_dt):
    no_time_steps = int(dt[i] / delta_time)
    rnd_generator.set_seed(seed)
    # european_option = EuropeanOption(f0, 1, TypeSellBuy.BUY, TypeEuropeanOption.CALL, f0, dt[i])
    # map_output = SABR_Engine.get_path_multi_step(0.0, dt[i], parameters, f0, no_paths, no_time_steps,
    #                                              Types.TYPE_STANDARD_NORMAL_SAMPLING.ANTITHETIC,
    #                                              rnd_generator)
    #
    # results = european_option.get_price(map_output[Types.SABR_OUTPUT.PATHS])
    # mc_option_price.append(results[0])

    # price the option with var swap approximation
    analytic_price = EuropeanOptionExpansion.get_var_swap_apprx_price(f0, 1.0, TypeSellBuy.BUY, TypeEuropeanOption.CALL,
                                                                      f0, dt[i], parameters, Types.TypeModel.SABR)
    var_swap_approximation_price.append(analytic_price)

    # hagan's price
    iv_hagan = SABRTools.sabr_vol_jit(parameters[0], parameters[1], parameters[2], 0.0, dt[i])
    hagan_price = black_scholes_merton('c', f0, f0, dt[i], 0.0, iv_hagan, 0.0)
    hagan_approximation_price.append(hagan_price)

plt.plot(dt, mc_option_price, label='mc price')
plt.plot(dt, var_swap_approximation_price, label='variance swap approximation')
plt.plot(dt, hagan_approximation_price, label='Hagan approximation')

plt.legend()
plt.title('ATM option price')
plt.show()
Exemple #10
0
# We will do the dynamic hedge of option call under BS model.
k = 100.0
spot = 120.0
r = 0.02
q = 0.00
sigma = 0.7
delta_time = T
notional = 1000.0

portfolio_t_i = np.zeros(no_time_steps)
option_t_i = np.zeros(no_time_steps)

alpha_t_i_1 = analytical.delta('c', spot, k, delta_time, r, sigma,
                               q) * notional
option_t_i[0] = black_scholes_merton('c', spot, k, delta_time, r, sigma,
                                     q) * notional
beta_t = option_t_i[0] - alpha_t_i_1 * spot

portfolio_t_i[0] = (alpha_t_i_1 * spot + beta_t)

s_t_i_1 = spot
s_t_i = 0.0
alpha_t_i = 0.0

rebalanced_index = list(
    map(lambda x: int(x), list(np.arange(0.0, no_time_steps, 30))))
# rebalanced_index = np.arange(1, no_time_steps)

rng = RNG.RndGenerator(123)
z_s = rng.normal(0.0, 1.0, no_time_steps - 1)
    0.0, T, parameters, f0, no_paths, no_time_steps,
    Types.TYPE_STANDARD_NORMAL_SAMPLING.REGULAR_WAY, rnd_generator)

option_prices_mc = []
option_prices_hagan = []
density_mc = []
density_hagan = []
no_options = len(european_options)
for i in range(0, no_options):
    result = european_options[i].get_price(
        map_output[Types.SABR_OUTPUT.PATHS][:, -1])
    option_prices_mc.append(result[0])
    z = np.log(f0 / k_s[i])
    iv_hagan = SABRTools.sabr_vol_jit(alpha, rho, nu, z, T)
    option_prices_hagan.append(
        black_scholes_merton('c', f0, k_s[i], T, 0.0, iv_hagan, 0.0))

pdf_hagan = []
pdf_mc = []
plt.figure(figsize=(8, 5))
for i in range(1, no_options - 1):
    pdf_hagan.append(
        (option_prices_hagan[i + 1] - 2.0 * option_prices_hagan[i] +
         option_prices_hagan[i - 1]) / (delta_strike * delta_strike))
    pdf_mc.append((option_prices_mc[i + 1] - 2.0 * option_prices_mc[i] +
                   option_prices_mc[i - 1]) / (delta_strike * delta_strike))

plt.plot(k_s[1:no_options - 1],
         pdf_hagan,
         label="Hagan's density",
         linestyle='--',
Exemple #12
0
def get_var_swap_apprx_price(strike: float,
                             notional: float,
                             buy_sell: TypeSellBuy,
                             option_type: TypeEuropeanOption,
                             spot: float,
                             delta_time: float,
                             parameters: List[float],
                             model: Types.TypeModel):

    if model == Types.TypeModel.SABR:
        alpha = parameters[0]
        rho = parameters[1]
        nu = parameters[2]
        var_swap = SABRTools.get_variance_swap(alpha, nu, delta_time)
        if option_type == TypeEuropeanOption.CALL:
            bs0 = black_scholes_merton('c', spot, strike, delta_time, 0.0, var_swap, 0.0)
            h_0 = delta_vega(strike, spot, var_swap, delta_time)
            rho_term = SABRTools.get_rho_term_var_swap(alpha, nu, delta_time) * h_0
            if buy_sell == TypeSellBuy.BUY:
                return notional * (bs0 + 0.5 * rho * rho_term)
            else:
                return - notional * (bs0 + 0.5 * rho * rho_term)
        else:
            bs0 = black_scholes_merton('p', spot, strike, delta_time, 0.0, var_swap, 0.0)
            h_0 = delta_vega(strike, spot, var_swap, delta_time)
            rho_term = SABRTools.get_rho_term_var_swap(alpha, nu, delta_time) * h_0
            forward = (spot - strike)
            call_price = notional * (bs0 + 0.5 * rho * rho_term)
            if buy_sell == TypeSellBuy.BUY:
                return call_price - forward
            else:
                return forward - call_price

    elif model == Types.TypeModel.HESTON:
        k = parameters[0]
        theta = parameters[1]
        epsilon = parameters[2]
        rho = parameters[3]
        v0 = parameters[4]

        var_swap = HestonTool.get_variance_swap(v0, k, theta, delta_time)
        if option_type == TypeEuropeanOption.CALL:
            bs0 = black_scholes_merton('c', spot, strike, delta_time, 0.0, var_swap, 0.0)
            h_0 = delta_vega(strike, spot, var_swap, delta_time)
            rho_term = HestonTool.get_rho_term_var_swap(v0, k, theta, epsilon, delta_time) * h_0
            if buy_sell == TypeSellBuy.BUY:
                return notional * (bs0 + 0.5 * rho * rho_term)
            else:
                return - notional * (bs0 + 0.5 * rho * rho_term)
        else:
            bs0 = black_scholes_merton('p', spot, strike, delta_time, 0.0, var_swap, 0.0)
            h_0 = delta_vega(strike, spot, var_swap, delta_time)
            rho_term = HestonTool.get_rho_term_var_swap(v0, k, theta, delta_time) * h_0
            forward = (spot - strike)
            call_price = notional * (bs0 + 0.5 * rho * rho_term)
            if buy_sell == TypeSellBuy.BUY:
                return call_price - forward
            else:
                return forward - call_price

    elif model == Types.TypeModel.ROUGH_BERGOMI:
        return 0.0
    else:
        print(f'At the moment we have not implmented the approximation price for {str(model)} ')