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
121
122
123
124
125
126
127
128
|
import datetime
import pandas as pd
import numpy as np
import argparse
from risk.portfolio import build_portfolio, generate_vol_surface
import serenitas.analytics as ana
from serenitas.analytics.scenarios import run_portfolio_scenarios
from serenitas.analytics.base import Trade
from serenitas.utils.db2 import dbconn
from serenitas.utils.db import dawn_engine
from serenitas.analytics.dates import prev_business_day
def parse_args():
"""Parses command line arguments"""
parser = argparse.ArgumentParser(description="Shock data and insert into DB")
parser.add_argument(
"date",
nargs="?",
type=datetime.date.fromisoformat,
default=prev_business_day(datetime.date.today()),
)
parser.add_argument("-n", "--no-upload", action="store_true", help="do not upload")
return parser.parse_args()
def gen_spreads(shock_date, fund):
Trade.init_ontr(shock_date)
ana._local = False
spread_shock = np.array([-100.0, -25.0, 1.0, +25.0, 100.0, 200.0, 500, 1000])
spread_shock /= Trade._ontr["HY"].spread
portf, _ = build_portfolio(shock_date, shock_date, fund)
vol_surface = generate_vol_surface(portf, 10, "BAML")
portf.reset_pv()
scens = run_portfolio_scenarios(
portf,
date_range=[pd.Timestamp(shock_date)],
params=["pnl", "hy_equiv"],
spread_shock=spread_shock,
vol_shock=[0.0],
corr_shock=[0.0],
vol_surface=vol_surface,
)
strategies = {}
strategies["options"] = [
"HYOPTDEL",
"HYPAYER",
"HYREC",
"IGOPTDEL",
"IGPAYER",
"IGREC",
]
strategies["tranches"] = [
"HYSNR",
"HYMEZ",
"HYINX",
"HYEQY",
"IGSNR",
"IGMEZ",
"IGINX",
"IGEQY",
"EUSNR",
"EUMEZ",
"EUINX",
"EUEQY",
"XOSNR",
"XOMEZ",
"XOINX",
"XOEQY",
"BSPK",
]
if fund == "BRINKER":
scens = scens.xs(0, level="corr_shock")
else:
scens = scens.xs((0.0, 0.0), level=["vol_shock", "corr_shock"])
scens.columns.names = ["strategy", "trade_id", "scen_type"]
results = {}
for i, g in scens.groupby(level="scen_type", axis=1):
temp = g.groupby(level="strategy", axis=1).sum()
for key, item in strategies.items():
exist_columns = set(temp.columns).intersection(item)
temp[key] = temp[exist_columns].sum(axis=1)
temp.drop(exist_columns, axis=1, inplace=True)
temp["total"] = temp.sum(axis=1)
results[i] = temp
results = pd.concat(results)
return results
def process_dataframe(raw_df):
"""Clean and transform the input dataframe to insert into database."""
transformed_df = raw_df.reset_index()
transformed_df = transformed_df.rename(columns={"level_0": "unit"})
strategy_columns = transformed_df.columns[3:]
transformed_df = pd.melt(
transformed_df,
id_vars=["unit", "date", "spread_shock"],
value_vars=strategy_columns,
)
transformed_df = transformed_df.rename(
columns={"variable": "strategy", "value": "value", "unit": "risk_type"}
)
transformed_df.risk_type = transformed_df.risk_type.str.upper()
return transformed_df
if __name__ == "__main__":
args = parse_args()
conn = dbconn("dawndb")
for fund in ("SERCGMAST", "BOWDST", "ISOSEL", "BRINKER"):
results = gen_spreads(args.date, fund)
with conn.cursor() as c:
c.execute(
"DELETE FROM shocks WHERE fund=%s and date=%s",
(
fund,
args.date,
),
)
df = process_dataframe(results)
df["fund"] = fund
df.to_sql("shocks", dawn_engine, if_exists="append", index=False)
conn.commit()
|