import argparse import logging import os import pandas as pd from pandas.tseries.offsets import BDay from analytics import Portfolio, BlackSwaption from db import dbconn, DataError logging.basicConfig(filename=os.path.join(os.getenv("LOG_DIR"), 'swaption_marks.log'), level=logging.INFO, format='%(asctime)s %(message)s') def get_swaption_portfolio(date, conn): with conn.cursor() as c: c.execute("SELECT id, dealid FROM swaptions WHERE termination_date is NULL " "AND expiration_date > %s AND trade_date <= %s", (date, date)) try: trade_ids, deal_ids = zip(*c) except ValueError: return {} portf = Portfolio([BlackSwaption.from_tradeid(t) for t in trade_ids], trade_ids=deal_ids) portf.value_date = date try: portf.mark(interp_method='bivariate_linear') except ValueError as e: logging.info(e) return {} return portf def insert_swaption_portfolio(portf, conn): sql_str = "INSERT INTO swaption_marks VALUES(%s, %s, %s, %s, %s, %s, %s)" with conn.cursor() as c: for id, trade in portf.items(): to_insert = (id, trade.value_date, trade.pv, trade.delta, trade.gamma, trade.vega, trade.theta) try: c.execute(sql_str, to_insert) except DataError as e: logging.error(e) finally: logging.info("succesfully marked trade id: %s", id) conn.commit() # 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 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 " \ # "LEFT JOIN swaption_quotes USING (quote_id) " \ # "LEFT JOIN swaption_ref_quotes USING (ref_id) "\ # "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: # result = r.fetchone() # if result is None: # logging.error("No data for {}{} {}K {} expiry on date {}". # format(index, series, strike, expiry, date)) # return result # except exc.DataError as e: # logging.error(e) # except e: # logging.error(e) # 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) # quote = get_swaptionvol(trade.index, trade.series, trade.strike, trade.expiration_date.date(), # date, serenitas_engine) # if quote is None: # continue # underlying.ref = quote.ref # swaption = Swaption(underlying, trade.expiration_date.date(), # trade.strike, trade.swaption_type.lower()) # swaption.sigma = getattr(quote, swaption.option_type) # if swaption.sigma is None: # swaption.sigma = quote.receiver if swaption.option_type == "payer" else quote.payer # direction = 1. if trade.buysell else -1. # market_value = swaption.pv * trade.notional * direction # if trade.index in ["HY", "XO"]: # market_value += (quote.ref - closeprice) / 100 * swaption.delta * trade.notional * direction # else: # market_value += swaption.DV01 * (closespread - quote.ref) * trade.notional * direction # #compute the greeks at index mark # swaption.index.spread = closespread # swaption._update() # try: # to_insert = (trade.Index, date, market_value, swaption.delta, swaption.gamma, # swaption.vega) # engine.execute("INSERT INTO swaption_marks VALUES(%s, %s, %s, %s, %s, %s)", # to_insert) # except exc.DataError as e: # logging.error(e) # finally: # logging.info("succesfully marked trade id: %s", trade.Index) # return result if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument('workdate', nargs='?', type=lambda s: pd.datetime.strptime(s, "%Y-%m-%d").date()), args = parser.parse_args() if args.workdate is None: workdate = (pd.Timestamp.today()-BDay()).date() else: workdate = args.workdate with dbconn('dawndb') as conn: portf = get_swaption_portfolio(workdate, conn) insert_swaption_portfolio(portf, conn)