diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/db.py | 3 | ||||
| -rw-r--r-- | python/mark_swaptions.py | 85 | ||||
| -rw-r--r-- | python/pnl_explain.py | 3 |
3 files changed, 83 insertions, 8 deletions
diff --git a/python/db.py b/python/db.py index 3c937ba1..0ba5f7b3 100644 --- a/python/db.py +++ b/python/db.py @@ -3,7 +3,7 @@ import os import psycopg2 from psycopg2.extras import DictCursor from psycopg2 import IntegrityError -from psycopg2.extensions import register_adapter +from psycopg2.extensions import register_adapter, AsIs from sqlalchemy import create_engine from sqlalchemy.engine.url import URL import numpy as np @@ -20,6 +20,7 @@ class InfDateAdapter: return psycopg2.extensions.DateFromPy(self.wrapped).getquoted() register_adapter(datetime.date, InfDateAdapter) +register_adapter(np.int64, lambda x: AsIs(x)) def dbconn(dbname): if dbname == 'etdb': diff --git a/python/mark_swaptions.py b/python/mark_swaptions.py index a7bb2b72..481979dd 100644 --- a/python/mark_swaptions.py +++ b/python/mark_swaptions.py @@ -1,17 +1,94 @@ +import argparse import datetime +import logging +import os import pandas as pd + from analytics import Index, Swaption from db import dbengine +from sqlalchemy import exc +logging.basicConfig(filename=os.path.join(os.getenv("LOG_DIR"), 'swaption_marks.log'), + level=logging.WARNING, + format='%(asctime)s %(message)s') def get_trades(date, engine): return pd.read_sql_query( "SELECT dealid, buysell, swaption_type, notional, strike, " \ "expiration_date, index, series FROM swaptions " \ "JOIN index_version ON (swaptions.security_id = index_version.redindexcode) " \ - "WHERE termination_date is NULL and expiration_date > %s", - engine, 'dealid', params=(date,), parse_dates=['expiration_date']) + "WHERE termination_date is NULL AND expiration_date > %s AND trade_date <= %s", + engine, 'dealid', params=(date, date), parse_dates=['expiration_date']) + + +def get_swaptionvol(index, series, strike, expiry, date, engine): + r = engine.execute( + "SELECT ref, vol_payer AS payer, vol_receiver AS receiver, " \ + "vol_payer_black AS payer_black, vol_receiver_black AS receiver_black " \ + "FROM swaption_calib JOIN swaption_ref_quotes " \ + "USING (quotedate, expiry, index, series) WHERE index = %s " \ + "AND series = %s AND strike=%s AND expiry = %s AND quotedate::date=%s " \ + "ORDER BY quotedate desc", + (index, series, strike, expiry, date)) + try: + return r.fetchone() + except exc.DataError as e: + logging.error(e) + return None + except TypeError: + logging.error("No data for {}{} {}K on date {}".format(index, series, strike, date)) + return None + +def mark_trades(date, engine): + df = get_trades(date, engine) + result = [] + for trade in df.itertuples(): + try: + r = engine.execute("SELECT closespread, closeprice FROM index_quotes " \ + "WHERE index=%s AND series=%s AND tenor='5yr' AND date=%s", + (trade.index, trade.series, date)) + closespread, closeprice = r.fetchone() + except exc.DataError as e: + logging.eror(e) + except TypeError: + logging.error("no quote for {}{} {} on date {}".format( + trade.index, trade.series, '5yr', date)) + underlying = Index.from_name(trade.index, trade.series, '5yr', date, + trade.notional) + sigma = get_swaptionvol(trade.index, trade.series, trade.strike, trade.expiration_date.date(), + date, serenitas_engine) + if trade.index == "IG": + underlying.spread = sigma.ref + elif trade.index == "HY": + underlying.price = sigma.ref + swaption = Swaption(underlying, trade.expiration_date.date(), + trade.strike, trade.swaption_type.lower()) + swaption.sigma = getattr(sigma, swaption.option_type) + direction = 1. if trade.buysell else -1. + market_value = swaption.pv * trade.notional * direction + market_value += swaption.DV01 * (closespread-sigma.ref) * trade.notional * direction + #compute the greeks at index mark + swaption.index.spread = closespread + swaption._update() + + try: + test = (trade.Index, date, market_value, swaption.delta, swaption.gamma, + swaption.vega) + engine.execute("INSERT INTO swaption_marks VALUES(%s, %s, %s, %s, %s, %s)", + (trade.Index, date, market_value, swaption.delta, swaption.gamma, + swaption.vega)) + except exc.DataError as e: + logging.error(e) + return result if __name__ == "__main__": - engine = dbengine('dawndb') - df = get_trades(datetime.date.today(), engine) + parser = argparse.ArgumentParser() + parser.add_argument('workdate', nargs='?', type = lambda s: pd.datetime.strptime(s, "%Y-%m-%d").date()) + dawn_engine = dbengine('dawndb') + serenitas_engine = dbengine('serenitasdb') + args = parser.parse_args() + if args.workdate is None: + workdate = datetime.date.today() + else: + workdate = args.workdate + r = mark_trades(workdate, dawn_engine) diff --git a/python/pnl_explain.py b/python/pnl_explain.py index 1c96deda..0be46854 100644 --- a/python/pnl_explain.py +++ b/python/pnl_explain.py @@ -3,9 +3,6 @@ import pandas as pd from db import dbengine from dates import bus_day, imm_dates, yearfrac -from psycopg2.extensions import register_adapter, AsIs - -register_adapter(np.int64, lambda x: AsIs(x)) def get_daycount(identifier, engine = dbengine("dawndb")): """ retrieve daycount and paydelay for a given identifier""" |
