aboutsummaryrefslogtreecommitdiffstats
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/db.py3
-rw-r--r--python/mark_swaptions.py85
-rw-r--r--python/pnl_explain.py3
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"""