diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/analytics/option.py | 3 | ||||
| -rw-r--r-- | python/analytics/portfolio.py | 57 |
2 files changed, 56 insertions, 4 deletions
diff --git a/python/analytics/option.py b/python/analytics/option.py index e7c87fbb..14e64d54 100644 --- a/python/analytics/option.py +++ b/python/analytics/option.py @@ -424,6 +424,8 @@ class VolatilitySurface(ForwardIndex): engine, parse_dates = ['quotedate', 'expiry'], params=(trade_date, index_type.upper(), series)) + if self._quotes.empty: + raise ValueError("No quotes for that day") self._quotes['quotedate'] = (self._quotes['quotedate']. dt.tz_convert('America/New_York'). dt.tz_localize(None)) @@ -479,6 +481,7 @@ class VolatilitySurface(ForwardIndex): quotes = quotes.assign(mid = quotes[['pay_bid','pay_offer']].mean(1) * 1e-4) else: quotes = quotes.assign(mid = quotes[['rec_bid','rec_offer']].mean(1) * 1e-4) + quotes = quotes.dropna(subset=['mid']) with Pool(4) as p: for expiry, df in quotes.groupby(['expiry']): atm_strike = ATMstrike(self._index, expiry.date()) diff --git a/python/analytics/portfolio.py b/python/analytics/portfolio.py index e7abf0a2..0688c868 100644 --- a/python/analytics/portfolio.py +++ b/python/analytics/portfolio.py @@ -1,11 +1,35 @@ from .index import Index -from .option import BlackSwaption +from .option import BlackSwaption, VolatilitySurface +from db import dbengine +from warnings import warn + +serenitasdb = dbengine('serenitasdb') + +def _key_from_index(index): + _, index_type, _, series, tenor = index.name.split() + series = int(series[1:]) + tenor = tenor.lower() + 'r' + return index_type, series, tenor class Portfolio: def __init__(self, trades): self.trades = trades self.indices = [t for t in trades if isinstance(t, Index)] self.swaptions = [t for t in trades if isinstance(t, BlackSwaption)] + self._keys = [] + for index in self.indices: + self._keys.append(_key_from_index(index)) + #pick the first available trade_date + trade_dates = set() + for index in self.indices: + trade_dates.add(index.trade_date) + for swaption in self.swaptions: + trade_dates.add(swaption.index.trade_date) + self._trade_date = trade_dates.pop() + if len(trade_dates) >= 1: + warn("not all instruments have the same trade date, picking {}". + format(self._trade_date)) + self._vs = {} @property def pnl(self): @@ -29,15 +53,40 @@ class Portfolio: @property def trade_date(self): - return self.index.trade_date + return self._trade_date @trade_date.setter def trade_date(self, d): + #we try to keep everybody in sync for index in self.indices: index.trade_date = d + if len(self.indices) == 0: + for swaption in self.swaptions: + self.swaption.trade_date = d + self._trade_date = d - def mark(self): - pass + def mark(self, source=None, option_type=None, model=None, surface_id=None): + vs_dict = {} + for index, (index_type, series, tenor) in zip(self.indices, self._keys): + run = serenitasdb.execute("""SELECT * FROM index_quotes + WHERE index=%s AND series=%s AND tenor=%s AND date=%s""", + (index_type, series, tenor, self.trade_date)) + rec = run.fetchone() + index.spread = rec.closespread + k = (self.trade_date, index_type, series, tenor) + if k not in self._vs: + vs = VolatilitySurface(index_type, series, tenor, self.trade_date) + if surface_id is None and len(vs.list(source, option_type, model)) >=1: + surface_id = vs.list(source, option_type, model)[-1] + else: + raise ValueError("No market data available for this day") + self._vs[k] = vs[surface_id] + for swaption in self.swaptions: + vol_surface = self._vs[(swaption.index.trade_date, ) + \ + _key_from_index(swaption.index)] + swaption.sigma = float(self._vs[(swaption.index.trade_date, ) \ + + _key_from_index(swaption.index)]. + ev(swaption.T, swaption.moneyness)) @property def ref(self): |
