aboutsummaryrefslogtreecommitdiffstats
path: root/python/option_trades.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/option_trades.py')
-rw-r--r--python/option_trades.py54
1 files changed, 29 insertions, 25 deletions
diff --git a/python/option_trades.py b/python/option_trades.py
index 3010b5c4..0b1c76dd 100644
--- a/python/option_trades.py
+++ b/python/option_trades.py
@@ -6,7 +6,7 @@ import pandas as pd
from pandas.tseries.offsets import BDay
from arch import arch_model
-from db import dbengine
+from db import dbengine, dbconn
from scipy.interpolate import interp1d
from analytics import Index
@@ -55,6 +55,8 @@ def index_returns(date=None, years=3, index="IG", tenor="5yr"):
def realized_vol(index, series, tenor, date=None, years=None):
"""computes the realized spread volatility"""
if date is None:
+ if years is None:
+ raise ValueError("need to provide at least one of date or years")
date = (pd.Timestamp.now() - pd.DateOffset(years=years)).date()
returns = daily_spreads(index, series, tenor)
am = arch_model(returns)
@@ -179,18 +181,22 @@ def get_strike(index, series, date, expiry, conn):
return ref, fwdspread
def get_option_pnl(strike, expiry, index, series, start_date, engine):
- for s in [strike, strike+2.5]:
+ for s in [strike, strike+2.5, strike-2.5, strike+5]:
df = pd.read_sql_query("SELECT quotedate, (pay_bid+pay_offer)/2 AS pay_mid, " \
"(rec_bid+rec_offer)/2 AS rec_mid FROM swaption_quotes " \
"WHERE strike=%s and expiry=%s and index=%s and series=%s" \
"and quotedate>=%s", engine,
params=(s, expiry, index, series, start_date),
- index_col='quotedate', parse_dates=['quotedate'])
- if not df.empty and df.index[0] == start_date:
+ index_col='quotedate',
+ parse_dates=['quotedate'])
+ if not df.empty and df.index[0].date() == start_date:
strike = s
break
else:
- raise ValueError("Something wrong")
+ raise ValueError("Couldn't find data starting from that date")
+
+ if not pd.api.types.is_datetime64tz_dtype(df.index):
+ df.index = df.index.tz_localize('utc')
df = df.groupby(df.index.normalize()).last()
if expiry < datetime.date.today():
@@ -206,37 +212,32 @@ def get_option_pnl(strike, expiry, index, series, start_date, engine):
pv = underlying.pv
df = df.append(pd.DataFrame([[pay_mid, rec_mid]],
columns=['pay_mid', 'rec_mid'],
- index=[pd.Timestamp(expiry)]))
+ index=[pd.Timestamp(expiry, tz='UTC')]))
return df, strike
def sell_vol_strategy(index="IG", months=3):
engine = dbengine('serenitasdb')
conn = engine.raw_connection()
- with conn.cursor() as c:
- c.execute("SELECT DISTINCT ON (expiry) series, expiry FROM " \
- "swaption_quotes GROUP BY series, expiry ORDER BY expiry, series desc")
+ with conn.cursor() as c1, conn.cursor() as c2:
+ c1.execute("SELECT DISTINCT series, expiry FROM " \
+ "swaption_quotes ORDER BY expiry, series desc")
d = {}
- for series, expiry in c:
+ for series, expiry in c1:
start_date = BDay().rollback(expiry - pd.DateOffset(months=months)).date()
- if start_date == datetime.date(2016, 1, 15):
- start_date = datetime.date(2016, 1, 14)
- elif start_date == datetime.date(2014, 7, 18):
- start_date = datetime.date(2014, 7, 17)
- elif start_date == datetime.date(2014, 11, 17):
- start_date = datetime.date(2014, 11, 14)
- elif start_date == datetime.date(2015, 3, 13):
- start_date = datetime.date(2015, 3, 12)
if start_date > datetime.date.today():
break
- for s in [series, series - 1]:
- ref, fwdspread = get_index_ref(index, s, start_date, expiry, conn)
- if fwdspread is not None:
- break
- else:
+ c2.execute("SELECT max(quotedate::date) FROM swaption_quotes WHERE " \
+ "index=%s AND series=%s AND expiry=%s AND quotedate<=%s",
+ (index, series, expiry, start_date))
+ actual_start_date, = c2.fetchone()
+ if actual_start_date is None or (start_date - actual_start_date).days > 5:
continue
+ ref, fwdspread = get_index_ref(index, series, actual_start_date, expiry, conn)
+ if fwdspread is None:
+ fwdspread = ref + months / 50 #TODO: use actual values
strike = round(fwdspread/2.5) * 2.5
- pnl, strike = get_option_pnl(strike, expiry, index, s, start_date, engine)
- d[(s, strike, expiry)] = pnl
+ pnl, strike = get_option_pnl(strike, expiry, index, series, actual_start_date, engine)
+ d[(series, strike, expiry)] = pnl
conn.commit()
return d
@@ -277,3 +278,6 @@ if __name__ == "__main__":
d3 = sell_vol_strategy(months=3)
all_tenors = pd.concat([aggregate_trades(d) for d in [d1, d2, d3]], axis=1)
all_tenors.columns = ['1m', '2m', '3m']
+ all_tenors['optimal'] = ((1.2*all_tenors['1m']).
+ sub(1.2*all_tenors['2m'], fill_value=0).
+ add(all_tenors['3m'], fill_value=0))