diff options
Diffstat (limited to 'python/analytics/index.py')
| -rw-r--r-- | python/analytics/index.py | 98 |
1 files changed, 49 insertions, 49 deletions
diff --git a/python/analytics/index.py b/python/analytics/index.py index 58cada76..f27bef6d 100644 --- a/python/analytics/index.py +++ b/python/analytics/index.py @@ -53,11 +53,11 @@ class Index(object): """ minimal class to represent a credit index """ __slots__ = ['fixed_rate', 'notional', '_start_date', '_end_date', 'recovery', '_version', '_fee_leg', '_default_leg', - '_trade_date', '_yc', '_sc', '_risky_annuity', '_spread', + '_value_date', '_yc', '_sc', '_risky_annuity', '_spread', '_price', 'name', 'issue_date', '_quote_is_price', '_direction', 'currency', '_step_in_date', '_accrued', - '_value_date', '_dl_pv', '_pv', '_clean_pv', - '_original_clean_pv', '_original_trade_date', + '_cash_settle_date', '_dl_pv', '_pv', '_clean_pv', + '_original_clean_pv', '_trade_date', 'index_type', 'series', 'tenor', '_observed'] def __init__(self, start_date, end_date, recovery, fixed_rate, notional=10e6, quote_is_price=False, issue_date=None): @@ -80,7 +80,7 @@ class Index(object): self._fee_leg = FeeLeg(self._start_date, end_date, True, 1., 1.) self._default_leg = ContingentLeg(self._start_date, end_date, True) - self._trade_date = None + self._value_date = None self._yc, self._sc = None, None self._risky_annuity = None self._spread, self._price = None, None @@ -88,9 +88,9 @@ class Index(object): self.issue_date = issue_date self._quote_is_price = quote_is_price self._direction = -1. - for attr in ['currency', '_step_in_date', '_value_date', '_accrued', + for attr in ['currency', '_step_in_date', '_cash_settle_date', '_accrued', '_dl_pv', '_pv', '_clean_pv', '_original_clean_pv', - '_original_trade_date', 'index_type', 'series', 'tenor']: + '_trade_date', 'index_type', 'series', 'tenor']: setattr(self, attr, None) self._observed = WeakSet() @@ -148,16 +148,16 @@ class Index(object): raise ValueError("Direction needs to be either 'Buyer' or 'Seller'") def _update(self): - self._sc = SpreadCurve(self.trade_date, self._yc, self.start_date, - self._step_in_date, self._value_date, + self._sc = SpreadCurve(self.value_date, self._yc, self.start_date, + self._step_in_date, self._cash_settle_date, [self.end_date], np.array([self._spread]), np.zeros(1), np.array([self.recovery])) - self._risky_annuity = self._fee_leg.pv(self.trade_date, self._step_in_date, - self._value_date, self._yc, + self._risky_annuity = self._fee_leg.pv(self.value_date, self._step_in_date, + self._cash_settle_date, self._yc, self._sc, False) self._dl_pv = self._default_leg.pv( - self.trade_date, self._step_in_date, self._value_date, + self.value_date, self._step_in_date, self._cash_settle_date, self._yc, self._sc, self.recovery) self._pv = self._dl_pv - self._risky_annuity * self.fixed_rate * 1e-4 self._clean_pv = self._pv + self._accrued * self.fixed_rate * 1e-4 @@ -209,16 +209,16 @@ class Index(object): if self._price is None or math.fabs(val-self._price) > 1e-6: self._clean_pv = (100 - val) / 100 self._sc = SpreadCurve( - self.trade_date, self._yc, self.start_date, - self._step_in_date, self._value_date, + self.value_date, self._yc, self.start_date, + self._step_in_date, self._cash_settle_date, [self.end_date], array.array('d',[self.fixed_rate*1e-4]), array.array('d', [self._clean_pv]), array.array('d', [self.recovery])) self._risky_annuity = self._fee_leg.pv( - self.trade_date, self._step_in_date, self._value_date, + self.value_date, self._step_in_date, self._cash_settle_date, self._yc, self._sc, False) self._dl_pv = self._default_leg.pv( - self.trade_date, self._step_in_date, self._value_date, + self.value_date, self._step_in_date, self._cash_settle_date, self._yc, self._sc, self.recovery) self._pv = self._clean_pv - self._accrued * self.fixed_rate * 1e-4 self._spread = self._clean_pv / (self._risky_annuity - self._accrued) \ @@ -250,13 +250,13 @@ class Index(object): @property def theta(self): - old_pv, old_trade_date = self.clean_pv, self.trade_date + old_pv, old_value_date = self.clean_pv, self.value_date with warnings.catch_warnings(): warnings.simplefilter("ignore") - self.trade_date = self.trade_date + relativedelta(days=1) + self.value_date = self.value_date + relativedelta(days=1) carry = self.notional * self._direction * self.fixed_rate * 1e-4/360 roll_down = self.clean_pv - old_pv - self.trade_date = old_trade_date + self.value_date = old_value_date return carry + roll_down @property @@ -265,7 +265,7 @@ class Index(object): # for rh in self._helpers: # rh.quote += 1e-4 # self._yc = ql_to_jp(self._ql_yc) - helpers = rate_helpers(self.currency, evaluation_date=self.trade_date) + helpers = rate_helpers(self.currency, evaluation_date=self.value_date) for rh in helpers: rh.quote += 1e-4 ql_yc = YC(helpers) @@ -301,32 +301,32 @@ class Index(object): return self._risky_annuity - self._accrued @property - def trade_date(self): - if self._trade_date is None: - raise AttributeError('Please set trade_date first') + def value_date(self): + if self._value_date is None: + raise AttributeError('Please set value_date first') else: - return self._trade_date + return self._value_date - @trade_date.setter - def trade_date(self, d): + @value_date.setter + def value_date(self, d): if isinstance(d, datetime.datetime): d = d.date() self.start_date = previous_twentieth(d) self._yc = get_curve(d, self.currency) # use the rolled forward curve if we price something in the future - if self._yc.base_date < d: - self._yc = self._yc.expected_forward_curve(d) - self._trade_date = d - self._step_in_date = self.trade_date + datetime.timedelta(days=1) + # if self._yc.base_date < d: + # self._yc = self._yc.expected_forward_curve(d) + self._value_date = d + self._step_in_date = d + datetime.timedelta(days=1) self._accrued = self._fee_leg.accrued(self._step_in_date) - self._value_date = pd.Timestamp(self._trade_date) + 3* BDay() + self._cash_settle_date = pd.Timestamp(self._value_date) + 3* BDay() if self._spread is not None: self._update() self.notify() def reset_pv(self): self._original_clean_pv = self._clean_pv - self._original_trade_date = self._trade_date + self._trade_date = self._value_date @property def pnl(self): @@ -334,7 +334,7 @@ class Index(object): raise ValueError("original pv not set") else: ## TODO: handle factor change - days_accrued = (self.trade_date - self._original_trade_date).days / 360 + days_accrued = (self.value_date - self._trade_date).days / 360 return - self._direction * self.notional * self.factor * \ (self._clean_pv - self._original_clean_pv - days_accrued * self.fixed_rate * 1e-4) @@ -347,7 +347,7 @@ class Index(object): self._observed.add(obj) def mark(self): - if self.trade_date == datetime.date.today(): + if self.value_date == datetime.date.today(): with init_bbg_session(BBG_IP) as session: security = self.name + " Corp" field = "PX_LAST" @@ -356,14 +356,14 @@ class Index(object): else: run = _engine.execute("""SELECT * FROM index_quotes WHERE index=%s AND series=%s AND tenor=%s AND date=%s""", - (self.index_type, self.series, self.tenor, self.trade_date)) + (self.index_type, self.series, self.tenor, self.value_date)) rec = run.fetchone() self.spread = rec.closespread @property def factor(self): for lastdate, factor, _ in self._version: - if lastdate >= self.trade_date: + if lastdate >= self.value_date: return factor else: return 1 @@ -371,13 +371,13 @@ class Index(object): @property def version(self): for lastdate, _, version in self._version: - if lastdate >= self.trade_date: + if lastdate >= self.value_date: return version else: return None @classmethod - def from_name(cls, index=None, series=None, tenor=None, trade_date=datetime.date.today(), + def from_name(cls, index=None, series=None, tenor=None, value_date=datetime.date.today(), notional=10_000_000, redcode=None, maturity=None): if all([index, series, tenor]): sql_str = "SELECT indexfactor, lastdate, maturity, coupon, " \ @@ -409,7 +409,7 @@ class Index(object): return None else: recovery = 0.4 if index_type in ['IG', 'EU'] else 0.3 - instance = cls(trade_date, maturity, recovery, coupon, notional, + instance = cls(value_date, maturity, recovery, coupon, notional, index_type == "HY", df.issue_date[0]) instance._version = tuple((ld.date(), factor / 100, version) for ld, factor, version in \ df[['lastdate', 'indexfactor', 'version']].itertuples(index=False)) @@ -428,7 +428,7 @@ class Index(object): instance.currency = "USD" else: instance.currency = "EUR" - instance.trade_date = trade_date + instance.value_date = value_date return instance @classmethod @@ -452,10 +452,10 @@ class Index(object): instance.name = rec.security_desc instance.currency = rec.currency instance.direction = rec.protection - instance.trade_date = rec.trade_date + instance.value_date = rec.trade_date instance.pv = rec.upfront instance._original_clean_pv = instance._clean_pv - instance._original_trade_date = rec.trade_date + instance._trade_date = rec.trade_date instance.index_type = index_type instance.series = rec.series instance.tenor = rec.tenor @@ -488,8 +488,8 @@ class Index(object): s += build_table(rows, format_strings, "{:<20}{:>19}\t\t{:<20}{:>15}") s += ["", colored("Calculator", attrs = ['bold'])] - rows = [["Valuation Date", self.trade_date], - ["Cash Settled On", self._value_date]] + rows = [["Valuation Date", self.value_date], + ["Cash Settled On", self._cash_settle_date]] format_strings = [[None, '{:%m/%d/%y}'], [None, '{:%m/%d/%y}']] s += build_table(rows, format_strings, "{:<20}\t{:>15}") @@ -524,8 +524,8 @@ class ForwardIndex(object): @classmethod def from_name(cls, index_type, series, tenor, forward_date, - trade_date=datetime.date.today(), notional=10e6): - index = Index.from_name(index_type, series, tenor, trade_date, notional) + value_date=datetime.date.today(), notional=10e6): + index = Index.from_name(index_type, series, tenor, value_date, notional) return cls(index, forward_date) @property @@ -552,12 +552,12 @@ class ForwardIndex(object): return hash(tuple(getattr(self, k) for k in ForwardIndex.__slots__ if k != '__weakref__')) def _update(self, *args): - if self.index.trade_date > self.forward_date: - return + if self.index.value_date > self.forward_date: + raise ValueError("Option expired") if self.index._sc is not None: step_in_date = self.forward_date + datetime.timedelta(days=1) - a = self.index._fee_leg.pv(self.index.trade_date, step_in_date, - self.index.trade_date, self.index._yc, self.index._sc, False) + a = self.index._fee_leg.pv(self.index.value_date, step_in_date, + self.index.value_date, self.index._yc, self.index._sc, False) Delta = self.index._fee_leg.accrued(step_in_date) q = self.index._sc.survival_probability(self.forward_date) self._forward_annuity = a - Delta * self.df * q |
