aboutsummaryrefslogtreecommitdiffstats
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/risk/swaptions.py76
1 files changed, 52 insertions, 24 deletions
diff --git a/python/risk/swaptions.py b/python/risk/swaptions.py
index 0b3752c3..9e5290d3 100644
--- a/python/risk/swaptions.py
+++ b/python/risk/swaptions.py
@@ -1,45 +1,73 @@
import logging
-from serenitas.analytics.api import Portfolio, BlackSwaption
+from itertools import chain
+from serenitas.analytics.api import Portfolio, BlackSwaption, CreditIndex
from serenitas.utils.db2 import DataError
from psycopg import sql
logger = logging.getLogger(__name__)
-def get_swaption_portfolio(date, conn, fund="SERCGMAST", portfolio=None, **kwargs):
- if portfolio is None:
- params = (date, date, date, fund)
- and_clause = ""
- else:
- params = (date, date, date, fund, portfolio)
- and_clause = "AND portfolio=%s"
+def get_swaption_portfolio(date, conn, **kwargs):
+ params = [date, date, date]
+ and_clause = []
+ for key in ["fund", "portfolio"]:
+ if key in kwargs:
+ params.append(kwargs[key])
+ and_clause.append(f"AND {key}=%s")
with conn.cursor() as c:
c.execute(
- "SELECT swaptions.id, folder, dealid, (notional - terminated_amount) AS notional "
+ "SELECT security_id AS redcode, maturity,"
+ " array_agg(swaptions.id) AS ids,"
+ " array_agg(folder::text) AS folders,"
+ " array_agg(buysell) AS buysells,"
+ " array_agg(option_type::text) AS option_types,"
+ " array_agg(notional - COALESCE(terminated_amount, 0.0)) AS notionals,"
+ " array_agg(fund::text) AS funds, "
+ " array_agg(expiration_date) AS expiries, "
+ " array_agg(strike) AS strikes "
"FROM swaptions LEFT JOIN ("
"SELECT dealid, SUM(termination_amount) AS terminated_amount "
"FROM terminations WHERE termination_date <= %s GROUP BY dealid) b "
"USING (dealid) "
- "WHERE notional IS DISTINCT FROM terminated_amount "
+ "WHERE (terminated_amount IS NULL OR notional > terminated_amount) "
"AND expiration_date > %s AND trade_date <= %s "
"AND swap_type='CD_INDEX_OPTION' "
- f"AND fund=%s {and_clause} "
- "ORDER BY expiration_date, strike",
+ f"{' '.join(and_clause)} "
+ "GROUP BY security_id, maturity",
params,
)
- try:
- trade_ids, folders, deal_ids, notionals = zip(*c)
- except ValueError:
- return {}
+ trades = []
+ trade_ids = []
+ for row in c:
+ index = CreditIndex(
+ redcode=row.redcode, maturity=row.maturity, value_date=date
+ )
+ index.mark()
+ trades.append(
+ [
+ BlackSwaption(
+ index,
+ expiry,
+ strike,
+ ot.lower(),
+ "Long" if direction else "Short",
+ notional,
+ )
+ for expiry, strike, ot, direction, notional in zip(
+ row.expiries,
+ row.strikes,
+ row.option_types,
+ row.buysells,
+ row.notionals,
+ )
+ ]
+ )
+ trade_ids.append(zip(row.folders, row.ids, row.funds))
portf = Portfolio(
- [BlackSwaption.from_tradeid(t) for t in trade_ids], list(zip(folders, deal_ids))
+ list(chain.from_iterable(trades)), list(chain.from_iterable(trade_ids))
)
- for t, ntl in zip(portf.trades, notionals):
- if ntl is not None:
- t.notional = ntl
- portf.value_date = date
- portf.mark(interp_method="bivariate_linear", **kwargs)
+ portf.mark(interp_method="bivariate_linear", mark_index=False, **kwargs)
return portf
@@ -61,9 +89,9 @@ def insert_swaption_portfolio(portf, conn, overwrite=True):
"INSERT INTO swaption_marks VALUES({}) ON CONFLICT (dealid, date) {} "
).format(place_holders, update_str)
with conn.cursor() as c:
- for id, trade in portf.items():
+ for (strat, tid, fund), trade in portf.items():
to_insert = (
- id[1],
+ f"SWPTN{tid}",
trade.value_date,
trade.pv,
trade.delta,