aboutsummaryrefslogtreecommitdiffstats
path: root/python/analytics/portfolio.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/analytics/portfolio.py')
-rw-r--r--python/analytics/portfolio.py52
1 files changed, 46 insertions, 6 deletions
diff --git a/python/analytics/portfolio.py b/python/analytics/portfolio.py
index e2f35a68..66cdfe0c 100644
--- a/python/analytics/portfolio.py
+++ b/python/analytics/portfolio.py
@@ -1,15 +1,32 @@
-from .index import Index
+from .index import Index, _key_from_index
from .option import BlackSwaption, VolatilitySurface
from db import dbengine
from warnings import warn
+import pandas as pd
+import numpy as np
serenitasdb = dbengine('serenitasdb')
-def _key_from_index(index):
- _, index_type, _, series, tenor = index.name.split()
- series = int(series[1:])
- tenor = tenor.lower() + 'r'
- return index_type, series, tenor
+def portf_repr(method):
+ def f(*args):
+ obj = args[0]
+ thousands = lambda x: "{:,.2f}".format(x)
+ percent = lambda x: "N/A" if np.isnan(x) else f"{100*x:.2f}%"
+ header = "Portfolio {}\n\n".format(obj.trade_date)
+ kwargs = {'formatters': {'Notional': thousands,
+ 'PV': thousands,
+ 'Delta': percent,
+ 'Gamma': percent,
+ 'Theta': thousands,
+ 'Vega': thousands,
+ 'Vol': percent,
+ 'Ref': thousands},
+ 'index': False}
+ if method == 'string':
+ kwargs['line_width'] = 100
+ s = getattr(obj._todf(), 'to_' + method)(**kwargs)
+ return header + s
+ return f
class Portfolio:
def __init__(self, trades):
@@ -123,3 +140,26 @@ class Portfolio:
@property
def dv01(self):
return sum(t.dv01 for t in self.trades)
+
+ def _todf(self):
+ headers = ["Product", "Index", "Notional", "Ref", "Direction", "Expiry",
+ "Vol", "PV", "Delta", "Gamma", "Theta", "Vega"]
+ rec = []
+ for t in self.trades:
+ if isinstance(t, Index):
+ index_type, series, tenor = _key_from_index(t)
+ r = ("Index", f"{index_type}{series} {tenor}",
+ t.notional, t.ref, t.direction, "N/A", None, t.pv, 1., 0., t.theta, 0.)
+ elif isinstance(t, BlackSwaption):
+ index_type, series, tenor = _key_from_index(t.index)
+ r = ("Swaption", f"{index_type}{series} {tenor}",
+ t.notional, t.ref, t.direction, t.forward_date, t.sigma, t.pv,
+ t.delta, t.gamma, t.theta, t.vega)
+ else:
+ raise TypeError
+ rec.append(r)
+ return pd.DataFrame.from_records(rec, columns=headers)
+
+ __repr__ = portf_repr('string')
+
+ _repr_html_ = portf_repr('html')