aboutsummaryrefslogtreecommitdiffstats
path: root/python/mark_swaptions.py
blob: d9edade895c12f6d0cd91d5083828806870c530a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import argparse
import datetime
import logging
import os
import pandas as pd
from pandas.tseries.offsets import BDay

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.INFO,
                    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 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()),
    dawn_engine = dbengine('dawndb')
    serenitas_engine = dbengine('serenitasdb')
    args = parser.parse_args()
    if args.workdate is None:
        workdate = (pd.Timestamp.today()-BDay()).date()
    else:
        workdate = args.workdate

    r = mark_trades(workdate, dawn_engine)