diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/analytics/cms_spread.py | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/python/analytics/cms_spread.py b/python/analytics/cms_spread.py index 2d5b2109..d9b0ecce 100644 --- a/python/analytics/cms_spread.py +++ b/python/analytics/cms_spread.py @@ -43,6 +43,7 @@ def close_dbs(): @vectorize([float64(float64, float64, float64, float64, float64, float64, float64, float64, float64)], cache=True, nopython=True) def h_call(z, K, S1, S2, mu_x, mu_y, sigma_x, sigma_y, rho): + # conditionned on S2, integral wrt S1 # z = (y - mu_y) / sigma_y u1 = mu_x + rho * sigma_x * z Ktilde = K + S2 * exp(mu_y + sigma_y * z) @@ -215,8 +216,8 @@ def globeop_model(date, spread_index, yc, strike, rho, maturity, vol1 = atm_vol.volatility(maturity, spread_index.swap_index1.tenor, 0.) vol2 = atm_vol.volatility(maturity, spread_index.swap_index2.tenor, 0.) vol_spread = sqrt(vol1**2 + vol2**2 - 2 * rho * vol1 * vol2) - # normal vol is not scale independent and is computed in percent terms, so we scale - # everything by 100. + # normal vol is not scale independent and is computed in percent terms, so + # we scale everything by 100. return 0.01 * yc.discount(T) * bachelier(forward * 100, strike * 100, T, vol_spread) def get_cms_coupons(trade_date, notional, option_tenor, spread_index, @@ -263,7 +264,8 @@ def get_params(cms_beta, cms_gamma, atm_vol): class CmsSpread: def __init__(self, maturity, tenor1, tenor2, strike, option_tenor=None, value_date=datetime.date.today(), notional=100_000_000, - fixing_days=2, corr=0.8, mean_reversion=0.1): + conditional1=None, conditional2=None, fixing_days=2, corr=0.8, + mean_reversion=0.1): """ tenor1 < tenor2""" self._value_date = value_date if maturity is None: @@ -305,6 +307,8 @@ class CmsSpread: self.cms2.set_pricer(self._cms_pricer) self._params = get_params(self.cms1, self.cms2, atm_vol) self._x, self._w = roots_hermitenorm(20) + self.conditional1 = conditional1 + self.conditional2 = conditional2 @staticmethod def from_tradeid(trade_id): @@ -313,7 +317,7 @@ class CmsSpread: "amount, expiration_date, floating_rate_index, strike, trade_date " "FROM capfloors WHERE id = %s", (trade_id,)) r = c.fetchone() - m = re.match("USD(\d{1,2})-(\d{1,2})CMS", r['floating_rate_index']) + m = re.match(r"USD(\d{1,2})-(\d{1,2})CMS", r['floating_rate_index']) if m: tenor2, tenor1 = map(int, m.groups()) instance = CmsSpread(r['expiration_date'], tenor1, tenor2, r['strike'] * 0.01, @@ -326,7 +330,7 @@ class CmsSpread: @corr.setter def corr(self, val): - self._corr.set_value(val) + self._corr.value = val @property def value_date(self): @@ -344,6 +348,9 @@ class CmsSpread: @property def pv(self): - return self.notional * 1 / sqrt(2 * pi) * \ - np.dot(self._w, h_call(self._x, self.strike, *self._params, self.corr)) * \ - self.yc.discount(self.cms1.fixing_date) + if self.conditional1 is not None: + bound = (log(self.conditional1 / self._params[1]) - self._params[3]) / self._params[-1] + else: + return self.notional * 1 / sqrt(2 * pi) * \ + np.dot(self._w, h_call(self._x, self.strike, *self._params, self.corr)) * \ + self.yc.discount(self.cms1.fixing_date) |
