Source code for putcall.formulas.interest_rate_options.bachelier

# -*- coding: utf-8 -*-

# putcall
# -------
# Collection of classical option pricing formulas.
# 
# Author:   sonntagsgesicht, based on a fork of Deutsche Postbank [pbrisk]
# Version:  0.2, copyright Wednesday, 18 September 2019
# Website:  https://github.com/sonntagsgesicht/putcall
# License:  Apache License 2.0 (see LICENSE file)


from math import exp, sqrt, pi

from mathtoolspy import cdf_abramowitz_stegun as normal_cdf
from mathtoolspy import density_normal_dist as normal_density

from ..option_payoffs import option_payoff, digital_option_payoff, straddle_payoff


def _bachelier_param(forward_value, strike_value, implied_vol_value, time_value):
    sigma = implied_vol_value * sqrt(time_value)
    fms = forward_value - strike_value
    d = fms / sigma if sigma > 0.0 else 0.0
    return sigma, fms, d


[docs]def bachelier(forward_value, strike_value, implied_vol_value, time_value, is_call_bool): """ Bachelier formula (Black formula for normal underlying distribution). :param float forward_value: forward price of underlying at exercise date :param float strike_value: strike price :param float implied_vol_value: volatility of underlying price :param float time_value: year fraction until exercise date :param boolean is_call_bool: call -> True, put -> False :return: float """ sigma, fms, d = _bachelier_param(forward_value, strike_value, implied_vol_value, time_value) if sigma == 0.0: return option_payoff(forward_value, strike_value, is_call_bool) # call # call_value = fms * normal_cdf(d) + exp(-d ** 2 / 2) * sigma / sqrt(2 * pi) # intern version call_value = fms * normal_cdf(d) + sigma * normal_density(d) put_value = -fms * normal_cdf(-d) + sigma * normal_density(d) return call_value if is_call_bool else call_value - fms # put
[docs]def bachelier_delta(forward_value, strike_value, implied_vol_value, time_value, is_call_bool): """ delta sensitivity for Bachelier formula. :param float forward_value: forward price of underlying at exercise date :param float strike_value: strike price :param float implied_vol_value: volatility of underlying price :param float time_value: year fraction until exercise date :param boolean is_call_bool: call -> True, put -> False :return: float """ sigma, fms, d = _bachelier_param(forward_value, strike_value, implied_vol_value, time_value) if sigma == 0.0: return 1.0 if fms > 0.0 else 0.0 return normal_cdf(d) if is_call_bool else -normal_cdf(-d)
[docs]def bachelier_gamma(forward_value, strike_value, implied_vol_value, time_value, is_call_bool): """ gamma sensitivity for Bachelier formula. :param float forward_value: forward price of underlying at exercise date :param float strike_value: strike price :param float implied_vol_value: volatility of underlying price :param float time_value: year fraction until exercise date :param boolean is_call_bool: call -> True, put -> False :return: float """ sigma, fms, d = _bachelier_param(forward_value, strike_value, implied_vol_value, time_value) if sigma == 0.0: return 0.0 return normal_density(d) / sigma
[docs]def bachelier_vega(forward_value, strike_value, implied_vol_value, time_value, is_call_bool): """ vega sensitivity for Bachelier formula. :param float forward_value: forward price of underlying at exercise date :param float strike_value: strike price :param float implied_vol_value: volatility of underlying price :param float time_value: year fraction until exercise date :param boolean is_call_bool: call -> True, put -> False :return: float """ sigma, fms, d = _bachelier_param(forward_value, strike_value, implied_vol_value, time_value) if sigma == 0.0: return 0.0 return sqrt(time_value) * normal_density(d)
[docs]def bachelier_digital(forward_value, strike_value, implied_vol_value, time_value, is_call_bool): """ Bachelier formula for digital option (Black formula for normal underlying distribution). :param float forward_value: forward price of underlying at exercise date :param float strike_value: strike price :param float implied_vol_value: volatility of underlying price :param float time_value: year fraction until exercise date :param boolean is_call_bool: call -> True, put -> False :return: float """ sigma, fms, d = _bachelier_param(forward_value, strike_value, implied_vol_value, time_value) if sigma == 0.0: return digital_option_payoff(forward_value, strike_value, is_call_bool) # call call_price = -1 * normal_cdf(d) + exp(-d ** 2 / 2) * sigma / sqrt(2 * pi) return call_price if is_call_bool else call_price + 1 # put
[docs]def bachelier_digital_delta(forward_value, strike_value, implied_vol_value, time_value, is_call_bool): """ delta sensitivity for Bachelier formula for digital option. :param float forward_value: forward price of underlying at exercise date :param float strike_value: strike price :param float implied_vol_value: volatility of underlying price :param float time_value: year fraction until exercise date :param boolean is_call_bool: call -> True, put -> False :return: float """ sigma, fms, d = _bachelier_param(forward_value, strike_value, implied_vol_value, time_value) if sigma == 0.0: return 0.0 # call call_value = normal_density(d) / sigma return call_value if is_call_bool else -call_value # put
[docs]def bachelier_digital_gamma(forward_value, strike_value, implied_vol_value, time_value, is_call_bool): """ gamma sensitivity for Bachelier formula for digital option. :param float forward_value: forward price of underlying at exercise date :param float strike_value: strike price :param float implied_vol_value: volatility of underlying price :param float time_value: year fraction until exercise date :param boolean is_call_bool: call -> True, put -> False :return: float """ sigma, fms, d = _bachelier_param(forward_value, strike_value, implied_vol_value, time_value) if sigma == 0.0: return 0.0 return d * normal_density(d) / (implied_vol_value * implied_vol_value * time_value)
[docs]def bachelier_digital_vega(forward_value, strike_value, implied_vol_value, time_value, is_call_bool): """ vega sensitivity for Bachelier formula for digital option. :param float forward_value: forward price of underlying at exercise date :param float strike_value: strike price :param float implied_vol_value: volatility of underlying price :param float time_value: year fraction until exercise date :param boolean is_call_bool: call -> True, put -> False :return: float """ sigma, fms, d = _bachelier_param(forward_value, strike_value, implied_vol_value, time_value) if sigma == 0.0: return 0.0 # call call_value = -d * normal_density(d) / implied_vol_value return call_value if is_call_bool else -call_value # put
[docs]def bachelier_straddle(forward_value, strike_value, implied_vol_value, time_value, is_call_bool): """ Bachelier formula for straddle option on log-normal underlying distribution. :param float forward_value: forward price of underlying at exercise date :param float strike_value: strike price :param float implied_vol_value: volatility of underlying price :param float time_value: year fraction until exercise date :param boolean is_call_bool: call -> True, put -> False :return: float """ sigma, fms, d = _bachelier_param(forward_value, strike_value, implied_vol_value, time_value) if sigma == 0.0: return straddle_payoff(forward_value, strike_value, is_call_bool) return None # TODO Bachelier for straddle payoff
[docs]def bachelier_straddle_delta(forward_value, strike_value, implied_vol_value, time_value, is_call_bool): """ Bachelier delta sensitivity for straddle payoff. :param float forward_value: forward price of underlying at exercise date :param float strike_value: strike price :param float implied_vol_value: volatility of underlying price :param float time_value: year fraction until exercise date :param boolean is_call_bool: call -> True, put -> False :return: float """ sigma, fms, d = _bachelier_param(forward_value, strike_value, implied_vol_value, time_value) if sigma == 0.0: return 1.0 if fms >= 0.0 else -1.0 return None # TODO Bachelier delta for straddle payoff
[docs]def bachelier_straddle_gamma(forward_value, strike_value, implied_vol_value, time_value, is_call_bool): """ Bachelier gamma sensitivity for straddle payoff. :param float forward_value: forward price of underlying at exercise date :param float strike_value: strike price :param float implied_vol_value: volatility of underlying price :param float time_value: year fraction until exercise date :param boolean is_call_bool: call -> True, put -> False :return: float """ sigma, fms, d = _bachelier_param(forward_value, strike_value, implied_vol_value, time_value) if sigma == 0.0: return 0.0 return None # TODO Bachelier gamma for straddle payoff
[docs]def bachelier_straddle_vega(forward_value, strike_value, implied_vol_value, time_value, is_call_bool): """ Bachelier vega sensitivity for straddle payoff. :param float forward_value: forward price of underlying at exercise date :param float strike_value: strike price :param float implied_vol_value: volatility of underlying price :param float time_value: year fraction until exercise date :param boolean is_call_bool: call -> True, put -> False :return: float """ sigma, fms, d = _bachelier_param(forward_value, strike_value, implied_vol_value, time_value) if sigma == 0.0: return 0.0 return None # TODO Bachelier vega for straddle payoff