aboutsummaryrefslogtreecommitdiffstats
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/analytics/index.py27
-rw-r--r--python/cds_curve.py10
-rw-r--r--python/yieldcurve.py68
3 files changed, 60 insertions, 45 deletions
diff --git a/python/analytics/index.py b/python/analytics/index.py
index a9b6ab6a..87f5471d 100644
--- a/python/analytics/index.py
+++ b/python/analytics/index.py
@@ -8,8 +8,6 @@ import warnings
from dateutil.relativedelta import relativedelta
from pyisda.legs import ContingentLeg, FeeLeg
-from quantlib.settings import Settings
-from quantlib.time.api import Date, Actual365Fixed
from termcolor import colored
from pandas.tseries.offsets import BDay
from sqlalchemy import exc
@@ -21,6 +19,7 @@ from bbg_helpers import BBG_IP, retrieve_data, init_bbg_session
from yieldcurve import get_curve, rate_helpers, YC, ql_to_jp
from weakref import WeakSet
+
def g(index, spread, exercise_date, pv=None):
"""computes the strike clean price using the expected forward yield curve. """
step_in_date = exercise_date + datetime.timedelta(days=1)
@@ -173,7 +172,7 @@ class Index(object):
@property
def flat_hazard(self):
sc_data = self._sc.inspect()['data']
- ## conversion to continuous compounding
+ # conversion to continuous compounding
return sc_data[0][1]
@property
@@ -210,7 +209,7 @@ class Index(object):
self._sc = SpreadCurve(
self.value_date, self._yc, self.start_date,
self._step_in_date, self._cash_settle_date,
- [self.end_date], array.array('d',[self.fixed_rate*1e-4]),
+ [self.end_date], array.array('d', [self.fixed_rate*1e-4]),
array.array('d', [self._clean_pv]),
array.array('d', [self.recovery]))
self._risky_annuity = self._fee_leg.pv(
@@ -269,7 +268,7 @@ class Index(object):
rh.quote += 1e-4
ql_yc = YC(helpers)
self._yc = ql_to_jp(ql_yc)
- self._update() ## to force recomputation
+ self._update() # to force recomputation
new_pv = self.pv
# for r in self._helpers:
# r.quote -= 1e-4
@@ -279,7 +278,7 @@ class Index(object):
@property
def rec_risk(self):
- old_pv, old_recovery = self.pv, self.recovery
+ old_recovery = self.recovery
self.recovery = old_recovery - 0.01
self._update()
pv_minus = self.pv
@@ -315,7 +314,7 @@ class Index(object):
self._value_date = d
self._step_in_date = d + datetime.timedelta(days=1)
self._accrued = self._fee_leg.accrued(self._step_in_date)
- self._cash_settle_date = pd.Timestamp(self._value_date) + 3* BDay()
+ self._cash_settle_date = pd.Timestamp(self._value_date) + 3 * BDay()
if self._spread is not None:
self._update()
self.notify()
@@ -329,7 +328,7 @@ class Index(object):
if self._original_clean_pv is None:
raise ValueError("original pv not set")
else:
- ## TODO: handle factor change
+ # TODO: handle factor change
days_accrued = (self.value_date - self._trade_date).days / 360
return - self._direction * self.notional * self.factor * \
(self._clean_pv - self._original_clean_pv -
@@ -397,7 +396,7 @@ class Index(object):
coupon = df.coupon[0]
if tenor is None:
tenor = df.tenor[0]
- index_type = index.upper() if index else df.loc[0,'index']
+ index_type = index.upper() if index else df.loc[0, 'index']
series = series if series else df.series.iat[0]
df.loc[df.lastdate.isnull(), 'lastdate'] = maturity
except exc.DataError as e:
@@ -408,7 +407,7 @@ class Index(object):
instance = cls(value_date, maturity, recovery, coupon, notional,
index_type == "HY", df.issue_date[0])
instance._version = tuple((ld.date(), factor / 100, version) for ld, factor, version in \
- df[['lastdate', 'indexfactor', 'version']].itertuples(index=False))
+ df[['lastdate', 'indexfactor', 'version']].itertuples(index=False))
instance.index_type = index_type
instance.series = series
instance.tenor = tenor
@@ -428,7 +427,7 @@ class Index(object):
@classmethod
def from_tradeid(cls, trade_id):
- engine = dbengine('dawndb')
+ engine = dbengine('dawndb')
r = engine.execute("""
SELECT * FROM cds
LEFT JOIN index_desc
@@ -465,7 +464,7 @@ class Index(object):
accrued_str = "Accrued ({} Day)".format(self.days_accrued)
s = ["{:<20}\tNotional {:>5}MM {}\tFactor {:>28}".format("Buy Protection"\
- if self._direction == -1 \
+ if self._direction == -1
else "Sell Protection",
self.notional/1_000_000,
self.currency,
@@ -482,7 +481,7 @@ class Index(object):
[None, None, None, None]]
s += build_table(rows, format_strings, "{:<20}{:>19}\t\t{:<20}{:>15}")
s += ["",
- colored("Calculator", attrs = ['bold'])]
+ colored("Calculator", attrs=['bold'])]
rows = [["Valuation Date", self.value_date],
["Cash Settled On", self._cash_settle_date]]
format_strings = [[None, '{:%m/%d/%y}'],
@@ -511,7 +510,7 @@ class ForwardIndex(object):
self.forward_date = forward_date.date()
else:
self.forward_date = forward_date
- self.exercise_date_settle = pd.Timestamp(forward_date) + 3* BDay()
+ self.exercise_date_settle = pd.Timestamp(forward_date) + 3 * BDay()
self.df = index._yc.discount_factor(self.exercise_date_settle)
self._update()
if observer:
diff --git a/python/cds_curve.py b/python/cds_curve.py
index 235f8fa0..ab13a9ef 100644
--- a/python/cds_curve.py
+++ b/python/cds_curve.py
@@ -2,12 +2,11 @@ from analytics.basket_index import MarkitBasketIndex
from pyisda.legs import FeeLeg, ContingentLeg
from pyisda.logging import enable_logging
-import datetime
-import numpy as np
import pandas as pd
from db import dbconn
+
def all_curves_pv(curves, today_date, jp_yc, start_date, step_in_date, value_date, maturities):
r = {}
for d in maturities:
@@ -26,7 +25,7 @@ def all_curves_pv(curves, today_date, jp_yc, start_date, step_in_date, value_dat
r[pd.Timestamp(d)] = pd.DataFrame.from_records(data,
index=tickers,
columns=['duration', 'protection_pv'])
- return pd.concat(r, axis=1).swaplevel(axis=1).sort_index(axis=1,level=0)
+ return pd.concat(r, axis=1).swaplevel(axis=1).sort_index(axis=1, level=0)
def calibrate_portfolio(index_type, series, tenors=['3yr', '5yr', '7yr', '10yr'],
@@ -43,7 +42,8 @@ def calibrate_portfolio(index_type, series, tenors=['3yr', '5yr', '7yr', '10yr']
'tweak': index.tweaks}, index=tenors)
return pd.concat(r)
-if __name__=="__main__":
+
+if __name__ == "__main__":
enable_logging()
import argparse
import sys
@@ -70,7 +70,7 @@ if __name__=="__main__":
with conn.cursor() as c:
for k, s in df.iterrows():
- c.execute("UPDATE index_quotes SET duration2=%s, theta2=%s "\
+ c.execute("UPDATE index_quotes SET duration2=%s, theta2=%s "
"WHERE date=%s AND tenor=%s AND index=%s AND series=%s",
(s.duration, s.theta, k[0], k[1], index, series))
conn.commit()
diff --git a/python/yieldcurve.py b/python/yieldcurve.py
index 7ef24a59..6e0cc3bf 100644
--- a/python/yieldcurve.py
+++ b/python/yieldcurve.py
@@ -23,12 +23,13 @@ from pyisda.curve import YieldCurve
from pyisda.date import BadDay
import warnings
+
def load_curves(currency="USD", date=None):
"""load the prebuilt curves from the database"""
+ sql_str = f"SELECT * FROM {currency}_curves"
if date:
- sql_str = "SELECT curve FROM {}_curves WHERE effective_date=%s".format(currency)
- else:
- sql_str = "SELECT * FROM {}_curves".format(currency)
+ sql_str += " WHERE effective_date=%s"
+
with closing(dbconn('serenitasdb')) as conn:
with conn.cursor() as c:
if date:
@@ -42,6 +43,7 @@ def load_curves(currency="USD", date=None):
(d, YieldCurve.from_bytes(lz4.block.decompress(curve)))
for d, curve in c])
+
def get_curve(effective_date, currency="USD"):
if f'_{currency}_curves' in globals():
curves = globals()[f'_{currency}_curves']
@@ -64,6 +66,7 @@ def get_curve(effective_date, currency="USD"):
curves[effective_date] = jp_yc
return jp_yc
+
def getMarkitIRData(effective_date=datetime.date.today(),
currency="USD"):
conn = dbconn("serenitasdb")
@@ -80,6 +83,7 @@ def getMarkitIRData(effective_date=datetime.date.today(),
if rate is not None]}
return MarkitData
+
def get_futures_data(date=datetime.date.today()):
futures_file = os.path.join(os.environ['DATA_DIR'], "Yield Curves",
"futures-{0:%Y-%m-%d}.csv".format(date))
@@ -87,6 +91,7 @@ def get_futures_data(date=datetime.date.today()):
quotes = [float(line.split(",")[1]) for line in fh]
return quotes
+
def rate_helpers(currency="USD", MarkitData=None, evaluation_date=None):
"""Utility function to build a list of RateHelpers
@@ -108,7 +113,7 @@ def rate_helpers(currency="USD", MarkitData=None, evaluation_date=None):
if not MarkitData:
MarkitData = getMarkitIRData(evaluation_date, currency)
if MarkitData['effectiveasof'] != evaluation_date:
- warnings.warn("Yield curve effective date: {0} doesn't " \
+ warnings.warn("Yield curve effective date: {0} doesn't "
"match the evaluation date: {1}".format(
MarkitData['effectiveasof'],
evaluation_date),
@@ -116,21 +121,23 @@ def rate_helpers(currency="USD", MarkitData=None, evaluation_date=None):
settings.evaluation_date = Date.from_datetime(MarkitData['effectiveasof'])
calendar = WeekendsOnly()
if currency == "USD":
- isda_ibor = IborIndex("IsdaIbor", Period(3, Months), 2, USDCurrency(), calendar,
- ModifiedFollowing, False, Actual360())
+ isda_ibor = IborIndex("IsdaIbor", Period(3, Months), 2, USDCurrency(),
+ calendar, ModifiedFollowing, False, Actual360())
fix_freq = Semiannual
elif currency == "EUR":
- isda_ibor = IborIndex("IsdaIbor", Period(6, Months), 2, EURCurrency(), calendar,
- ModifiedFollowing, False, Actual360())
+ isda_ibor = IborIndex("IsdaIbor", Period(6, Months), 2, EURCurrency(),
+ calendar, ModifiedFollowing, False, Actual360())
fix_freq = Annual
# we use SimpleQuotes, rather than just float to make it updateable
- deps = [DepositRateHelper(SimpleQuote(q), Period(t), 2, calendar, ModifiedFollowing, False, Actual360())
+ deps = [DepositRateHelper(SimpleQuote(q), Period(t), 2, calendar,
+ ModifiedFollowing, False, Actual360())
for t, q in MarkitData['deposits']]
# this matches with bloomberg, but according to Markit, maturity should be unadjusted
swaps = [SwapRateHelper.from_tenor(SimpleQuote(q), Period(t), calendar, fix_freq, ModifiedFollowing,
Thirty360(), isda_ibor) for t, q in MarkitData['swaps']]
return deps + swaps
+
def get_dates(date, currency="USD"):
"""computes the list of curve dates on a given date"""
if currency == "USD":
@@ -139,20 +146,22 @@ def get_dates(date, currency="USD"):
calendar = WeekendsOnly()
settle_date = calendar.advance(Date.from_datetime(date), 2, 0)
deposit_dates = [calendar.advance(settle_date, period=Period(m, Months),
- convention=ModifiedFollowing) \
+ convention=ModifiedFollowing)
for m in month_periods]
swap_dates = [calendar.advance(settle_date, period=Period(y, Years),
- convention=ModifiedFollowing) \
- for y in year_periods]
+ convention=ModifiedFollowing)
+ for y in year_periods]
dates = deposit_dates + swap_dates
return [pydate_from_qldate(d) for d in dates]
+
def roll_yc(yc, forward_date):
"""returns the expected forward yield cuve on a forward_date"""
dates = [d for d in yc.dates if d >= forward_date]
dfs = np.array([yc.discount_factor(d, forward_date) for d in dates])
return YieldCurve.from_discount_factors(forward_date, dates, dfs, 'ACT/365F')
+
def YC(helpers=None, currency="USD", MarkitData=None, evaluation_date=None):
if helpers is None:
helpers = rate_helpers(currency, MarkitData, evaluation_date)
@@ -163,25 +172,27 @@ def YC(helpers=None, currency="USD", MarkitData=None, evaluation_date=None):
return PiecewiseYieldCurve(BootstrapTrait.Discount, Interpolator.LogLinear,
0, calendar, helpers, Actual365Fixed())
+
def jpYC(effective_date, currency="USD", MarkitData=None):
if MarkitData is None:
markit_data = getMarkitIRData(effective_date,
currency)
periods, rates = zip(*markit_data['deposits'])
- periods_swaps, rate_swaps = zip(*markit_data['swaps'])
+ periods_swaps, rates_swaps = zip(*markit_data['swaps'])
types = 'M'*len(periods) + 'S'*len(periods_swaps)
rates = np.array(rates + rates_swaps)
- periods = list(period + periods_swaps)
+ periods = list(periods + periods_swaps)
if currency == "USD":
fixed_period = '6M'
float_period = '3M'
elif currency == 'EUR':
fixed_period = '12M'
float_period = '6M'
- return YieldCurve(effective_date, types, periods, rates, 'ACT/360',\
+ return YieldCurve(effective_date, types, periods, rates, 'ACT/360',
fixed_period, float_period, '30/360', 'ACT/360',
BadDay.MODIFIED)
+
def ql_to_jp(ql_yc):
"""convert a QuantLib yield curve to a JP's one"""
if ql_yc._trait == BootstrapTrait.Discount:
@@ -190,21 +201,23 @@ def ql_to_jp(ql_yc):
trade_date = pydate_from_qldate(ql_yc.dates[0])
return YieldCurve.from_discount_factors(trade_date, dates, dfs, 'ACT/365F')
else:
- raise RuntimeErrror('QuantLib curve needs to use Discount trait')
+ raise RuntimeError('QuantLib curve needs to use Discount trait')
+
def build_curves(currency="USD"):
settings = Settings()
calendar = WeekendsOnly()
if currency == "USD":
- isda_ibor = IborIndex("IsdaIbor", Period(3, Months), 2, USDCurrency(), calendar,
- ModifiedFollowing, False, Actual360())
+ isda_ibor = IborIndex("IsdaIbor", Period(3, Months), 2, USDCurrency(),
+ calendar, ModifiedFollowing, False, Actual360())
fix_freq = Semiannual
elif currency == "EUR":
- isda_ibor = IborIndex("IsdaIbor", Period(6, Months), 2, EURCurrency(), calendar,
- ModifiedFollowing, False, Actual360())
+ isda_ibor = IborIndex("IsdaIbor", Period(6, Months), 2, EURCurrency(),
+ calendar, ModifiedFollowing, False, Actual360())
fix_freq = Annual
engine = dbengine('serenitasdb')
- rates = pd.read_sql_table('{}_rates'.format(currency.lower()), engine, index_col='effective_date')
+ rates = pd.read_sql_table('{}_rates'.format(currency.lower()), engine,
+ index_col='effective_date')
quotes = [SimpleQuote() for c in rates.columns]
gen = zip(quotes, rates.columns)
deps = [DepositRateHelper(q, Period(t), 2, calendar, ModifiedFollowing,
@@ -212,7 +225,7 @@ def build_curves(currency="USD"):
swaps = [SwapRateHelper.from_tenor(q, Period(t), calendar,
fix_freq, ModifiedFollowing,
Thirty360(), isda_ibor) for q, t in gen]
- sql_str = "INSERT INTO {}_curves VALUES(%s, %s) ON CONFLICT DO NOTHING".format(currency)
+ sql_str = f"INSERT INTO {currency}_curves VALUES(%s, %s) ON CONFLICT DO NOTHING"
conn = dbconn('serenitasdb')
for effective_date, curve_data in rates.iterrows():
print(effective_date)
@@ -221,15 +234,18 @@ def build_curves(currency="USD"):
q.value = val
valid_deps = [d for d in deps if not np.isnan(d.quote)]
valid_swaps = [s for s in swaps if not np.isnan(s.quote)]
- ql_yc = PiecewiseYieldCurve(BootstrapTrait.Discount, Interpolator.LogLinear,
- 0, calendar, valid_deps + valid_swaps, Actual365Fixed())
+ ql_yc = PiecewiseYieldCurve(BootstrapTrait.Discount,
+ Interpolator.LogLinear,
+ 0, calendar, valid_deps + valid_swaps,
+ Actual365Fixed())
jp_yc = ql_to_jp(ql_yc)
with conn.cursor() as c:
c.execute(sql_str, (effective_date, lz4.block.compress(jp_yc.__getstate__())))
conn.commit()
-if __name__=="__main__":
- #evaluation_date = Date(29, 4, 2014)
+
+if __name__ == "__main__":
+ # evaluation_date = Date(29, 4, 2014)
Settings.instance().evaluation_date = today()
import matplotlib.pyplot as plt