aboutsummaryrefslogtreecommitdiffstats
path: root/python/risk/tranches.py
blob: edd83f50d77326b74c510683e5056d0764a7ae6b (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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
from analytics import Portfolio, DualCorrTranche
import logging

logger = logging.getLogger(__name__)


def get_tranche_portfolio(date, conn, by_strat=False, fund="SERCGMAST", **kwargs):
    if by_strat:
        sql_string = "SELECT * from list_tranche_positions_by_strat(%s, %s)"
    else:
        sql_string = "SELECT * FROM list_cds(%s, %s) WHERE orig_attach IS NOT NULL "

    with conn.cursor() as c:
        c.execute(sql_string, (date, fund))
        trade_ids = list(c)

    portf = Portfolio(
        [
            DualCorrTranche(
                redcode=t.security_id,
                maturity=t.maturity,
                notional=t.notional,
                tranche_running=t.fixed_rate * 100,
                attach=t.orig_attach,
                detach=t.orig_detach,
                corr_attach=None,
                corr_detach=None,
                value_date=t.trade_date,
                trade_id=t.id,
            )
            for t in trade_ids
        ]
    )
    if by_strat:
        portf.trade_ids = [
            (tid.folder, f"{t.index_type} {t.series} {t.tenor} {t.attach}-{t.detach}")
            for tid, t in zip(trade_ids, portf.trades)
        ]
    else:
        portf.trade_ids = [(t.folder, t.id) for t in trade_ids]
    portf.value_date = date
    portf.mark(**kwargs)
    return portf


def insert_tranche_portfolio(portf, conn):
    cols = [
        "date",
        "tranche_id",
        "notional",
        "clean_nav",
        "accrued",
        "duration",
        "delta",
        "gamma",
        "theta",
        "theta_amount",
        "corr01",
        "tranche_factor",
        "upfront",
        "running",
        "corr_attach",
        "corr_detach",
        "index_refprice",
        "index_refspread",
        "index_duration",
        "hy_equiv",
    ]
    update_str = ",".join(f"{c} = EXCLUDED.{c}" for c in cols[2:])
    sql_str = (
        f"INSERT INTO tranche_risk({','.join(cols)}) "
        f"VALUES({','.join(['%s'] * len(cols))}) "
        " ON CONFLICT (date, tranche_id) DO UPDATE "
        f"SET {update_str}"
    )

    with conn.cursor() as c:
        for (strat, trade_id), trade in portf.items():
            logger.info(f"marking tranche {trade_id} in {strat}")
            try:
                theta = trade.theta(method="TLP")
            except (ValueError, RuntimeError) as e:
                # when there is less than one year left we computed the theta to maturity
                logger.info(str(e))
                theta = (
                    trade.clean_pv
                    / trade.notional
                    / trade.tranche_factor
                    / trade._index._fx
                    + trade.tranche_running * 1e-4 * trade.duration
                )
            c.execute(
                sql_str,
                (
                    trade.value_date,
                    trade_id,
                    trade.notional,
                    trade.clean_pv,
                    trade.accrued,
                    trade.duration,
                    trade.delta,
                    trade.gamma,
                    theta,
                    -theta * trade.notional * trade.tranche_factor * trade._index._fx,
                    trade.corr01,
                    trade.tranche_factor,
                    trade.upfront,
                    trade.tranche_running,
                    trade.rho[0],
                    trade.rho[1],
                    100 - float(trade._index.pv()) * 100,
                    trade._index._snacspread(
                        trade._index.coupon(), trade._index.recovery, trade.maturity
                    )
                    * 10000,
                    float(trade._index.duration()),
                    trade.hy_equiv,
                ),
            )
    conn.commit()