-
Notifications
You must be signed in to change notification settings - Fork 968
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
bc02081
commit bcfb2f8
Showing
30 changed files
with
7,272 additions
and
18,072 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
167 changes: 167 additions & 0 deletions
167
gs_quant/content/reports_and_screens/00_fx/0000_vol_screen.ipynb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"pycharm": { | ||
"is_executing": true | ||
} | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"from gs_quant.data import Dataset\n", | ||
"from gs_quant.timeseries import percentiles, volatility, last_value, Returns\n", | ||
"from gs_quant.datetime import business_day_offset\n", | ||
"import seaborn as sns\n", | ||
"import pandas as pd\n", | ||
"pd.options.display.float_format = '{:,.2f}'.format \n", | ||
"import matplotlib.pyplot as plt\n", | ||
"from scipy import stats\n", | ||
"import warnings\n", | ||
"from datetime import date\n", | ||
"warnings.filterwarnings('ignore')\n", | ||
"sns.set(style=\"darkgrid\", color_codes=True)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"from gs_quant.session import GsSession\n", | ||
"# external users should substitute their client id and secret; please skip this step if using internal jupyterhub\n", | ||
"GsSession.use(client_id=None, client_secret=None, scopes=('run_analytics',)) " | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Screen Functions" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"def format_df(data_dict):\n", | ||
" df = pd.concat(data_dict, axis=1)\n", | ||
" df.columns = data_dict.keys()\n", | ||
" return df.fillna(method='ffill').dropna()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"pycharm": { | ||
"is_executing": true | ||
} | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"def volatility_screen(crosses, start_date, end_date, tenor='3m', history='2y', plot=True):\n", | ||
" #replace with premium dataset for more history\n", | ||
" fxspot_dataset, fxvol_dataset = Dataset('FXSPOT'), Dataset('FXIMPLIEDVOL')\n", | ||
" spot_data, impvol_data, spot_fx, data = {}, {}, {}, {}\n", | ||
" for cross in crosses:\n", | ||
" spot_fx[cross] = fxspot_dataset.get_data(start_date, end_date, bbid=cross)[['spot']].drop_duplicates(keep='last')['spot']\n", | ||
" spot_data[cross] = volatility(spot_fx[cross], tenor) # realized vol \n", | ||
" impvol_data[cross] = fxvol_dataset.get_data(start_date, end_date, bbid=cross, tenor=tenor, deltaStrike='DN', location='NYC')[['impliedVolatility']]* 100\n", | ||
"\n", | ||
" spdata, ivdata = format_df(spot_data), format_df(impvol_data)\n", | ||
" diff = ivdata.subtract(spdata).dropna()\n", | ||
" for cross in crosses:\n", | ||
" data[cross] = {'Spot': last_value(spot_fx[cross]),\n", | ||
" f'{tenor} Implied': last_value(ivdata[cross]),\n", | ||
" f'{tenor} Realized': last_value(spdata[cross]),\n", | ||
" 'Diff': last_value(diff[cross]),\n", | ||
" f'{history} Implied Low': min(ivdata[cross]),\n", | ||
" f'{history} Implied High': max(ivdata[cross]),\n", | ||
" '%-ile': last_value(percentiles(ivdata[cross]))\n", | ||
" }\n", | ||
" df = pd.DataFrame(data)\n", | ||
" vol_screen = df.transpose()\n", | ||
" \n", | ||
" if plot:\n", | ||
" for fx in vol_screen.index:\n", | ||
" plt.scatter(vol_screen.loc[fx]['%-ile'], vol_screen.loc[fx]['Diff'])\n", | ||
" plt.legend(vol_screen.index,loc='best', bbox_to_anchor=(0.9, -0.13), ncol=3)\n", | ||
" \n", | ||
" plt.xlabel('Percentile of Current Implied Vol')\n", | ||
" plt.ylabel('Implied vs Realized Vol')\n", | ||
" plt.title('Entry Point vs Richness')\n", | ||
" plt.show()\n", | ||
" return vol_screen.sort_values(by=['Diff']).style.background_gradient(subset=['Diff']).format(\"{:.1f}\")" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### FX Implied Volatility Screen\n", | ||
"Let's pull [GS FX Spot](https://marquee.gs.com/s/developer/datasets/FXSPOT) and [GS FX Implied Volatility](https://marquee.gs.com/s/developer/datasets/FXIMPLIEDVOL) and look at implied vs realized vol as well as current implied level as percentile relative to the last 2 years. Note, FX Spot uses GS NYC closes.\n", | ||
"\n", | ||
"\n", | ||
"If you are looking for additional history or coverage, please see our premium version [link](https://marquee.gs.com/s/developer/datasets/FXIMPLIEDVOL_PREMIUM).\n", | ||
"\n", | ||
"The FX Structuring team uses this analysis to screen for the most attractive vols to buy in the 3m tenor by looking at where implied trades in its own history and where realized trades in relationship with implieds.\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### Entry Point vs Richness\n", | ||
"\n", | ||
"Note: Lower left corner shows currencies with low and cheap vol. Upper right corner\n", | ||
"shows currencies with high and rich vol." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"from gs_quant.datetime import business_day_offset\n", | ||
"from dateutil.relativedelta import relativedelta\n", | ||
"g10 = ['USDJPY', 'EURUSD', 'AUDUSD', 'GBPUSD', 'USDCAD', 'USDNOK', 'NZDUSD', 'USDSEK', 'USDCHF']\n", | ||
"\n", | ||
"end = business_day_offset(date.today(), -1, roll='forward')\n", | ||
"start = business_day_offset(end - relativedelta(years=2), -1, roll='forward')\n", | ||
"\n", | ||
"tenor = '3m'\n", | ||
"history = '2y'\n", | ||
"\n", | ||
"screen = volatility_screen(g10, start, end, tenor, history, plot=True)\n", | ||
"screen" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.7.4" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 4 | ||
} |
Oops, something went wrong.