Source code for putcall.formulas.interest_rate_options.sabr

# -*- 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)


import math
import logging

pace_log = logging.getLogger('pace')

# ----- sabr -----

EPS = 0.000000001


[docs]def sabr_black_vol(strike_value, forward_value, alpha_value, beta_value, nu_value, rho_value, time_value): ''' :param strike_value: :type strike_value: :param forward_value: :type forward_value: :param alpha_value: :type alpha_value: :param beta_value: :type beta_value: :param nu_value: :type nu_value: :param rho_value: :type rho_value: :param time_value: :type time_value: :return: :rtype: ''' return_value = 0.00 # Compute the Black equivalent voltatility from SABR model forward_strike_value = forward_value * strike_value log_moneyness_value = math.log(forward_value / strike_value) one_minus_beta_value = 1 - beta_value factor = 0.00 if abs(strike_value - forward_value) > EPS: Z = nu_value / alpha_value * forward_strike_value ** (one_minus_beta_value / 2) * log_moneyness_value xz = math.log((math.sqrt(1 - 2 * rho_value * Z + Z * Z) + Z - rho_value) / (1 - rho_value)) denom_value = forward_strike_value ** (one_minus_beta_value / 2) * ( 1 + one_minus_beta_value ** 2 / 24 * log_moneyness_value ** 2 + one_minus_beta_value ** 4 / 1920 * log_moneyness_value ** 4) factor = one_minus_beta_value ** 2 / 24 * alpha_value ** 2 / (forward_strike_value ** one_minus_beta_value) factor = factor + 0.25 * rho_value * beta_value * alpha_value * nu_value / ( forward_strike_value ** (one_minus_beta_value / 2)) factor = factor + (2 - 3 * rho_value ** 2) * nu_value ** 2 / 24 factor = 1 + factor * time_value # obloj correction # return_value = alpha_value / denom_value * Z / xz * factor return_value = alpha_value / denom_value * factor else: # factor = ( 1 + ( one_minus_beta_value **2 / 24 * alpha_value ** 2 / ( forward_value ** ( 2 * one_minus_beta_value ) ) + 0.25 * rho_value * beta_value * alpha_value * nu_value / ( forward_value ** one_minus_beta_value ) + ( 2 - 3 * rho_value * rho_value ) * nu_value * nu_value / 24 ) * time_value ) factor = one_minus_beta_value ** 2 / 24 * alpha_value ** 2 / (forward_value ** (2 * one_minus_beta_value)) factor = factor + 0.25 * rho_value * beta_value * alpha_value * nu_value / ( forward_value ** one_minus_beta_value) factor = factor + (2 - 3 * rho_value ** 2) * nu_value ** 2 / 24 factor = 1 + factor * time_value factor = (1 + (one_minus_beta_value ** 2 / 24 * alpha_value ** 2 / ( forward_value ** (2 * one_minus_beta_value)) + 0.25 * rho_value * beta_value * alpha_value * nu_value / ( forward_value ** one_minus_beta_value) + ( 2 - 3 * rho_value * rho_value) * nu_value * nu_value / 24) * time_value) return_value = alpha_value / forward_value ** one_minus_beta_value * factor return return_value
[docs]def sabr_atmadj_black_vol(strike_value, forward_value, atm_vol_value, beta_value, nu_value, rho_value, time_value): ''' :param strike_value: :type strike_value: :param forward_value: :type forward_value: :param atm_vol_value: :type atm_vol_value: :param beta_value: :type beta_value: :param nu_value: :type nu_value: :param rho_value: :type rho_value: :param time_value: :type time_value: :return: :rtype: ''' alpha_value = sabr_alpha_from_atm(forward_value, atm_vol_value, beta_value, nu_value, rho_value, time_value) pace_log.debug('sabr atm alpha: %f' % alpha_value) return sabr_black_vol(strike_value, forward_value, alpha_value, beta_value, nu_value, rho_value, time_value)
[docs]def sabr_alpha_from_atm(forward_value, atm_vol_value, beta_value, nu_value, rho_value, time_value): ''' :param forward_value: :type forward_value: :param atm_vol_value: :type atm_vol_value: :param beta_value: :type beta_value: :param nu_value: :type nu_value: :param rho_value: :type rho_value: :param time_value: :type time_value: :return: :rtype: ''' alpha_value = 0.0 diff = sabr_black_vol(forward_value, forward_value, alpha_value, beta_value, nu_value, rho_value, time_value) - atm_vol_value while diff < EPS: alpha_value += EPS diff = sabr_black_vol(forward_value, forward_value, alpha_value, beta_value, nu_value, rho_value, time_value) - atm_vol_value return alpha_value