aboutsummaryrefslogtreecommitdiffstats
path: root/python/risk/tranches.py
blob: 0f4292c493db6586867769466113766e4e133283 (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
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,
            )
            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",
        "corr01",
        "tranche_factor",
        "upfront",
        "running",
        "corr_attach",
        "corr_detach",
        "index_refprice",
        "index_refspread",
        "index_duration",
    ]
    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:
                logger.info(str(e))
                theta = (
                    trade.clean_pv / trade.notional / trade.duration
                    + trade.tranche_running * 1e-4
                )
            c.execute(
                sql_str,
                (
                    trade.value_date,
                    trade_id,
                    trade.notional,
                    trade.clean_pv,
                    trade.accrued,
                    trade.duration,
                    trade.delta,
                    trade.gamma,
                    theta,
                    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()),
                ),
            )
    conn.commit()