import numpy as np
from Smile.Representations.MoneynessSmileRepresentation import MoneynessSmileRepresentation
from scipy.stats import norm
from Smile.Representations.StrikeSmileRepresentation import StrikeSmileRepresentation
[docs]class SmileRepresentationConverter:
""" Class that permits to convert a smile representation from Strike-> Vol(Strike) to Moneyness -> Vol(Moneyness)
and vice-versa
"""
@staticmethod
[docs] def moneyness_to_strike(underlying_level : float, moneyness : float, volatility : float, duration : float) -> float:
""" Compute the strike associated to a given moneyness expressed in delta.
Parameters
----------
underlying_level : float
The market value of the option underlying.
moneyness : float
The moneyness expressed in terms of delta.
volatility : float
The volatility associated to the inputted moneyness.
duration : float
The duration of the option for which the moneyness was provided
Returns
-------
strike : float
The strike associated to the given moneyness.
Examples
--------
>>> from Smile.Representations.SmileRepresentationConverter import SmileRepresentationConverter
>>> underlying_level = 100.0
>>> moneyness = 0.45
>>> volatility = 0.15
>>> duration = 2.5
>>> SmileRepresentationConverter.moneyness_to_strike(underlying_level, moneyness, volatility, duration)
103.02517658563964
"""
return underlying_level / np.exp(norm.ppf(moneyness) * volatility * np.sqrt(duration))
@staticmethod
[docs] def strike_to_moneyness(underlying_level : float, strike : float, volatility : float, duration : float) -> float:
""" Compute the moneyness expressed in delta associated to a given strike.
Parameters
----------
underlying_level : float
The market value of the option underlying.
strike : float
The strike of the option.
volatility : float
The volatility associated to the inputted strike.
duration : float
The duration of the option for which the strike was provided
Returns
-------
moneyness : float
The moneyness associated to the given strike.
Examples
--------
>>> from Smile.Representations.SmileRepresentationConverter import SmileRepresentationConverter
>>> underlying_level = 100.0
>>> strike = 103.0251
>>> volatility = 0.15
>>> duration = 2.5
>>> SmileRepresentationConverter.strike_to_moneyness(underlying_level, strike, volatility, duration)
0.45000124057807839
"""
return norm.cdf(np.log(underlying_level / strike) / (volatility * np.sqrt(duration)))
@staticmethod
[docs] def strike_representation(moneyness_representation: MoneynessSmileRepresentation, underlying_level: float, duration : float) -> StrikeSmileRepresentation:
""" Compute the smile parametrized in strike equivalent to a given smile parametrized in deltas.
Parameters
----------
moneyness_representation : :class:`~Smile.Representations.MoneynessSmileRepresentation`
The representation of the volatility smile in terms of deltas.
underlying_level : float
The market value of the option underlying.
duration : float
The duration of the option for which the strike was provided
Returns
-------
strike_smile_representation : :class:`~Smile.Representations.StrikeSmileRepresentation`
The representation of the volatility smile in terms of strikes.
Examples
--------
>>> from Smile.Representations.SmileRepresentationConverter import SmileRepresentationConverter
>>> from Smile.Representations.MoneynessSmileRepresentation import MoneynessSmileRepresentation
>>> import numpy as np
>>> underlying_level = 100.0
>>> duration = 2.5
>>> atm_vol = 0.15
>>> moneyness = np.array([0.05,0.25,0.5,0.75,0.95])
>>> vol_shifts = np.array([0.10, 0.05, 0, -0.03, -0.09])
>>> moneyness_representation = MoneynessSmileRepresentation(atm_vol, moneyness, vol_shifts)
>>> strike_representation = SmileRepresentationConverter.strike_representation(moneyness_representation,underlying_level, duration)
>>> print(strike_representation)
Strikes |65.108|84.538|100.000|116.786|142.618|
Vols |0.165|0.158|0.150|0.145|0.137|
Skew |0.100|0.050|0.000|-0.030|-0.090|
<BLANKLINE>
"""
volvec = moneyness_representation.volatilities
strikes = underlying_level / np.exp(
norm.ppf(moneyness_representation.moneyness[::-1]) * volvec * np.sqrt(duration))
return StrikeSmileRepresentation(moneyness_representation.atm_vol, strikes, moneyness_representation.vol_shifts)
@staticmethod
[docs] def moneyness_representation(strike_representation: StrikeSmileRepresentation, underlying_level: float, duration : float) -> MoneynessSmileRepresentation:
""" Compute the smile parametrized in deltas equivalent to a given smile parametrized in strikes.
Parameters
----------
strike_representation : :class:`~Smile.Representations.StrikeSmileRepresentation`
The representation of the volatility smile in terms of strikes.
underlying_level : float
The market value of the option underlying.
duration : float
The duration of the option for which the strike was provided
Returns
-------
moneyness_representation : :class:`~Smile.Representations.MoneynessSmileRepresentation`
The representation of the volatility smile in terms of deltas.
Examples
--------
>>> from Smile.Representations.SmileRepresentationConverter import SmileRepresentationConverter
>>> from Smile.Representations.StrikeSmileRepresentation import StrikeSmileRepresentation
>>> import numpy as np
>>> underlying_level = 100.0
>>> duration = 2.5
>>> atm_vol = 0.15
>>> strikes = np.array([65.108,84.538,100.000,116.786,142.618])
>>> vol_shifts = np.array([0.10, 0.05, 0, -0.03, -0.09])
>>> strike_representation = StrikeSmileRepresentation(atm_vol, strikes, vol_shifts)
>>> moneyness_representation = SmileRepresentationConverter.moneyness_representation(strike_representation,underlying_level, duration)
>>> print(moneyness_representation)
Moneyness |0.087|0.267|0.500|0.767|0.977|
Vols |0.165|0.158|0.150|0.145|0.137|
Skew |0.100|0.050|0.000|-0.030|-0.090|
<BLANKLINE>
"""
volvec = strike_representation.volatilities
calldeltavec = norm.cdf(
np.log(underlying_level / strike_representation.strikes[::-1]) / (volvec * np.sqrt(duration)))
return MoneynessSmileRepresentation(strike_representation.atm_vol, calldeltavec, strike_representation.vol_shifts)
if __name__ == "__main__":
import doctest
doctest.testmod()